Custom contact callback

gfm
Posts: 16
Joined: Tue Sep 09, 2008 8:56 am

Custom contact callback

Post by gfm »

I was following the example in ConcavePhysicsDemo for creating a custom contact callback so I could supply my own friction/restitution values when an object impacted my trimesh, however I observed that no matter what I supplied for the friction/restitution the simulation always used the friction/restitution values set on the collision shape.

Tracing the problem back to btManifoldResult::addContactPoint I noticed that the contact information is added to the manifold *before* the contact callback is issued. Moving the callback back a few steps seems to have resolved the problem.

Is this a bug, or am I misinterpreting how this is supposed to work?

Before my change:

Code: Select all

void btManifoldResult::addContactPoint(const btVector3& normalOnBInWorld,const btVector3& pointInWorld,btScalar depth)
{
	assert(m_manifoldPtr);
	//order in manifold needs to match
	
	if (depth > m_manifoldPtr->getContactBreakingThreshold())
		return;

	bool isSwapped = m_manifoldPtr->getBody0() != m_body0;

	btVector3 pointA = pointInWorld + normalOnBInWorld * depth;

	btVector3 localA;
	btVector3 localB;
	
	if (isSwapped)
	{
		localA = m_rootTransB.invXform(pointA );
		localB = m_rootTransA.invXform(pointInWorld);
	} else
	{
		localA = m_rootTransA.invXform(pointA );
		localB = m_rootTransB.invXform(pointInWorld);
	}

	btManifoldPoint newPt(localA,localB,normalOnBInWorld,depth);
	newPt.m_positionWorldOnA = pointA;
	newPt.m_positionWorldOnB = pointInWorld;
	
	int insertIndex = m_manifoldPtr->getCacheEntry(newPt);

	newPt.m_combinedFriction = calculateCombinedFriction(m_body0,m_body1);
	newPt.m_combinedRestitution = calculateCombinedRestitution(m_body0,m_body1);

   //BP mod, store contact triangles.
   newPt.m_partId0 = m_partId0;
   newPt.m_partId1 = m_partId1;
   newPt.m_index0  = m_index0;
   newPt.m_index1  = m_index1;
	
	///todo, check this for any side effects
	if (insertIndex >= 0)
	{
		//const btManifoldPoint& oldPoint = m_manifoldPtr->getContactPoint(insertIndex);
		m_manifoldPtr->replaceContactPoint(newPt,insertIndex);
	} else
	{
		m_manifoldPtr->AddManifoldPoint(newPt);
	}

	//User can override friction and/or restitution
	if (gContactAddedCallback &&
		//and if either of the two bodies requires custom material
		 ((m_body0->getCollisionFlags() & btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK) ||
		   (m_body1->getCollisionFlags() & btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK)))
	{
		//experimental feature info, for per-triangle material etc.
		btCollisionObject* obj0 = isSwapped? m_body1 : m_body0;
		btCollisionObject* obj1 = isSwapped? m_body0 : m_body1;
		(*gContactAddedCallback)(newPt,obj0,m_partId0,m_index0,obj1,m_partId1,m_index1);
	}

}
After my change:

Code: Select all

...
   newPt.m_partId0 = m_partId0;
   newPt.m_partId1 = m_partId1;
   newPt.m_index0  = m_index0;
   newPt.m_index1  = m_index1;
	
	//User can override friction and/or restitution
	if (gContactAddedCallback &&
		//and if either of the two bodies requires custom material
		((m_body0->getCollisionFlags() & btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK) ||
		 (m_body1->getCollisionFlags() & btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK)))
	{
		//experimental feature info, for per-triangle material etc.
		btCollisionObject* obj0 = isSwapped? m_body1 : m_body0;
		btCollisionObject* obj1 = isSwapped? m_body0 : m_body1;
		(*gContactAddedCallback)(newPt,obj0,m_partId0,m_index0,obj1,m_partId1,m_index1);
	}
	
	///todo, check this for any side effects
	if (insertIndex >= 0)
	{
		//const btManifoldPoint& oldPoint = m_manifoldPtr->getContactPoint(insertIndex);
		m_manifoldPtr->replaceContactPoint(newPt,insertIndex);
	} else
	{
		m_manifoldPtr->AddManifoldPoint(newPt);
	}
...
User avatar
Erwin Coumans
Site Admin
Posts: 4221
Joined: Sun Jun 26, 2005 6:43 pm
Location: California, USA

Re: Custom contact callback

Post by Erwin Coumans »

Are you using the latest Bullet 2.71?

The code should look like this:

Code: Select all

(*gContactAddedCallback)(m_manifoldPtr_>getContactPoint(insertIndex),obj0,m_partId0,m_index0,obj1,m_partId1,m_index1);
So it passes in a reference, not a newPt.

Hope this helps,
Erwin
gfm
Posts: 16
Joined: Tue Sep 09, 2008 8:56 am

Re: Custom contact callback

Post by gfm »

> Are you using the latest Bullet 2.71?

I guess not. I was using some version pre-2.70.. Anyways, I've updated and the new code behaves as expected. Thanks!