My custom patch for collision callbacks

Promit
Posts: 3
Joined: Fri Oct 20, 2006 12:08 am

My custom patch for collision callbacks

Post by Promit »

For my purposes, I want two very simple collision callbacks: CollisionStarted(objA, objB) and CollisionEnded(objA, objB). I got tired of Bullet's seemingly convoluted, quirky methods for detecting what collisions have happened. Iterating over the manifolds doesn't tell you whether a collision is new or not, and can't yield the correct events as a result. Contact processing is exposed in a very confusing way, and ghost objects are a hassle. So I dropped into the source and wrote up a new set of callbacks that work the way I want. The modifications are trivial, yet immensely helpful IMO.

This is how it looks in client code:

Code: Select all

	//set the callbacks somewhere
	gCollisionStartedCallback = CollisionStarted;
	gCollisionEndedCallback = CollisionEnded;

static void CollisionStarted(btPersistentManifold* manifold)
{
	btCollisionObject* obA = static_cast<btCollisionObject*>(manifold->getBody0());
	btCollisionObject* obB = static_cast<btCollisionObject*>(manifold->getBody1());
	PhysicsComponent* phyA = (PhysicsComponent*) obA->getUserPointer();
	PhysicsComponent* phyB = (PhysicsComponent*) obB->getUserPointer();
	if(!phyA || !phyB)
		return;
	
	printf("Collision started between: %s, %s.\n", phyA->_parent->Name.c_str(), phyB->_parent->Name.c_str());
}

static void CollisionEnded(btPersistentManifold* manifold)
{
	btCollisionObject* obA = static_cast<btCollisionObject*>(manifold->getBody0());
	btCollisionObject* obB = static_cast<btCollisionObject*>(manifold->getBody1());
	PhysicsComponent* phyA = (PhysicsComponent*) obA->getUserPointer();
	PhysicsComponent* phyB = (PhysicsComponent*) obB->getUserPointer();
	if(!phyA || !phyB)
		return;
	
	printf("Collision ended between: %s, %s.\n", phyA->_parent->Name.c_str(), phyB->_parent->Name.c_str());	
}
That's it. You get a single notification when a collision starts, no matter what is happening with the contacts. You get another notification when the collision ends. In my code I walk back into my own object hierarchy, but you could conceivably do whatever since the whole manifold is present and persistent.

The changes to Bullet are a mere handful of lines. The logic is dead simple: If a contact is added to a manifold with zero contacts, trigger gCollisionStarted. If a contact is removed leaving a manifold with zero contacts, trigger gCollisionEnded. Personally I think this is what most people want. This may not work well if you need all of the contact points, as the collision started callback triggers as soon as a single point is available. Here is a patch file with the changes:
http://promitroy.com/temp/promit-bulletcollisions.patch

I'm posting this here first in case I did something incredibly stupid or unnecessary, but all of the stuff I've seen in the forums and documentation is waaaay more of a PITA than what I've put together here. If this is something useful and productive, I'll probably publish on GameDev and my blog, dunno if it's appropriate for inclusion into Bullet main-line.