7
votes

Hey i'm trying to integrate SFML and Box2D, and SFML has made setting centers for sprites, shapes, etc. very easy. Box2D, on the other hand, I'm having trouble with as i can't figure out how to set or even find the center of a shape or fixture.

It seems to me that when adding vertices manually to a b2_PolygonShape the center is set to the first vertex in the vertex array, but the results are very different when using the shortcut functions SetAsBox() or any other SetAs__(). The Center is the middle of the shape, or half extent(s) of the box/shape.

I need to commonize box2D's and SFML's centering system, but i can't figure out how the local coordinate systems work for objects.

How do I set/get the centers of the many objects such as shapes, fixtures, bodies, etc. in Box2D?

5
what do you mean by a center of b2body? The center of mass?Andrew
the center that is used for positioning in the Global, World coordinate system. Not the local body coordinate system which i assume is used to position fixtues on a body.Griffin

5 Answers

4
votes

Ok I realized that SFML and Box2D really weren't all that different, but i just wasn't thinking about how shapes are made/ rendered correctly in world coordinates.

Unless otherwise specified, (0,0) is always used as the refrence point/ center of the object when its position is being moved around/ drawn, and each vertex is drawn in relation to that point.

the SFML tutorial was a bit confusing as it said setting the center of a shape/sprite was the offset from the top left corner of the object, not (0,0).

2
votes

I think that with box2d you are responsible of making the 'centroid' of the polygon coincide with the position of your body. Basically what you have to do is something like this.

  • Compute the centroid of your list of vertices (b2vec)

  • Shift the vertices by -centroid.

Box2d provides the necessary functions to help you with this task. What happens with SetAs__ is that the centroid is (0,0) and the polygon is created symmetrically around the center of the body.

1
votes

I'll give it another try. I'm pretty sure I can help you but I don't understand your question completely.

A body has a Position (b2Vec2) in the world.
A body has b2Fixtures (density, friction, restitution, shape, etc...)
The b2PolygonShape has vertices and mass data. Those vertices are relative to the body position.

Example vertices for a b2PolgygonShape (rectangle, size: 1 meter * 1 meter)

(-0.5f, -0.5f)  // left  upper corner
( 0.5f, -0.5f)  // right upper corner
( 0.5f,  0.5f)  // right lower corner
(-0.5f,  0.5f)  // left  lower corner

Keep in mind you can't set the vertices yourself! You have to pass them to

b2PolgygonShape::Set(b2Vec2 *vertices, int count);

This method will compute the mass data, depending on the vertices.

0
votes

This is maybe related, though I'm using Box2DWeb and Easel.js rather than Box2D and SFML. The issue I encountered is that the Easel.js regX/regY (the graphical center of the sprite) needs to match the physical center of mass.

For a simple b2Body with one b2FixtureDef, the center of mass of the body coincides with the m_centroid of the b2FixtureDef.shape (whether SetAsBox, SetAsArray, new b2CircleShape, etc).

For multi-fixture bodies and irregular polygons, what worked for me was to add all fixtures (i.e. call b2Body.CreateFixture), then set the graphic regX/regY equal to the b2Body.m_sweep.localCenter.x/y (multiplied by the pixels/meter scale factor).

This didn't work for simple circles and boxes, but they weren't a problem in the first place. Hope this helps.

-1
votes

You can simply do this:

b2Body *body = ...;
b2Vec2 pos = body->GetPosition();

This is the body position in the world (pos.x and pos.y, defined in meters). This means you have to use a ratio, eg: 1 meter = 20 pixels. So you have to multiply the coordinates by your ratio to get the position in pixels.

Use that position to draw your images. If needed you can add coordinates to your image and draw the image on these coordinates relative to the body position.

Keep in mind that you have to draw your images as well with that ratio. When the ratio changes (zoom in or zoom out), the images should enlarge as well.

For my game, I'm using SDL with OpenGL, which is a very nice combination, so I don't know exactly how SFML works.