Box2D получить ограничивающую коробку тела

12

В Box2D мне было любопытно, можно ли получить ограничивающий прямоугольник тела, уже созданного в мире.

Итак, в основном, Тело создано, оно взаимодействует с миром и тому подобное. И мне нужна была ограничительная коробка этого Тела. Является ли это возможным?

Колин Гисласон
источник

Ответы:

11

В Box2D тела не имеют связанных с ними ограничительных рамок, как у прибора. Поэтому вам нужно перебрать все приборы и сгенерировать новый AABB. Что-то вроде этого:

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
Это действительно правильно. В box2d я использую, fixture->GetAABB()не существует, но есть fixture->GetAABB(int32 childIndex).
Джонни,
верхний и нижний верхний и прямой углы?
Jokoon
1

просто использование приспособления aabb также включает радиус формы - если вы хотите получить реальное aabb без радиуса формы, сделайте это следующим образом:

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();
}
Мартин Герхарди
источник
Почему бы вам не захотеть получить радиус формы? Первоначально я скопировал исходный код из этого ответа, думая, что он более тщательный, чем другие ответы, но теперь я обнаружил, что это не правильно для моего случая, и мне любопытно, в каком сценарии должен использоваться этот код.
Митч
Я вижу, что здесь используется более новый API Box2D. Это одна из причин, чтобы предпочесть этот ответ. Однако, в связи с тем, что я упомянул выше, я должен был закомментировать shapeAABB.lowerBound = shapeAABB.lowerBound + r;и shapeAABB.upperBound = shapeAABB.upperBound - r;получить то поведение, которое хотел.
Митч
0

Действительно, цикл for обычно лучше для итерации. Принимая ответ @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());
}

Выражение fixture, взятое как логическое, я понимаю, эквивалентно fixture != NULL.

GKFX
источник
0

Это то, что я обычно использую:

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

Где это какой-то родительский узел. Я даже добавил это к самому узлу (например, someNode), и это также, кажется, работает, просто убедитесь, что ваш z-индекс достаточно высок.

nikc
источник