Box2D Uzyskaj obwiednię ciała

12

W Box2D byłem ciekawy, czy można uzyskać obwiednię ciała już utworzonego na świecie.

Zasadniczo Ciało jest tworzone, wchodzi w interakcje ze światem i tym podobne. Potrzebowałem obwiedni tego Ciała. Czy to możliwe?

Colin Gislason
źródło

Odpowiedzi:

11

W Box2D obiekty nie są powiązane z ramkami ograniczającymi, tak jak urządzenia. Musisz więc iterować wszystkie urządzenia i wygenerować nowy AABB. Coś takiego:

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
źródło
1
Czy to naprawdę poprawne? W box2d, którego używam, fixture->GetAABB()nie istnieje, ale istnieje fixture->GetAABB(int32 childIndex).
Jonny
czy górne i dolne są górne i dolne rogi?
Jokoon
1

samo użycie urządzenia aabb obejmuje również promień kształtu - jeśli chcesz uzyskać prawdziwy aabb bez promienia kształtu, zrób to w następujący sposób:

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
źródło
Dlaczego nie chcesz uzyskać promienia kształtu? Pierwotnie skopiowałem źródło z tej odpowiedzi, myśląc, że było dokładniejsze niż inne odpowiedzi, ale teraz odkryłem, że nie jest ono właściwe dla mojego przypadku i jestem ciekawy, w którym scenariuszu należy użyć tego kodu.
Mitch
Widzę jednak, że używa to nowszego interfejsu API Box2D. To jeden z powodów, dla których wolę tę odpowiedź. Jednak w związku z tym, o czym wspomniałem powyżej, musiałem się wypowiedzieć shapeAABB.lowerBound = shapeAABB.lowerBound + r;i shapeAABB.upperBound = shapeAABB.upperBound - r;uzyskać pożądane zachowanie.
Mitch
0

Naprawdę, pętla for jest zwykle lepsza do iteracji. Biorąc odpowiedź @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());
}

fixtureRozumiane jako logiczne wyrażenie jest, jak rozumiem, równoważne z fixture != NULL.

GKFX
źródło
0

Tego zazwyczaj używam:

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

Gdzie jest to jakiś węzeł nadrzędny. Dodałem to nawet do samego węzła (np. SomeNode) i to również wydaje się działać, po prostu upewnij się, że twój indeks Z jest wystarczająco wysoki.

nikc
źródło