Bullet物理引擎:接触力/冲量

7

我希望能够检测到球触碰其他物体(目标),并且知道它所产生的冲量。

我知道三种检测接触的方法。

gContactAddedCallback

或者

    int numManifolds = m_dynamicsWorld->getDispatcher()->getNumManifolds();
    for (int i=0;i<numManifolds;i++)
    {
        btRigidBody* obA = static_cast<btRigidBody*>(contactManifold->getBody0());
        btRigidBody* obB = static_cast<btRigidBody*>(contactManifold->getBody1());
        // May be there is contact obA and obB

        btPersistentManifold* contactManifold =  m_dynamicsWorld->getDispatcher()->getManifoldByIndexInternal(i);
        int numContacts = contactManifold->getNumContacts();
        for (int j=0;j<numContacts;j++)
        {
            btManifoldPoint& pt = contactManifold->getContactPoint(j);
            if (pt.getDistance()<0.f)
            {
                // One contact point is inside of another object
                // But some contacts are ignored
            }
        }
    }

或者

检查线速度和角速度的变化。(不清楚是否有接触,以及是什么物体使速度发生了变化——是物体、阻尼、重力还是一些力场。)


我希望获得联系人信息来包括联系人脉冲。

我注意到有些联系在1个帧模拟中解决,其他联系则需要2个帧,并且脉冲减少了一半。(我通过调试代码得到的信息。)获取1个联系人通知并具有总脉冲将是完美的。

我列出的方法都没有为我提供关于该联系的完整信息。

有时候它会在球飞近目标时触发,甚至根本没有碰到它。

有什么预期的方法可以做到这一点?

这样的信息可以用于播放撞击音效或启动一些动画,如果联系人能量很高的话。


pt.getAppliedImpulse() - 我错过了这个!添加答案,我会标记它。谢谢。 - Max
1个回答

3
这段代码应该指向您可能需要的方向。
// some global constants needed

enum collisiontypes {
    NOTHING         = 0,    // things that don't collide
    BALL_BODY       = 1<<2, // is ball
    TARGET_BODY     = 1<<3  // is target
};

int ballBodyCollidesWith    = TARGET_BODY | BALL_BODY;  // balls collide with targets and other balls
int targetBodyCollidesWith  = BALL_BODY;    // targets collide with balls

// ...
// bodies creation

dynamicsWorld->addRigidBody(ballBody, BALL_BODY, ballBodyCollidesWith);

dynamicsWorld->addRigidBody(targetBody, TARGET_BODY, targetBodyCollidesWith);

//...
// find out whether a ball collides with a target

int numManifolds = m_dynamicsWorld->getDispatcher()->getNumManifolds();
for (int i=0;i<numManifolds;i++)
{
    btRigidBody* obA = static_cast<btRigidBody*>(contactManifold->getBody0());
    btRigidBody* obB = static_cast<btRigidBody*>(contactManifold->getBody1());
    // May be there is contact obA and obB

    // ignore bodies that are not balls or targets
    if (
        (!(obA->getCollisionFlags() | BALL_TYPE) && !(obB->getCollisionFlags() | BALL_TYPE))    // there is no BALL_TYPE colliding
        ||
        (!(obA->getCollisionFlags() | TARGET_TYPE) && !(obB->getCollisionFlags() | TARGET_TYPE))    // there is no TARGET_TYPE colliding
        )
        continue; // no more searching needed

    btPersistentManifold* contactManifold =  m_dynamicsWorld->getDispatcher()->getManifoldByIndexInternal(i);
    int numContacts = contactManifold->getNumContacts();
    for (int j=0;j<numContacts;j++)
    {
        btManifoldPoint& pt = contactManifold->getContactPoint(j);

        printf("%f\n", pt.getAppliedImpulse()); // log to see the variation range of getAppliedImpulse and to chose the appropriate impulseThreshold
        if (pt.getAppliedImpulse() > impulseThreshold)
        {
                // increase score or something
                break; // no more searching needed
        }
    }
}

2
很抱歉,我无法标记它为已响应。我只能给+1。我测试了pt.getAppliedImpulse(),但它不起作用。即使我看到模拟中发生了碰撞并且速度发生了显着变化,该函数通常仍然返回0的总冲量,或者numContacts为零。 - Max
getAppliedImpulse 给出了一些奇怪的结果。即使是静止的物体接触地面也会受到很大的力,但有时具有高速度的物体撞击后却只产生低冲击力。我已经遍历了所有接触点并选择了最大的强度值。你有什么想法为什么会发生这种情况吗? - Pawel
同样的问题,我怀疑可能是CCD问题,或者只是Bullet非常隐晦且文档不够完善,像往常一样。作为一种应对措施,检查obA/B getInterpolationLinearVelocity().length()可能是一种相当不错的方式,用来检查碰撞是否发生在足够高的速度下,以播放声音。 - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接