Box2D - 我怎么知道2个灯具何时接触?

时间:2012-02-22 10:29:58

标签: c++ box2d

我只是好奇,如果我的身体有2个或更多的固定装置没有“连接在一起”,我怎么能在代码中明确地确定这个?这是我的意思的一个例子:

Example of a single body with more than 1 fixture, two are touching, one is not.

我标记了每个独特夹具的顶点,只是为了使它们完全清楚,这些是不相互共享顶点的独立形状。然而,它们组合成一个整体。正如您所看到的,两个灯具彼此非常接近或“接触”,并且一个灯具本身是分开的。我想知道如何在Box2D中查询正文的装置,以便能够在运行时找到它。

为了全面考虑这一点,它是用于创建和处理可破坏的物体。该图像粗略地表示在穿过身体中的一组固定器孔之后会发生什么。我需要查询以查看哪些灯具相互接触,以便我可以将一个机构分成两个,当然它们应该在那一点。

4 个答案:

答案 0 :(得分:3)

如果您已准备好新灯具,则可以使用b2TestOverlap功能检查它们是否重叠。该函数可在b2Collision.h中找到:

/// Determine if two generic shapes overlap.
bool b2TestOverlap( const b2Shape* shapeA, int32 indexA,
                    const b2Shape* shapeB, int32 indexB,
                    const b2Transform& xfA, const b2Transform& xfB );

可以通过fixture-> GetShape()找到形状,并且多边形的索引参数将为零。 由于灯具位于同一主体上,最后两个参数都可以是body-> GetTransform()。

我自己从未使用过这个,所以我无法确切地告诉你,但是注意到这个函数的名称是'重叠',它可能不会为图中的A和B灯具的情况返回正数从技术上讲,我不认为它们是重叠的。如果是这种情况,我认为你是独立的,因为Box2D不提供任何“接触”测试。

顺便提一下Constantinius提到的联系人列表仅对不同身体碰撞时的灯具有效 - 同一身体上的灯具不会碰撞。

答案 1 :(得分:2)

" 9.3访问联系人" 下的Box2D manual中,您可以使用GetContactList功能访问正文的所有联系人:

for (b2ContactEdge* ce = myBody->GetContactList(); ce; ce = ce->next)
{
    b2Contact* c = ce->contact;
    ...
}

b2ContactEdgeb2Contact中,您可以找到实际的形状和标志,如果它们实际上正在触摸(b2Contact::IsTouching)。

答案 2 :(得分:1)

我建议做这样的事情:

  • 要获得准确的结果,您必须测试交叉点。在第一遍中,您可以仅比较灯具的重心,然后仅在COG位于较小距离内时计算所有线的交点。

  • 另一种方法可能是栅格化场景。那么你可以使用类似模板缓冲区的东西来绘制栅格化像素。

  • 模板将是一个大小(w * h)的数组,其中w和h是光栅化图像的宽度和高度,并且每个像素保持一个整数。

  • 为每个像素初始化模板缓冲区为0。

  • 对于您“绘制”的每个光栅化灯具,您只需增加其所有像素位置的缓冲值。

  • 所以最后模板缓冲区在没有被任何夹具占据的位置包含0,其中只有一个夹具位于该位置,而对于任何更大的值,你有交叉点。

这种方法的复杂性主要取决于所选择的光栅化分辨率。

答案 3 :(得分:0)

执行此操作的另一种方法(作为其他人之前建议使用b2TestOverlap的替代方法),将使用b2CollidePolygons函数(来自b2Collision.h)。您可以在灯具的多边形形状上使用它,然后查看b2Manifold' pointCount字段是否大于零。

这里有一些C ++ 11之前的代码示例(我没有编译和测试过,所以希望它还没有得到foobar' ed):

bool isTouching(const b2PolygonShape& polygonA, const b2Transform& xfA, const b2PolygonShape& polygonB, const b2Transform& xfb)
{
    b2Manifold manifold;
    b2CollidePolygons(&manifold, &polygonA, xfA, &polygonB, xfB);
    return manifold.pointCount > 0;
}

bool isPolygonFixturesTouching(const b2Fixture& fixtureA, const b2Fixture& fixtureB)
{
    const b2Shape* shapeA = fixtureA.GetShape();
    const b2Shape* shapeB = fixtureB.GetShape();
    if (shapeA->GetType() == b2Shape::e_polygon && shapeB->GetType() == b2Shape::e_polygon)
    {
        const b2Body* bodyA = fixtureA.GetBody();
        const b2Transform& xfA = bodyA->GetTransform();
        const b2Body* bodyB = fixtureB.GetBody();
        const b2Transform& xfB = bodyB->GetTransform();
        return isTouching(*(static_cast<b2PolygonShape*>(shapeA)), xfA, *(static_cast<b2PolygonShape*>(shapeB)), xfB);
    }
    return false;
}

int main()
{
    ...
    if (isPolygonFixturesTouching(fixtureA, fixtureB))
    {
        std::cout << "hooray!" << std::endl;
    }
}

注意:我刚试过的一些原始时序测试比较b2TestOverlapb2CollidePolygons显示b2TestOverlap为4或5倍更快(比b2CollidePolygons)。鉴于前者只是在寻找任何重叠,而后者正在计算碰撞流形,我认为速度差异并不令人惊讶。无论如何,这个故事的寓意似乎是b2TestOverlap可能是一个更好的功能,如果你只是想知道2个灯具是否正在触摸,而b2CollidePolygons则更有用如果你还想知道更多的东西,比如2个灯具是如何接触的。