BulletPhysic: contacts force/impulse
Asked Answered
T

1

7

I wish to detect when one (ball) touches another object (target) and I wish to know the impulse of that contact.

I know three ways to detect contacts

gContactAddedCallback

or

    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
            }
        }
    }

or

Check the linear and angular velocity change. (Not clear if there was contact and what object made the speed change, was it object or damping, gravity or some force field.


I wish to have contact information to include contacts impulse. I noticed that some contact resolved in 1 frame simulation other take 2 frames and impulse is twice lower. (I got it debugging code.) I would be perfect to get 1 contact notification with total impulse.

None of the methods I listed give me full information for the contact. Some time it fires when ball flies near target and even does not touch it.

What is an anticipated way to do it?

Such information could used to play impact sound or start some animation if contacts energy is high.

Trow answered 21/10, 2012 at 18:22 Comment(1)
pt.getAppliedImpulse() - I missed this one! add answer and I will mark it as such. Thank YouTrow
M
3

This code should point you in on posible direction

// 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
        }
    }
}
Makkah answered 22/11, 2012 at 19:36 Comment(3)
I am sorry. I can't mark it responded. I only give +1. I tested pt.getAppliedImpulse() and it does not work. It is often has 0 total impulse even when I see that it was happened in simulation and my speeds changes significantly. or numContacts is zero.Trow
getAppliedImpulse gives some weird results. i.e. stationary objects touches the ground with high force but an object impacting with high speed sometimes gives low impact force. I'm already iterating over all contact points and selecting the highest strength. Any ideas why this happens?Hiatus
Same issue, i suspect it's probably a CCD issue, or just Bullet being really obscure and not documented well enough, as usual. As a cope - checking obA/B getInterpolationLinearVelocity().length() might be a decent-ish way to check if collision happened at a high enough velocity to say play a sound.Selfreproach

© 2022 - 2024 — McMap. All rights reserved.