Slicing, splitting and cutting objects with Box2D – part 2

Here we are with the second part of the Box2D splitter engine. In the first part of this tutorial we managed to find laser entry and exit points, now it’s time to make the laser cut the object.

In just three steps, we’ll have our object splitted, so let’s start:

Finding the centre of the laser ray

In this step we need to find the center of the laser ray inside the object. In other words, if we consider the segment going from the entry point to the exit point, we must find its centre point. This will help us a lot in the slicing process.

This is quite easy, although we have to modify a bit laserFired function

First, we added two new class level variables:

Line 15: affectedByLaser is a b2Body vector which will store all bodies affected by the laser

Line 16: entryPoint is a b2Vec2 vector which will store all entry points generated by the laser

Now let’s look at the new laserFired function (lines 101-114).

Now it’s not simply a matter of drawing a circle, we have to distinguish entry point from exit point as it could be useful if you want to add two different graphical effects, one for the entry point and one for the exit point, keep track of all bodies affected by the laser ray and finding the centre of each laser segment which is cutting the body.

Line 102: creates a b2Body variable called affectedBody which gets the body touched by the laser ray starting from the given fixture with getBody method.

Line 103: creates a variable called fixtureIndex which, using indexOf method, will tell us if affectedBody is already inside affectedByLaser vector.

Line 104: if fixtureIndex is equal to -1 we know affectedBody is not inside affectedByLaser vector, so we can say it’s the first time the laser hits affectedBody, and obviously we must be dealing with the entry point.

Lines 105-106: push both the affected body and the intersection point in affectedByLaser and entryPoint vectors respectively.

Line 107: what happens if fixtureIndex is different than -1? This means it’s not the first time we meet affectedBody, and this suggests us two things: it’s an exit point and affectedBody is spliced by the laser.

Line 108: draws the entry point

Line 109: draws the exit point

Line 110: finds the centre of the segment going from the entry point to the exit point

Lines 11: draws the centre point

And this is the result:

Try to slice bodies with the laser.

Now only bodies entirely sliced by the laser have entry, exit and centre points. In all other cases, when the laser intersects the body in just one point, we don’t do anything since the body is not sliced.

Entry point is marked with red, exit point with yellow and the centre with orange.

Defining new polygons vertices

Before you split the body in two, you have to know which vertices will be part of the first slice and wich ones will be part of the second slice.

How can we do it? The concept is simple: assuming the laser is an axis, all the vertices above such axis are part of a slice, and all the vertices below the axis are part of another slice. Both slices will also have laser entry and exit points among their vertices.

Time to add some code to laserFired function:

Line 112: rayAngle is the angle of the laser segment which slices the polygon

Line 114: populates polyVertices vector with all affectedPolygon vertices thanks to GetVertices() method.

Line 115: looping through all vertices. It’s time to see which ones will be part of the first slice, and which ones will be part of the second slice.

Line 116: worldPoint is a b2Vec2 variable which gets the vertex coordinates thanks to GetWorldPoint method

Line 117: the core of the script: cutAngle variable is the angle of the vertex using the laser as reference axis. This is when the centre of the laser segment comes into play.

Lines 121-125: each vertex is marked with a white or a black point according to its angle.

Now we can spot the vertices of the new slices:

Try to cut an object and you will see the vertices of the new slices marked in black and white.

Finally we can split the objects!

Splitting objects

Although this is the last step, it’s not the easiest… we can say it’s the hardest. But we’ll manage to have our objects sliced.

First, some theory. As you can see from the previous movie, it’s easy to visually find the vertices of the new slices: one is made by all white vertices and the entry and exit laser points, and another is made by all black vertices and the entry and exit laser points.

Putting it into coding is a bit more complicated because Box2D wants polygon vertices to be defined in clockwise order. In most sites and forums you may read it wants it into counter clockwise order, but they are wrong. Or, at least, they are wrong when talking about Box2D and Flash.

So the idea is: create one slice with the white points in clockwise order and append the exit and the entry laser points, and the other slice with black points in clockwise order and append the entry and exit laser points. Notice how laser points order is inverted when I switch from “white” to “black” slice.

Let’s see the whole script:

As usual, laserFired function does the hard job, saving the vertices of the new polygons in two vectors called newPolyVertices1 and newPolyVertices2 declared at lines 112-113.

Lines 117-149 populate such vectors with the vertices of each slice in a “not that smart” way as I am using a bunch of useless variables, so feel free to change and optimize this part of code.

Anyway, once we have the vectors populated with all vertices, lines 150 and 151 call createSlice function I will explain in a moment and finally we can remove the body we just sliced with DestroyBody method at line 152.

Now let’s talk about createSlice function, which takes two arguments: the vector of vertices forming the slice and the length of such vectors. And, at the time of writing, I recognize it’s a bit having two arguments when the second argument can be obtained starting from the first one.

Anyway… at line 180 I am finding the centroid of the slice. findCentroid function is the copy/paste of the protected ComputeCentroid function you can find in file.

Lines 181-183: once I have the centroid, I have to transform vertices coordinates from absolute in the Box2D world into relative to the centroid.

Lines 184-193: create the body from a vector of points thanks to SetAsVector method at line 188.

Finally, since the new slices share two points (the entry and the exit laser points), and such points are passed by reference, I have to restore the coordinates from relative to absolute at lines 194-196.

And that’s it!!!

Finally you can cut the objects.

But it’s not over yet, now we have to get rid of the debug draw and skin objects. I will explain how to do it soon, meanwhile download the source code of all examples.

  • daniel

    thank you!

  • Wow. That’s an extraordinary example. Bravo.

  • MC

    Great! i would love to see how you manage to skin sliced parts!

  • Scott

    Very cool demo. You can slice the floor and have it drop away too :P

  • Olivier

    Great! I have made my own slicing engine too with box2D and it works pretty well except for cutting dynamic bodies but i figured out how to fix it. The next tricky part is to integrate textures and redraw bitmaps after cuttin them…
    I’m lookin on your source code to see how to improve mine

  • good demo. Thanks for shearing!

  • Alexandre Colella

    Man, very good!
    Write a book about Box2D and Flash!!!! Please!!!

  • Great ! Thank you !

  • Good article! But I has implemented your old cutting algorithm, but with using new raycasting methods. And already was implemented cut of textures, it not so hard as look at first time. All what you need, is to create rectangle(polygon) for texture coordinates and cut it, as you cutted your polygon. And as last step, draw cutted polygon with material texture.

  • Perfect!
    Thank You!!!

  • Edanna

    I’ve made a such engine without using raycasting, because I found this function not documented enough.

    Box2D has a few issues with tiny cutted pieces : they bounce, bounce and bounce again and aren’t realistic at all (It happens also with your exemple).
    (my cutting engine had this problem too, so I remove little pieces when they touch the ground).

    Do you know the reason ?

  • Emanuele Feronato

    I would say because of they tiny mass they get an wrong restitution.

  • AC

    @Jason – my word, that was dreadful. Well done.

  • Edanna

    @Emanuele : excellent ! Instead of deleting them, I set their restitution to zero. It works !!!

  • I sliced those boxes to little pieces… AWESOME TUTORIAL!

  • Colin Douch

    You could transfer velocities to sliced pieces aswell, as, if you cut a piece in mid air, the velocities will be reset…

  • alex

    so cool!!!

  • extraordinary physics, sure.

    congratz :)

  • Pingback: links for 2011-07-23 « ???????()

  • James

    Great stuff!

    Just a suggestion: with multipart posts, it would be really great if you also included a ‘next part’ link (either near the end or top).

    Would be a nice timesaver.

  • sir am using flash cs3….this idea was gud but it shows some error in vector……

    pls rectify tht errors

  • macfriday

    awesome! thank u

  • marcin

    Hi thanks for great art !

    but i can’t to find getVertices() function in Box2d

    this line:


    ther is no function whih returning Vector2 set

    please help

  • marcin

    hmmm ok i rewrote this code in java and for me there is a mistake in code…

    there is :
    if (fixtureIndex==-1) {
    } else {
    var rayCenter:b2Vec2=new b2Vec2((point.x+entryPoint[fixtureIndex].x)/2,(point.y+entryPoint[fixtureIndex].y)/2);

    should be

    if (fixtureIndex==-1) {
    } else {
    var rayCenter:b2Vec2=new b2Vec2((point.x+entryPoint[fixtureIndex].x)/2,(point.y+entryPoint[fixtureIndex].y)/2);

  • sus

    You’re great!!
    Thanks for the tutorial :)

  • Hi Emanuele,

    Great article! It was fun to slice stuff. But can you make tutorial or give some examples how to slice circle object. Because circle objects have b2CircleShape and that class naturally do not have GetVertices() method and so I am not really sure how to implement it without vertices.

    Thanks :)

  • macaan

    Thanks a lot for this, I used it within the Citrusengine. Next step will be some texture, here is a demo with debug mode: ctrl:shoot(restart shooting for new slices)

    I’m looking forward how you will solve it, cheers