Collision callback member function

From ODE Wiki

Jump to: navigation, search

Copy-dump from old wiki!

The following is a simplified version of code cut-and-pasted from Juice, so if some details look wrong, they probably are. This code is merely intended to illustrate the use of a static member function to wrap the standard member function in which the callback functionality resides.

class World
{
    // Step the world
    virtual bool fStep (unsigned uMilliseconds);
    // This wrapper is called by the physics library to get information 
    // about object collisions
    static void CollisionCallback (void *pData, dGeomID o1, dGeomID o2);

    // This actually implements the collision callback 
    void CollisionCallback (dGeomID o1, dGeomID o2);
}

// Step the world.  Notice that "this" is passed as the second
// parameter to dSpaceCollide.  That's crucial.
//
bool IterativeWorld::fStep (unsigned uMilliseconds)
{
    // check for collisions, create contact joints
    dSpaceCollide (m_SpaceID, this, CollisionCallback);

    // convert to seconds
    real rElapsedTime = ((real) uMilliseconds) / ((real) 1000.0);

    // step the world
    dWorldStep (m_WorldID, rElapsedTime, m_Constants.m_uIterations);

    // remove all contact joints
    dJointGroupEmpty (m_CollisionJointGroup);

    return fReturn;
}

// Remember, this function is static, it has no "this" pointer,
// nor any of the other members of the World class.
//
void World::CollisionCallback (void *pData, dGeomID o1, dGeomID o2)
{
    // pData is the "this" that was passed into dSpaceCollide
    World* pThis = (World*) pData;
    if (pThis)
    pThis->CollisionCallback (o1, o2);
}

// This is a nonstatic member function, here you have access to
// all of the member variables in your World class.  Notice the
// parameters to dJointCreateContact, near the bottom.
//
void World::CollisionCallback (dGeomID o1, dGeomID o2)
{
    if (!(o1 && o2))
    {
        Breakpoint ("CollisionCallback with null geometry\n");
        return;
    }

    // ignore collisions between bodies that are connected by the same joint
    dBodyID Body1 = null, Body2 = null;

    if (o1) Body1 = dGeomGetBody (o1);
    if (o2) Body2 = dGeomGetBody (o2);

    if (Body1 && Body2 && dAreConnected (Body1, Body2))
    return;

    const int iContacts = ODE_MAX_CONTACTS;
    dContact contact[iContacts];

    int iCount = dCollide (o1, o2, iContacts, &contact[0].geom, sizeof (dContact));

    if (iCount)
    {
        int iMax = min (iCount, iContacts);
        for (int iContact = 0; iContact < iMax; iContact++)
        {
            contact[iContact].surface.mode = dContactBounce; 
            contact[iContact].surface.mu = m_Constants.m_rFriction;
            contact[iContact].surface.bounce = m_Constants.m_rBounce;
            contact[iContact].surface.bounce_vel = (dReal) 0.01;
            contact[iContact].surface.slip1 = (dReal) 0.1;
            contact[iContact].surface.slip2 = (dReal) 0.1;

            dJointID ContactJoint = dJointCreateContact (m_WorldID, 
                                                         m_CollisionJointGroup, 
                                                         &contact[iContact]);

            dJointAttach (ContactJoint, Body1, Body2);
        }
    }
}
Personal tools
Navigation