12
\$\begingroup\$

In Box2D, I was curious if it's possible to get a bounding box of a body already created in the world.

So basically, the Body is created, it's interacting with the world and such. And I needed that Body's bounding box. Is it possible?

\$\endgroup\$

4 Answers 4

10
\$\begingroup\$

In Box2D, bodies don't have bounding boxes associated with them, fixture do. So you need to iterate over all the fixtures and generate a new AABB. Something like this:

b2AABB aabb;
aabb.lowerBound = b2Vec2(FLT_MAX,FLT_MAX);
aabb.upperBound = b2Vec2(-FLT_MAX,-FLT_MAX); 
b2Fixture* fixture = body->GetFixtureList();
while (fixture != NULL)
{
    aabb.Combine(aabb, fixture->GetAABB());
    fixture = fixture->GetNext();
}
\$\endgroup\$
2
  • 2
    \$\begingroup\$ Is this really correct. In the box2d I am using, fixture->GetAABB() does not exist, but a fixture->GetAABB(int32 childIndex) does. \$\endgroup\$
    – Jonny
    Apr 4, 2013 at 1:27
  • \$\begingroup\$ are upperbound and lowerbound the topleft and downright corners ? \$\endgroup\$
    – jokoon
    May 10, 2013 at 13:22
1
\$\begingroup\$

just using the fixture aabb also includes the shape radius - if you want to get the real aabb without the radius of the shape, do it like this:

b2AABB aabb;
b2Transform t;
t.SetIdentity();
aabb.lowerBound = b2Vec2(FLT_MAX,FLT_MAX);
aabb.upperBound = b2Vec2(-FLT_MAX,-FLT_MAX); 
b2Fixture* fixture = body->GetFixtureList();
while (fixture != nullptr) {
     const b2Shape *shape = fixture->GetShape();
     const int childCount = shape->GetChildCount();
     for (int child = 0; child < childCount; ++child) {
            const b2Vec2 r(shape->m_radius, shape->m_radius);
            b2AABB shapeAABB;
            shape->ComputeAABB(&shapeAABB, t, child);
            shapeAABB.lowerBound = shapeAABB.lowerBound + r;
            shapeAABB.upperBound = shapeAABB.upperBound - r;
            aabb.Combine(shapeAABB);
    }
    fixture = fixture->GetNext();
}
\$\endgroup\$
2
  • \$\begingroup\$ Why would you not want to get the shape radius? I originally copied the source from this answer, thinking it was more thorough than the other answers, but now I've found that it's not correct for my case, and am curious about which scenario this code should be used in. \$\endgroup\$
    – Mitch
    Jul 11, 2015 at 12:08
  • \$\begingroup\$ I see that this uses the newer Box2D API, though. That's one reason to prefer this answer. However, related to what I mentioned above, I had to comment out shapeAABB.lowerBound = shapeAABB.lowerBound + r; and shapeAABB.upperBound = shapeAABB.upperBound - r; to get the behaviour that I wanted. \$\endgroup\$
    – Mitch
    Jul 11, 2015 at 12:10
0
\$\begingroup\$

Really, a for loop is usually better for iteration. Taking @noel 's answer:

b2AABB aabb;
aabb.lowerBound = b2Vec2(FLT_MAX,FLT_MAX);
aabb.upperBound = b2Vec2(-FLT_MAX,-FLT_MAX); 
for (b2Fixture* fixture = body->GetFixtureList(); fixture; fixture = fixture->GetNext())
{
    aabb.Combine(aabb, fixture->GetAABB());
}

The expression fixture, taken as boolean, is, I understand, equivalent to fixture != NULL.

\$\endgroup\$
0
\$\begingroup\$

This is what I generally use:

Rect aabb = someNode->getBoundingBox();
DrawNode* drawNode = DrawNode::create();
drawNode->drawRect(aabb.origin, aabb.origin + aabb.size, Color4F(1, 0, 0, 1));
this->addChild(drawNode, 100);

Where this is some parent node. I've even added this to the node itself (e.g. someNode) and that also seems to work, just make sure your z-index is high enough.

\$\endgroup\$

You must log in to answer this question.