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?
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();
}
fixture->GetAABB()
does not exist, but a fixture->GetAABB(int32 childIndex)
does.
\$\endgroup\$
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();
}
shapeAABB.lowerBound = shapeAABB.lowerBound + r;
and shapeAABB.upperBound = shapeAABB.upperBound - r;
to get the behaviour that I wanted.
\$\endgroup\$
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
.
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.