Collision callback member function
From ODE Wiki
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);
}
}
}

