[ODE] Collision callback pattern
Nate W
coding at natew.com
Mon Sep 1 23:19:01 2003
On Tue, 2 Sep 2003, Dave Lloyd wrote:
> Seems like a good strategy then would be to blend the materials
> empirically according to 'typical physics' (i.e., best guess) and
> provide escape mechanisms for unusual material combinations. An
> alternative would be to provide a rule for each pair of surface types -
> admittedly more awkward to introduce new surfaces as each combination
> must be considered but I suspect in many cases there won't be that many
> surface types.
Ok, so... thinking out loud, for a racing game...
// Enumerate material types, with the last item in the enum being the
// number of material types
enum MaterialType
{
kDirt = 0,
kAsphalt,
kIce,
kTire,
kBodywork,
kMaterialTypes
}
// Pointer to a function that sets properties for a contact, given the
// two materials that are colliding.
typedef void (*ContactPropertiesProc) (dContact *pContact,
Material *pM1, Material *pM2);
void Default (dContact *pContact,
Material *pM1, Material *pM2);
{
// use "best guess" method, based on the two material types
}
void TireAndAsphalt (dContact *pContact,
Material *pM1, Material *pM2);
{
// Use more sophisticated method for tire-asphalt contacts
// The two material type parameters could be ignored, or maybe it
// could be asserted that one material is "tire" and the other is
// "asphalt."
}
void TireAndDirt (dContact *pContact,
Material *pM1, Material *pM2);
{
// Use different method for tire-dirt contacts
}
// 2D array of those function pointers
ContactPropertiesProc PropertySetters[kMaterialTypes][kMaterialTypes];
void InitContactPropertySetterArray ()
{
// Fill the array with the default function pointer
for (int i = 0; i < nMaterials; i++)
for (int j = 0; j < nMaterials; j++)
PropertySetters[i][j] = Default;
// Set the 'special case' contact property functions
PropertySetters[kTire][kAsphalt] = TireAndAsphalt;
PropertySetters[kAsphalt][kTire] = TireAndAsphalt;
PropertySetters[kTire][kDirt] = TireAndDirt;
PropertySetters[kDirt][kTire] = TireAndDirt;
}
// This function is slightly abridged...
void CollisionCallback (dGeomID o1, dGeomID o2)
{
// Get the materials and their enums
Material* pM1 = GetMaterial (o1);
Material* pM2 = GetMaterial (o2);
MaterialType mt1 = GetMaterialType (pM1);
MaterialType mt2 = GetMaterialType (pM2);
// Get the property setter for this material combination
ContactPropertiesProc PropertySetter = PropertySetters[mt1][mt2];
dContact Contact[ODE_MAX_CONTACTS];
int iCount = dCollide (o1, o2, iContacts,
&Contact[0].geom, sizeof (dContact));
for (int iContact = 0; iContact < iMax; iContact++)
{
// Set the contact properties with the property setter
PropertySetter (Contact[iContact], pM1, pM2)
// Create the contact joint as usual
dJointID ContactJoint = dJointCreateContact (WorldID,
CollisionJointGroup, &Contact[iContact]);
}
}
--
I think it'd work, but I'm not promising. :-)
--
Nate Waddoups
Redmond WA USA
http://www.natew.com