Box2D Get Bounding Box of a Body

12

En Box2D, tenía curiosidad por saber si es posible obtener una caja delimitadora de un cuerpo ya creado en el mundo.

Básicamente, el Cuerpo se crea, está interactuando con el mundo y demás. Y necesitaba la caja de límite de ese cuerpo. ¿Es posible?

Colin Gislason
fuente

Respuestas:

11

En Box2D, los cuerpos no tienen cuadros delimitadores asociados con ellos, el accesorio sí. Por lo tanto, debe iterar sobre todos los accesorios y generar un nuevo AABB. Algo como esto:

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
fuente
1
¿Es esto realmente correcto? En el box2d que estoy usando, fixture->GetAABB()no existe, pero fixture->GetAABB(int32 childIndex)sí.
Jonny
¿son las esquinas superior e inferior de las esquinas superior e inferior?
jokoon
1

simplemente usar el dispositivo aabb también incluye el radio de la forma; si desea obtener el aabb real sin el radio de la forma, hágalo así:

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
fuente
¿Por qué no querrías obtener el radio de la forma? Originalmente copié la fuente de esta respuesta, pensando que era más exhaustiva que las otras respuestas, pero ahora he descubierto que no es correcta para mi caso, y tengo curiosidad sobre en qué escenario se debe usar este código.
Mitch
Sin embargo, veo que esto usa la API Box2D más nueva. Esa es una razón para preferir esta respuesta. Sin embargo, en relación con lo que mencioné anteriormente, tuve que comentar shapeAABB.lowerBound = shapeAABB.lowerBound + r;y shapeAABB.upperBound = shapeAABB.upperBound - r;obtener el comportamiento que quería.
Mitch
0

Realmente, un bucle for suele ser mejor para la iteración. Tomando la respuesta 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());
}

La expresión fixture, tomada como booleana, es, entiendo, equivalente a fixture != NULL.

GKFX
fuente
0

Esto es lo que generalmente 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);

Donde este es un nodo padre. Incluso he agregado esto al nodo en sí (por ejemplo, someNode) y eso también parece funcionar, solo asegúrese de que su índice z sea lo suficientemente alto.

nikc
fuente