Box2D Nhận Bounding Box of a Body


12

Trong Box2D, tôi đã tò mò liệu có thể lấy một hộp giới hạn của một cơ thể đã được tạo ra trên thế giới hay không.

Về cơ bản, Cơ thể được tạo ra, nó tương tác với thế giới và như vậy. Và tôi cần cái hộp giới hạn của Cơ thể đó. Có thể không?

Câu trả lời:


11

Trong Box2D, các cơ quan không có các hộp giới hạn liên kết với chúng, vật cố định làm. Vì vậy, bạn cần lặp đi lặp lại tất cả các đồ đạc và tạo AABB mới. Một cái gì đó như thế này:

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
Điều này thực sự chính xác. Trong box2d tôi đang sử dụng, fixture->GetAABB()không tồn tại, nhưng fixture->GetAABB(int32 childIndex)có.
Jonny

phía trên và phía dưới góc trên và góc dưới?
jokoon

1

chỉ cần sử dụng vật cố aabb cũng bao gồm bán kính hình dạng - nếu bạn muốn có được aabb thật mà không có bán kính của hình dạng, hãy làm như thế này:

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

Tại sao bạn không muốn có được bán kính hình dạng? Ban đầu tôi đã sao chép nguồn từ câu trả lời này, nghĩ rằng nó kỹ lưỡng hơn các câu trả lời khác, nhưng bây giờ tôi thấy rằng nó không đúng với trường hợp của tôi và tò mò về kịch bản nào nên sử dụng mã này.
Mitch

Tuy nhiên, tôi thấy rằng điều này sử dụng API Box2D mới hơn. Đó là một lý do để thích câu trả lời này. Tuy nhiên, liên quan đến những gì tôi đã đề cập ở trên, tôi đã phải bình luận shapeAABB.lowerBound = shapeAABB.lowerBound + r;shapeAABB.upperBound = shapeAABB.upperBound - r;để có được hành vi mà tôi muốn.
Mitch

0

Thực sự, một vòng lặp for thường tốt hơn cho việc lặp lại. Lấy câu trả lời của @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());
}

Biểu thức fixture, được coi là boolean, là, tôi hiểu, tương đương với fixture != NULL.


0

Đây là những gì tôi thường sử dụng:

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

Đây là một số nút cha. Tôi thậm chí đã thêm nó vào nút (ví dụ: someNode) và nó dường như cũng hoạt động, chỉ cần đảm bảo chỉ số z của bạn đủ cao.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.