How do I detect contacts ?

User avatar
cippyboy
Posts: 36
Joined: Fri Aug 25, 2006 1:00 am
Location: Bucharest

How do I detect contacts ?

Post by cippyboy »

I tried 2 ways which i've seen in the sample programs but they don't seem to function as expected.

First I tried the code from the CollisionInterfaceDemo.cpp, the function begining with :
void CollisionInterfaceDemo::displayCallback(void) {

I'm not used to physics nomenclature so I don't get all the things. The Manifolds are supposed to be contact details right ? So then what does "contactManifold->clearManifold();" do ? remove the contacts ? if so, what if you don't remove them, they remain there until what ?
I thought that contacts are updated per frame and I should check the contacts against my objects and check which was one has collided. Unfortunately, there are contacts even if only the AABB collide, and there isn't any flag to tell me that an actual contact has happened or if only the AABB has collided. Other times, there are Manifolds generated, but no contact points, how come ?

The other way is to replace the NearCallback and... do what it should do ? There's this btManifoldResult variable and I don't realize what to do with it to get the contact point.
User avatar
Erwin Coumans
Site Admin
Posts: 4221
Joined: Sun Jun 26, 2005 6:43 pm
Location: California, USA

Re: How do I detect contacts ?

Post by Erwin Coumans »

cippyboy wrote:
I'm not used to physics nomenclature so I don't get all the things. The Manifolds are supposed to be contact details right ? So then what does "contactManifold->clearManifold();" do ? remove the contacts ? if so, what if you don't remove them, they remain there until what ?
I thought that contacts are updated per frame and I should check the contacts against my objects and check which was one has collided. Unfortunately, there are contacts even if only the AABB collide, and there isn't any flag to tell me that an actual contact has happened or if only the AABB has collided. Other times, there are Manifolds generated, but no contact points, how come ?
The CollisionInterfaceDemo should work fine. You call 'performDiscreteCollisionDetection, and then the contacts are available in the 'manifolds'. They contact the contact details for each pair indeed. You don't need to call 'clearManifold', it will throw away all contact points. Contact points are updated and removed in the 'refreshContactPoints' call.

Code: Select all

	collisionWorld->performDiscreteCollisionDetection();
	
	int i;

	///one way to draw all the contact points is iterating over contact manifolds / points:

	int numManifolds = collisionWorld->getDispatcher()->getNumManifolds();
	for (i=0;i<numManifolds;i++)
	{
		btPersistentManifold* contactManifold = collisionWorld->getDispatcher()->getManifoldByIndexInternal(i);
		btCollisionObject* obA = static_cast<btCollisionObject*>(contactManifold->getBody0());
		btCollisionObject* obB = static_cast<btCollisionObject*>(contactManifold->getBody1());
		contactManifold->refreshContactPoints(obA->getWorldTransform(),obB->getWorldTransform());

		int numContacts = contactManifold->getNumContacts();
		for (int j=0;j<numContacts;j++)
		{
			btManifoldPoint& pt = contactManifold->getContactPoint(j);

			glBegin(GL_LINES);
			glColor3f(1, 0, 1);
			
			btVector3 ptA = pt.getPositionWorldOnA();
			btVector3 ptB = pt.getPositionWorldOnB();

			glVertex3d(ptA.x(),ptA.y(),ptA.z());
			glVertex3d(ptB.x(),ptB.y(),ptB.z());
			glEnd();
		}

		//you can un-comment out this line, and then all points are removed
		//contactManifold->clearManifold();	
	}
The other way is to replace the NearCallback and... do what it should do ? There's this btManifoldResult variable and I don't realize what to do with it to get the contact point.
The btManifoldResult is a class, that has a virtual method. Override this virtual method, and you will get a callback for new contact points. However, if you want to have more then one contact point per overlapping pair, you better use the first method (iterating over manifolds).

Hope this helps,
Erwin
User avatar
cippyboy
Posts: 36
Joined: Fri Aug 25, 2006 1:00 am
Location: Bucharest

Re: How do I detect contacts ?

Post by cippyboy »

Ok, so I gave it another try. It seems that it doesn't generate a point when it just enters the AABB (my bad) and it works fine except... when I have <120 FPS. I use this piece of code to detect my objects, named BOMB, and upon an impact I delete it.

Code: Select all


void DetectContacts()
{

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());
		contactManifold->refreshContactPoints(obA->getWorldTransform(),obB->getWorldTransform());
		//
		PHYSICAL_OBJECT *ObjectA=FindPhysicalObject(obA);
		PHYSICAL_OBJECT *ObjectB=FindPhysicalObject(obB);
		if (!ObjectA || !ObjectB)
		{			
			//DebugBreak();			
			continue;
		}
		//
		int numContacts = contactManifold->getNumContacts();		
		//
		if (numContacts>0)
		{
			PHYSICAL_OBJECT *TheBomb=NULL;
			if (strstr(ObjectA->Name,"BOMB"))
				TheBomb=ObjectA;
			if (strstr(ObjectB->Name,"BOMB"))
				TheBomb=ObjectB;
			if (TheBomb)
			{
				//delete this object			
				DeletePhysicalObject(TheBomb);
				continue;
			}
		}
}

PHYSICAL_OBJECT *FindPhysicalObject(btCollisionObject *ColObj)
{
	//btRigidBody is derived from btCollisionObject
		//so their pointers should coincide
	for(int y=0;y<PhysObject.nr;y++)
	{
		//body is a btRigidBody 
		if ((*PhysObject[y])->body==ColObj)
			return (*PhysObject[y]);
	}
	return NULL;
}

Another odd thing is that sometimes when I try to find my objects based on the obA & obB pointers, it returns NULL and I don't know how else to detect my objects.
I also use a variable time step based on the frame rate. I don't understand why in the samples there was a fixed time step. My application will surely have variable frame rates so I wouldn't want the simulation to be variable. Could the missed contact be from that ?

Here's a video : http://youtube.com/watch?v=9eFIROTLJNM . The Balls get deleted upon first contact, but some just roll away or get deleted at the second contact, dunno why. Don't mind the extreme gravity (around 5G).