Box2D Get Bounding Box of a Body

12

Dans Box2D, j'étais curieux de savoir s'il était possible d'obtenir une boîte englobante d'un corps déjà créé dans le monde.

Donc, fondamentalement, le corps est créé, il interagit avec le monde et autres. Et j'avais besoin de la boîte englobante de ce corps. C'est possible?

Colin Gislason
la source

Réponses:

11

Dans Box2D, les corps n'ont pas de boîtes englobantes qui leur sont associées, les luminaires en ont. Vous devez donc parcourir tous les appareils et générer un nouvel AABB. Quelque chose comme ça:

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();
}
Noel Llopis
la source
1
Est-ce vraiment correct? Dans le box2d que j'utilise, fixture->GetAABB()n'existe pas, mais existe fixture->GetAABB(int32 childIndex).
Jonny
les virages supérieur et inférieur sont-ils les coins supérieur et droit?
jokoon
1

juste utiliser le luminaire aabb inclut également le rayon de la forme - si vous voulez obtenir le vrai aabb sans le rayon de la forme, faites-le comme ceci:

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();
}
Martin Gerhardy
la source
Pourquoi ne voudriez-vous pas obtenir le rayon de forme? J'ai initialement copié la source de cette réponse, pensant qu'elle était plus approfondie que les autres réponses, mais maintenant j'ai trouvé que ce n'est pas correct pour mon cas, et je suis curieux de savoir dans quel scénario ce code devrait être utilisé.
Mitch
Je vois que cela utilise la nouvelle API Box2D, cependant. C'est une raison de préférer cette réponse. Cependant, par rapport à ce que j'ai mentionné ci-dessus, j'ai dû commenter shapeAABB.lowerBound = shapeAABB.lowerBound + r;et shapeAABB.upperBound = shapeAABB.upperBound - r;obtenir le comportement que je voulais.
Mitch
0

Vraiment, une boucle for est généralement meilleure pour l'itération. Prendre la réponse de @noel:

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());
}

L'expression fixture, prise comme booléenne, est, je comprends, équivalente à fixture != NULL.

GKFX
la source
0

C'est ce que j'utilise généralement:

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);

Où il s'agit d'un nœud parent. J'ai même ajouté cela au nœud lui-même (par exemple someNode) et cela semble également fonctionner, assurez-vous simplement que votre z-index est suffisamment élevé.

nikc
la source