Simplest possible C/D between two objects?

devmelon
Posts: 19
Joined: Thu Nov 27, 2008 1:44 pm

Simplest possible C/D between two objects?

Post by devmelon »

Hi, I have been struggling the whole day trying to achieve what I thought was the simplest thing in the world and it has only brought me headache :)
I want to check if two CollisionObject's (rigid bodies if that matters) collide with each other. That's it.

What is the simplest possible way to check if two known objects collide or not?

I am looking for something like

Code: Select all

if (body1.CollidesWith(body2))  { /*do something*/ }
preferable without having to use a world.

Currently I have been cornered into iterating through all the manifold points retrieved from the dispatcher, requiring a world which I have set up in advance, checking if my two objects are any of the pairs in that collection of manifolds and if they are, return true. If no match was found return false. Not only does this approach seem a bit overkill and unintuitive but it does also not work. Any ideas? I have performed a discrete collision detection prior to iterating the objects to populate the dispatcher, but the expected object pair never evaluates as a collision.
devmelon
Posts: 19
Joined: Thu Nov 27, 2008 1:44 pm

Re: Simplest possible C/D between two objects?

Post by devmelon »

I have a slight update. I thought I'd share some code, perhaps that will help.

Here is my code which is pretty much copied from the wiki. As you see, I am looking for a true return value if object1 has a collision with object2, otherwise the function should return false. I first find the dispatcher of the world and query it for the count of manifolds. Then, for each manifold I find the two candidate objects which might be the two I am looking for. Then I figure out if the objects from the query really is the two objects I want to test. If they are not, skip this manifold and resume next. If they are the objects I am looking for, check if they have any contacts and if they have any contacts we return true and stop the test. If no contacts or no pairs are found, then there was no contact and I return false.

Code: Select all

bool CollisionHelper::TestCollision(btCollisionObject *object1, btCollisionObject *object2)
{
	btDispatcher *dispatcher = mWorld->getDispatcher();
	int numManifolds = dispatcher->getNumManifolds();

	for (int i = 0; i < numManifolds; ++i)
	{
		btPersistentManifold* contactManifold = dispatcher->getManifoldByIndexInternal(i);
		btCollisionObject* obA = static_cast<btCollisionObject*>(contactManifold->getBody0());
		btCollisionObject* obB = static_cast<btCollisionObject*>(contactManifold->getBody1());

		bool isMatchingPair = (object1 == obA && object2 == obB) || (object2 == obA && object1 == obB);

		if (isMatchingPair)
		{
			int numContacts = contactManifold->getNumContacts();
			
			if (numContacts > 0)
			{
				// If the pair we are interested in have at least one contact point,
				// return true to indicate that there is a collision between object1 and object2.
				return true;
			}
		}
	}
	// If the pair we are interested in was not found or had no contacts,
	// return false to indicate that there is no collision between object1 and object2.
	return false;
}
Using the debugger, I find that both object1 and object2 are found when iterating over the manifold points, but they are never found together as a pair. Visually I can tell that the bodies are colliding, using debug drawing. I have some far stretched idea that perhaps the pointer check is not safe to do as I have previously encountered that for instance virtual inheritance changes the pointer bases for the objects. I have set my collision group and masks accordingly on the bodies and before calling this function I also call performDiscreteCollisionDetection() on the world.

I have no idea how to solve this, it shouldn't have to be so hard. I can't come up with anything else that might do what I want to do. If you can, please let me know.
Dominik
Posts: 32
Joined: Fri Dec 19, 2008 2:51 pm

Re: Simplest possible C/D between two objects?

Post by Dominik »

Looking at your code, I don't really see a mistake.
Did you call performDiscreteCollisionDetection() before?

However, the general approach is probably a little overkill, testing the whole scenery just for two bodies...
The way I do collision detection between two objects is this.

Code: Select all

btCollisionAlgorithm* pAlgorithm = pBtWorld->getDispatcher()->findAlgorithm( pBulletObj1, pBulletObj2 );
btManifoldResult oManifoldResult( pBulletObj1, pBulletObj2 );
pAlgorithm->processCollision( pBulletObj1, pBulletObj2, pBtWorld->getDispatchInfo(), &oManifoldResult );
btPersistentManifold* pManifold = oManifoldResult.getPersistentManifold();
It may not be optimal, since it does not include a broadphase step, but it works fine for me...
slithEToves
Posts: 24
Joined: Mon Mar 12, 2007 9:55 pm

Re: Simplest possible C/D between two objects?

Post by slithEToves »

In addition, adding a simple AABB check before the processCollision call can make Dominik's code fairly optimal.
nokto
Posts: 8
Joined: Fri Apr 17, 2009 12:04 am

Re: Simplest possible C/D between two objects?

Post by nokto »

Dominik wrote:Looking at your code, I don't really see a mistake.
Did you call performDiscreteCollisionDetection() before?

However, the general approach is probably a little overkill, testing the whole scenery just for two bodies...
The way I do collision detection between two objects is this.

Code: Select all

btCollisionAlgorithm* pAlgorithm = pBtWorld->getDispatcher()->findAlgorithm( pBulletObj1, pBulletObj2 );
btManifoldResult oManifoldResult( pBulletObj1, pBulletObj2 );
pAlgorithm->processCollision( pBulletObj1, pBulletObj2, pBtWorld->getDispatchInfo(), &oManifoldResult );
btPersistentManifold* pManifold = oManifoldResult.getPersistentManifold();
It may not be optimal, since it does not include a broadphase step, but it works fine for me...
Hi everyone,

I'm using the code posted above for the simpliest collision detection between two objects. But it seems that it creates leaks in memory, which is not affordable in my code. Do I have to clear anything before I leave this function? Is there any other way to do this that doesn't create memory leaks?

Thank you in advance,
nokto.-
dwells254lb43
Posts: 10
Joined: Wed Jan 21, 2009 12:27 am

Re: Simplest possible C/D between two objects?

Post by dwells254lb43 »

I have a question about that snippet of code posted by Dom, when do you know if it collided or not?
nokto
Posts: 8
Joined: Fri Apr 17, 2009 12:04 am

Re: Simplest possible C/D between two objects?

Post by nokto »

dwells254lb43 wrote:I have a question about that snippet of code posted by Dom, when do you know if it collided or not?
If pManifold == NULL then the objects didn't collide. Anyway, seriously, if your world is wide or you're calling this code quite often, I wouldn't recommend it as it creates memory leaks.

nokto.-
Dominik
Posts: 32
Joined: Fri Dec 19, 2008 2:51 pm

Re: Simplest possible C/D between two objects?

Post by Dominik »

Thanks for pointing out the mem leak. Putting this at the end of the function should fix it...

Code: Select all

pAlgorithm->~btCollisionAlgorithm();
pBtWorld->getDispatcher()->freeCollisionAlgorithm( pAlgorithm );
pManifold should usually be non-NULL after the call (except, as it seems, for GIMPACT shape tests, where it is NULL if no collision was found). If it is alive, simply check if pManifold->getNumContacts() > 0