Contacts management....

dreamtheater39
Posts: 13
Joined: Sat Nov 10, 2007 8:39 pm

Contacts management....

Post by dreamtheater39 »

Hi Erwin!

First of all, a formal "Thank you very much for this incredible engine"!!!! :)
I was using ODE earlier, and now moved into bullet, and i must say that this engine is far superior/cleaner and easier to use! There is a lot more flexibility available and excellent support for collision detection, which makes bullet a god send!

Now to my question on contacts management -
Wouldnt it be easier if every body object maintained an array of current contacts its making with other bodies? Basic info such as number of contacts, contact locations & normals, penetration depth/force magnitude during impact should be great and handy. I'm sure the core engine is already calculating these, its just a matter of exposing these results to the end user to make it possible to do a lot more with less coding.

Of course, the alternate approach is to create a callback and tap the results from there, but i feel this is extra work for no reason and besides this info will be useful to everyone! For example, for using this to play sounds when objects collide etc.

Thanks a lot for your patience, and for the wonderful engine!!!

San
dreamtheater39
Posts: 13
Joined: Sat Nov 10, 2007 8:39 pm

Re: Contacts management....

Post by dreamtheater39 »

Did i make sense? or was it a stupid request?!

San
User avatar
Erwin Coumans
Site Admin
Posts: 4221
Joined: Sun Jun 26, 2005 6:43 pm
Location: California, USA

Re: Contacts management....

Post by Erwin Coumans »

Hi,

the contact points are available, each overlapping pair of objects has up to 4 points in a btPersistentContactManifold (=contact cache).

You can iterate over all those pairs and get the contacts, see Demos/CollisionInterfaceDemo:

Code: Select all

             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());
		
		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();
		}
	}
In the future, we might be able to make it a bit easier to get from rigid body to the overlappings that contact this body.

Hope this helps,
Erwin
dreamtheater39
Posts: 13
Joined: Sat Nov 10, 2007 8:39 pm

Re: Contacts management....

Post by dreamtheater39 »

Erwin Coumans wrote:Hi,

the contact points are available, each overlapping pair of objects has up to 4 points in a btPersistentContactManifold (=contact cache).

You can iterate over all those pairs and get the contacts, see Demos/CollisionInterfaceDemo:

Code: Select all

             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());
		
		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();
		}
	}
In the future, we might be able to make it a bit easier to get from rigid body to the overlappings that contact this body.

Hope this helps,
Erwin
Hi Erwin!

Thanks for your reply!
Well, i was aware of how bullet currently maintains its contact manifolds. However, I thought it would be inefficient for me to browse through an entire list of all contacts/bodies present in my dynamics world to find contact info for JUST one of the bodies i'm interested in.

In a game we're developing, we have a ball which drops through a maze and i need to use the contact info to play sounds based on hits/material hit etc. Now all i'm interested in is if the ball is touching any object, for which i will need to parse through the entire body list participating in any active collision/contact. Is it efficient enough already which wont make a difference for my implementation? Or do you suggest i change the internals to store collision info into the rigid body when a contact happens?

Thanks for your time!
San
User avatar
Erwin Coumans
Site Admin
Posts: 4221
Joined: Sun Jun 26, 2005 6:43 pm
Location: California, USA

Re: Contacts management....

Post by Erwin Coumans »

dreamtheater39 wrote: In a game we're developing, we have a ball which drops through a maze and i need to use the contact info to play sounds based on hits/material hit etc. Now all i'm interested in is if the ball is touching any object, for which i will need to parse through the entire body list participating in any active collision/contact. Is it efficient enough already which wont make a difference for my implementation? Or do you suggest i change the internals to store collision info into the rigid body when a contact happens?

Thanks for your time!
San
Bullet 2.65 will contain various contact callback demos, that show how to do this most efficiently (avoiding traversing all pairs).

However even traversing the entire array of contact manifolds shouldn't take much time. Have you done any profiling?

Thanks,
Erwin
richieturner
Posts: 2
Joined: Wed Feb 11, 2009 12:22 pm

Re: Contacts management....

Post by richieturner »

Hi,

I'm have a similar problem to this where I'd like to retrieve, on a per object basis, a contact list including normals, position and a ptr. to the collision object we collided with. This is for much the same purpose; rending collision effects and applying logic to collidees etc.

I've implemented the solution above and it works great to get contacts between dynamic objects. However I don’t get results for collisions between dynamic and static objects? Also, you mention there’s a better way of going about this with callbacks? We're on Bullet 2.73, can you point me in the right direction for the callback method?

Churz,

Richie.
Flix
Posts: 456
Joined: Tue Dec 25, 2007 1:06 pm

Re: Contacts management....

Post by Flix »

I'm looking forward the future improvements of the Bullet library in this field.

For the current version of Bullet I can contribute my implementation. It's far for being fast/efficient/perfect, but it's compliant with the code in the Bullet Demos and it's easy to integrate it in client code.

There are already code snippets about this topic here:
http://www.bulletphysics.com/Bullet/php ... 97&p=15575

My implementation is more complicated because I calculate the "average" contact point before sending events. I don't know if that is really necessary; for sure it makes my code slower and more prone to errors...
Moreover I use (unsorted) btAlignedObjectArrays instead of std::maps. That makes my code even slower (expecially when I have to compare the two lists to fire start/end events); but STL containers are strictly fobidden in the Bullet library to improve code portability.

In the attached demo, three objects are monitored for collisions: the two big objects and the ground (the latter is the worst case scenario, since its contact lists are very long, and I suggest to avoid monitoring it in real applications).

Hope it helps (at least some newbie 8) ).
You do not have the required permissions to view the files attached to this post.
richieturner
Posts: 2
Joined: Wed Feb 11, 2009 12:22 pm

Re: Contacts management....

Post by richieturner »

Thanks Flix,

Thats pretty much what I'm doing although I leave the averaging to the user to implement.

It turns out there was a problem with the way I was filtering rigid bodies the precluded Static Object contacts. Thats fixed now so all is groovy once more :)

I would be interested in hearing from anyone who has implemented a more elegant solution though, maybe using per-object callbacks?

Richie.
Flix
Posts: 456
Joined: Tue Dec 25, 2007 1:06 pm

Re: Contacts management....

Post by Flix »

richieturner wrote:
Thats pretty much what I'm doing although I leave the averaging to the user to implement.
For curiosity how do you do it? Do you send a collection of contact points to the user? Otherwise the user can still get all the points but in multiple callbacks (per physic frame), and it would be a bit complicated to collect them from the user side...
I would be interested in hearing from anyone who has implemented a more elegant solution though, maybe using per-object callbacks?
Adding per objects callbacks based on the code I posted won't be that difficult. If we make btRigidBodyWithEvents a template class, we can pass it our application class and then store the application class instance pointer inside it and subscribe delegates or events like this: bodyWithEvents->addCollisionStart(&MyApplicationClass:onCollisionStart,this);

I didn't do it because I am lazy on client side coding, and I prefer simply to write bodyWithEvents->setMonitorCollision(true), instead of writing 3 lines of code plus other three for the event method definitions that now are "recycled" from the interface I provided (although I know that per-object callback is THE way of doing it...).


Anyway my primary target was to provide a Bullet Demo performing collision start/end event (because AFAIK it was missing); so people can optimize/modify/enhance/improve it (and maybe sending it back to the Bullet community).
Flix
Posts: 456
Joined: Tue Dec 25, 2007 1:06 pm

Re: Contacts management....

Post by Flix »

I've made a small update:
BasicDemoCollisionEvents.7z
CHANGELOG:

Now events can be selectively filtered and can be optionally redirected to generic callbacks (on a per body basis).

An "AvgContactPoint" struct is passed directly to the user (instead of the long list of arguments used before).

Now by default the "AvgContactPoint" applied impulse is just the sum of the applied impulses of all contact points (but a definition can be
used to revert this change if needed).

The number of the original contact points can be retrieved too.

There are definitions in both "btRigidBodyWithCollisionEvents.h" and "BasicDemo.cpp" that can be used to configure/test the system.

A few runtime queries are available for bodies monitored for collisions.

Further info can be found at the top of the "btRigidBodyWithCollisionEvents.h" header file.

P.S. I know it's not the faster possible system, but at least now it's comfortable to use, and it's freely available.


Hope that people who used the old version like the updated one...
Any possible improvement and bug fix is welcome!
You do not have the required permissions to view the files attached to this post.