Box2D obter caixa delimitadora de um corpo

12

No Box2D, fiquei curioso para saber se é possível obter uma caixa delimitadora de um corpo já criado no mundo.

Então, basicamente, o Corpo é criado, está interagindo com o mundo e tal. E eu precisava da caixa delimitadora do Corpo. É possível?

Colin Gislason
fonte

Respostas:

11

No Box2D, os corpos não têm caixas delimitadoras associadas a eles, o equipamento possui. Então, você precisa iterar sobre todos os equipamentos e gerar um novo AABB. Algo assim:

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
fonte
1
Isso é realmente correto? No box2d que estou usando, fixture->GetAABB()não existe, mas existe fixture->GetAABB(int32 childIndex).
quer
são superior e inferior os cantos esquerdo e direito?
Jokoon #
1

O simples uso do acessório aabb também inclui o raio da forma - se você deseja obter o verdadeiro aabb sem o raio da forma, faça o seguinte:

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
fonte
Por que você não deseja obter o raio da forma? Originalmente, copiei a fonte desta resposta, pensando que era mais completa do que as outras respostas, mas agora descobri que não é o correto para o meu caso e estou curioso para saber em que cenário esse código deve ser usado.
Mitch
Vejo que isso usa a API Box2D mais recente. Essa é uma razão para preferir esta resposta. No entanto, relacionado ao que mencionei acima, tive que comentar shapeAABB.lowerBound = shapeAABB.lowerBound + r;e shapeAABB.upperBound = shapeAABB.upperBound - r;obter o comportamento que queria.
Mitch
0

Realmente, um loop for geralmente é melhor para iteração. Tomando a resposta 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());
}

A expressão fixture, tomada como booleana, é, eu entendo, equivalente a fixture != NULL.

GKFX
fonte
0

Isto é o que eu geralmente uso:

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

Onde este é algum nó pai. Eu até adicionei isso ao próprio nó (por exemplo, someNode) e isso também parece funcionar, apenas verifique se o seu z-index está alto o suficiente.

nikc
fonte