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\$
11
\$\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\$
  • 1
    \$\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 '13 at 1:27
  • \$\begingroup\$ are upperbound and lowerbound the topleft and downright corners ? \$\endgroup\$ – jokoon May 10 '13 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\$
  • \$\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 '15 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 '15 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\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy