Box2D Bounding Box eines Körpers erhalten

12

In Box2D war ich neugierig, ob es möglich ist, einen Begrenzungsrahmen eines Körpers zu erhalten, der bereits in der Welt erstellt wurde.

Im Grunde genommen ist der Körper geschaffen, er interagiert mit der Welt und so weiter. Und ich brauchte den Begrenzungsrahmen dieses Körpers. Ist es möglich?

Colin Gislason
quelle

Antworten:

11

In Box2D sind Körpern keine Begrenzungsrahmen zugeordnet, Fixture do. Sie müssen also alle Fixtures durchlaufen und einen neuen AABB generieren. Etwas wie das:

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
quelle
1
Ist das wirklich richtig? In der Box2D die ich benutze, fixture->GetAABB()gibt es nicht, aber eine fixture->GetAABB(int32 childIndex)tut es.
Jonny
sind die oberen und unteren linken und rechten Ecken oben und unten gebunden?
jokoon
1

Wenn Sie nur das Fixture aabb verwenden, wird auch der Formradius berücksichtigt. Wenn Sie den echten Aabb ohne den Radius der Form erhalten möchten, gehen Sie folgendermaßen vor:

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
quelle
Warum möchten Sie den Formradius nicht erhalten? Ich habe die Quelle ursprünglich aus dieser Antwort kopiert und dachte, sie sei gründlicher als die anderen Antworten, aber jetzt habe ich festgestellt, dass sie für meinen Fall nicht korrekt ist, und bin gespannt, in welchem ​​Szenario dieser Code verwendet werden sollte.
Mitch,
Ich sehe, dass dies die neuere Box2D-API verwendet. Das ist ein Grund, diese Antwort vorzuziehen. Im Zusammenhang mit dem, was ich oben erwähnte, musste ich jedoch einen Kommentar abgeben shapeAABB.lowerBound = shapeAABB.lowerBound + r;und shapeAABB.upperBound = shapeAABB.upperBound - r;das Verhalten erhalten, das ich wollte.
Mitch
0

Wirklich, eine for-Schleife ist normalerweise besser für die Iteration. Antwort von @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());
}

fixtureIch verstehe, der Ausdruck , der als boolescher Ausdruck verstanden wird, ist äquivalent zu fixture != NULL.

GKFX
quelle
0

Dies ist, was ich im Allgemeinen benutze:

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

Wobei dies ein übergeordneter Knoten ist. Ich habe dies sogar zum Knoten selbst hinzugefügt (z. B. someNode), und das scheint auch zu funktionieren. Stellen Sie nur sicher, dass Ihr Z-Index hoch genug ist.

nikc
quelle