Mirroring Box2D shape

899 views Asked by At

I use the following code to flip the shape. When I flip along x or y, it appears that shape is flipped.

b2FixtureDef fixd = fix->fixture;
const b2Shape *shape = fixd.shape;
if(shape->GetType()== b2Shape::e_polygon && flip)
{
        b2PolygonShape* ps = (b2PolygonShape*)shape;
        for(int i=0;i<ps->m_vertexCount;i++)
        {
            ps->m_vertices[i].x *= -1;
            //ps->m_vertices[i].y *= -1; // causing assert later
        }

        // revert the vertices
        b2Vec2* reVert = new b2Vec2[ps->m_vertexCount];
        int j = ps->m_vertexCount -1;
        for(int i=0; i<ps->m_vertexCount;i++)
            reVert[i] = ps->m_vertices[j--];

        ps->Set(&reVert[0], ps->m_vertexCount);
        body->CreateFixture(ps, 1.0f);
}

But if I flip x and y together I get an assertion b2PolygonShape.cpp, because area is negative.

// Centroid
b2Assert(area > b2_epsilon);

I'm not sure how else to flip both x and y. I need to mirror the shape and Box2D forum says

To mirror a polygon, mirror every vertex, then reverse the order of the vertices. I'm already considering adding a method for this.

2

There are 2 answers

1
godel9 On BEST ANSWER

If you flip across both the x and y axes, then you don't need to reverse the order of the vertices.

Think of it this way... If you flip across both axes, then you're basically flipping across the x axis and then the y axis. If you reverse the vertices each time you flip across an axis, you've reversed the vertices twice, and you end up with the same order you started out with.

1
FuzzyBunnySlippers On

Previous to version 2.3.0, Box2d requires a counter-clockwise winding order for all vertices.

When you mirror the vertices, you are reversing the order of the winding.

I believe this has been corrected in 2.3.0 (see here). So I believe you can either (1) reverse the order after you mirror them or (2) upgrade to the latest version of Box2d.

For option 1, for example, I had previously created a square using a polyshape (for this project)

   // Main Box
   vertices.clear();
   vertices.push_back(Vec2(1*VERT_SCALE,1*VERT_SCALE));
   vertices.push_back(Vec2(-1*VERT_SCALE,1*VERT_SCALE));
   vertices.push_back(Vec2(-1*VERT_SCALE,-1*VERT_SCALE));
   vertices.push_back(Vec2(1*VERT_SCALE,-1*VERT_SCALE));
   polyShape.Set(&vertices[0],vertices.size());
   _body->CreateFixture(&fixtureDef);

The vertices are in order of (1,1), (-1,1), (-1,-1), (1,-1). Or: Top Right, Top Left, Bottom Left, Bottom Right.

This is counterclockwise order.

If you mirror these, you get: Top Left, Top Right, Bottom Right, Bottom Left

This is clockwise order.

If you reverse them, you get:

Bottom Left, Bottom Right, Top Right, Top Left

Which I believe is clockwise again. I believe (but I'm not certain...not enough coffee yet) that this will work for any convex polygon.

NOTE I used a std::vector for vertices. You can reverse it using this.

Was this helpful?