bullet collision callback between 2 bodies

3.7k views Asked by At

I have 2 objects, a sphere and a box that, when one collides with the other, will do some action (i.e. destroy the box).

I have tried several ways:

  • checkCollideWith always returns true;
  • contactPairTest - this I do not understand how to use. It takes 3 arguments, the 2 objects and a callback. I thought that the callback can be any function in my code, but it doesn't work like that.

Could someone please give an example of how to call a method, for example CollissionResult(), when 2 btRigidBodies collide (i.e. bodyA and bodyB)?

2

There are 2 answers

7
john On BEST ANSWER

Maybe this example will help explain the concept. You have to define a new class, derived from an existing abstract class. You override one of the abstract classes methods with your callback code. You then create an object of the derived class and pass that to the function you want to call the callback. It's a common enough C++ technique.

struct MyContactResultCallback : public ContactResultCallback
{
    btScalar addSingleResult(btManifoldPoint& cp,
        const btCollisionObjectWrapper* colObj0Wrap,
        int partId0,
        int index0,
        const btCollisionObjectWrapper* colObj1Wrap,
        int partId1,
        in index1)
    {
        // your callback code here
    }
};

MyContactResultCallback callback;
world.contactPairTest(bodyA, bodyB, callback);

I should add that I nothing whatsoever about this library. I've just read the docs.

EDIT

Showing how to add a context member to MyContactResultCallback.

struct MyContactResultCallback : public ContactResultCallback
{
    MyContactResultCallback(some_type* ptr) : context(ptr) {}

    btScalar addSingleResult(btManifoldPoint& cp,
        const btCollisionObjectWrapper* colObj0Wrap,
        int partId0,
        int index0,
        const btCollisionObjectWrapper* colObj1Wrap,
        int partId1,
        in index1)
    {
        context->currentPoints += 10;
    }

    some_type* context;
};

MyContactResultCallback callback(ptr_to_some_object);
world.contactPairTest(bodyA, bodyB, callback);

ptr_to_some_object is the pointer to the object with the currentPoints that you want to increment. I don't know what type of object that is, so I've just said some_type, you can replace that with whatever the real type is.

This is the point of using an object as a callback instead of a function. If the callback is an object you can add data members to it for whatever purpose you want, you cannot do that to a function.

0
Bram On

I found the easiest way is to check the manifolds. No custom classes needed if you just ask the dispatcher.

Just execute this each time after stepping the world:

    btDispatcher* dp = world->getDispatcher();
    const int numManifolds = dp->getNumManifolds();
    for ( int m=0; m<numManifolds; ++m )
    {
            btPersistentManifold* man = dp->getManifoldByIndexInternal( m );
            const btRigidBody* obA = static_cast<const btRigidBody*>(man->getBody0());
            const btRigidBody* obB = static_cast<const btRigidBody*>(man->getBody1());
            const void* ptrA = obA->getUserPointer();
            const void* ptrB = obB->getUserPointer();
            // use user pointers to determine if objects are eligible for destruction.
            ...
            const int numc = man->getNumContacts();
            float totalImpact = 0.0f;
            for ( int c=0; c<numc; ++c )
                    totalImpact += man->getContactPoint(c).m_appliedImpulse;
            if ( totalImpact > threshold )
            {
                    // Here you can break one, or both shapes, if so desired.
            }
    }