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?

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

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

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.


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é.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.