Collision detection between two btBvhTriangleMeshes

jstolarz
Posts: 14
Joined: Thu Dec 09, 2010 9:32 pm
Location: Glendale, California

Collision detection between two btBvhTriangleMeshes

Post by jstolarz »

Hello, I'm new to Bullet and am trying to use it's Collision Detection interface (not dynamics) for detecting collisions in a virtual (eventually real) robot arm. I've gone through the demo code, especially CollisionInterfaceDemo and tried to find the answer on the forum/manual, etc (already quite useful for earlier issues), but can't seem to find a solution to my problem.

Basically, the meshes are visibly in collision according to the DebugDrawer, but no collisions seem to be generated (neither via the DebugDrawer or by iterating over the ContactManifolds as suggested on various posts and in CollisionInterfaceDemo). Specifically, a call to getNumManifolds() from the dispacther returns 0 (similar to post 7 in this topic: http://www.bulletphysics.org/Bullet/php ... 26&start=0), even though the broadphase (btDbvtBroadphase) algorithm reports there are 4 overlapping pairs with a call to getNumOverlappingPairs(). As I understand it, there should always be a btPersistentManifold for each overlapping pair. Is this not the case?

I feel like I'm probably missing something basic, but I can't figure out what it is...

Here's my pertinent "world building" code:

Code: Select all

//CD stuff
btDefaultCollisionConfiguration* colConfig = new btDefaultCollisionConfiguration();
btCollisionDispatcher* dispatcher = new btCollisionDispatcher(colConfig);
btBroadphaseInterface* broadphase = new btDbvtBroadphase();
btCollisionWorld* world = new btCollisionWorld(dispatcher, broadphase, colConfig);

//arrays for keeping mesh data, shapes, and collision objects
btAlignedObjectArray<btCollisionObject*> armCollObjs;
btAlignedObjectArray<btBvhTriangleMeshShape*> armTriMeshShapes;
btAlignedObjectArray<btTriangleMesh*> armTriMeshes;

//how above arrays are filled (bt is a pointer to a class I made to encapsulate Bullet related functions and variables)
//loop through mesh data imported from Panda3d, calling addTriangle() on armTriMeshes
bt->armTriMeshShapes.push_back(new btBvhTriangleMeshShape(bt->armTriMeshes[i], true));
bt->armCollObjs.push_back(new btCollisionObject());
bt->armCollObjs[i]->setCollisionShape(bt->armTriMeshShapes[i]);
bt->world->addCollisionObject(bt->armCollObjs[i]);
Up to here, everything seems to work fine, with mesh data drawn as expected via DebugDrawer (options: wireframe, aabb, contact points):
planarArm_screen.jpg
Now for the collision detection:

Code: Select all

bt->world->performDiscreteCollisionDetection();
btOverlappingPairCache* overlap = broadphase->getOverlappingPairCache();  //<------this returns 4, as expected
printf("num overlaps: %d\n", overlap->getNumOverlappingPairs());
int numManifolds = bt->world->getDispatcher()->getNumManifolds();   //<-------this returns 0!
printf("num manifolds: %d\n", numManifolds);
for (int i=0;i<numManifolds;i++)  // borrowed directly from CollisionInterfaceDemo
{
	btPersistentManifold* contactManifold = bt->world->getDispatcher()->getManifoldByIndexInternal(i);
	btCollisionObject* obA = static_cast<btCollisionObject*>(contactManifold->getBody0());  //separate note: why are these here?
	btCollisionObject* obB = static_cast<btCollisionObject*>(contactManifold->getBody1());
	
	int numContacts = contactManifold->getNumContacts();
	printf("num contacts: %d\n", numContacts);
	for (int j=0;j<numContacts;j++)
	{
	    btManifoldPoint& pt = contactManifold->getContactPoint(j);
	    btVector3 ptA = pt.getPositionWorldOnA();
	    btVector3 ptB = pt.getPositionWorldOnB();

	    printf("ptA: %f, %f, %f\n", ptA.x(),ptA.y(),ptA.z());
	    printf("ptB: %f, %f, %f\n", ptB.x(),ptB.y(),ptB.z());
	}

	//you can un-comment out this line, and then all points are removed
	//contactManifold->clearManifold();   
}
bt->world->debugDrawWorld();
Below I've attached a couple close-ups to show the meshes are indeed penetrating. (As an aside, I realize I'll need to eventually shrink the meshes to avoid having the arm say it's individual components are colliding with each other upon loading, but I'm currently just trying to get collision detection between meshes running, and I figure this case is as good as any! :) )

Thanks for any help anyone can provide.

On a side note, does the feature request of positive distance for concave objects mentioned here (http://www.bulletphysics.org/Bullet/php ... 47&p=18791) have any ETA? It would eventually be very useful for collision avoidance! :D
You do not have the required permissions to view the files attached to this post.
sparkprime
Posts: 508
Joined: Fri May 30, 2008 2:51 am
Location: Ossining, New York

Re: Collision detection between two btBvhTriangleMeshes

Post by sparkprime »

You can't do collision detection between two btBvhTriangleMeshes -- it's simply not implemented. Explore other shapes, like gimpact triangle mesh or compound of convex hulls.
skeen
Posts: 24
Joined: Wed Dec 08, 2010 11:59 am

Re: Collision detection between two btBvhTriangleMeshes

Post by skeen »

Try changing:

Code: Select all

bt->armTriMeshShapes.push_back(new btBvhTriangleMeshShape(bt->armTriMeshes[i], true));
to:

Code: Select all

bt->armTriMeshShapes.push_back(new btConvexTriangleMeshShape(bt->armTriMeshes[i]));
jstolarz
Posts: 14
Joined: Thu Dec 09, 2010 9:32 pm
Location: Glendale, California

Re: Collision detection between two btBvhTriangleMeshes

Post by jstolarz »

sparkprime wrote:You can't do collision detection between two btBvhTriangleMeshes -- it's simply not implemented. Explore other shapes, like gimpact triangle mesh or compound of convex hulls.
Oh. I guess I missed wherever that was mentioned. Looking into Gimpact meshes now...
skeen wrote:Try changing:

Code: Select all

bt->armTriMeshShapes.push_back(new btBvhTriangleMeshShape(bt->armTriMeshes[i], true));
to:

Code: Select all

bt->armTriMeshShapes.push_back(new btConvexTriangleMeshShape(bt->armTriMeshes[i]));
Unfortunately they are concave meshes, so I don't think this will give me the desired behavior (though I guess it'd test collisions generally)...
skeen
Posts: 24
Joined: Wed Dec 08, 2010 11:59 am

Re: Collision detection between two btBvhTriangleMeshes

Post by skeen »

jstolarz wrote:
skeen wrote: Try changing:

Code: Select all

bt->armTriMeshShapes.push_back(new btBvhTriangleMeshShape(bt->armTriMeshes[i], true));
to:

Code: Select all

bt->armTriMeshShapes.push_back(new btConvexTriangleMeshShape(bt->armTriMeshes[i]));
Unfortunately they are concave meshes, so I don't think this will give me the desired behavior (though I guess it'd test collisions generally)...
I missed that, sorry, but if they're concave meshes, then I guess your off to; either: Make a convex decomposition, or use the btGImpactMeshShape. - Just as sparkprime said.

As far as I know the convex decomposition should be the fastest.
jstolarz
Posts: 14
Joined: Thu Dec 09, 2010 9:32 pm
Location: Glendale, California

Re: Collision detection between two btBvhTriangleMeshes

Post by jstolarz »

Alright, so as far as I can tell to enable GImpact and use GImpactMeshShapes I merely have to register the collision algorithm and create the mesh shapes. So these are the changes I've made to my code:

Code: Select all

//world building changes from above
btAlignedObjectArray<btGImpactMeshShape*> armTriMeshShapes; //instead of bvh

//right after creating the world with the same dispatcher, collision config, and broadphase as before
btCollisionDispatcher* dispatcher = static_cast<btCollisionDispatcher*>(world->getDispatcher());
btGImpactCollisionAlgorithm::registerAlgorithm(dispatcher);

//again, filling the meshes with data is the same as above except for when i create the btGImpactMeshShape
bt->armTriMeshShapes.push_back(new btGImpactMeshShape(bt->armTriMeshes[i]));
Yet now when I run the app, not only do I still have no collisions, I now have no debug wireframes or bounding boxes drawing! A call to world->getNumCollisionObjects() returns 4 as expected, however, so I know they're in there... Any idea what's going on?

Also, as an alternative to iterating over (seemingly non-existent) contact manifolds, I tried directly testing two objects in collision (see images) with the following code borrowed from CollisionInterfaceDemo. However, it also found no collisions:

Code: Select all

btCollisionAlgorithm* algo = bt->world->getDispatcher()->findAlgorithm(bt->armCollObjs[0], bt->armCollObjs[1]);
btManifoldResult contactPointResult(bt->armCollObjs[0], bt->armCollObjs[1]);
algo->processCollision(bt->armCollObjs[0], bt->armCollObjs[1], bt->world->getDispatchInfo(), &contactPointResult);
btManifoldArray manifoldArray;
algo->getAllContactManifolds(manifoldArray);

numManifolds = manifoldArray.size();    //<--------returns 0!
printf("num manifolds2: %d\n", numManifolds);
for (int i=0;i<numManifolds;i++)
{
	btPersistentManifold* contactManifold = manifoldArray[i];
	btCollisionObject* obA = static_cast<btCollisionObject*>(contactManifold->getBody0());
	int numContacts = contactManifold->getNumContacts();
	printf("num contacts2: %d\n", numContacts);
	bool swap = obA == bt->armCollObjs[0];

	for (int j=0;j<numContacts;j++)
	{
	    btManifoldPoint& pt = contactManifold->getContactPoint(j);
	    btVector3 ptA = swap ?pt.getPositionWorldOnA():pt.getPositionWorldOnB();
	    btVector3 ptB = swap ? pt.getPositionWorldOnB():pt.getPositionWorldOnA();

	    printf("ptA2: %f, %f, %f\n", ptA.x(),ptA.y(),ptA.z());
	    printf("ptB2: %f, %f, %f\n", ptB.x(),ptB.y(),ptB.z());
	}
	//you can un-comment out this line, and then all points are removed
	//contactManifold->clearManifold();	
}
What am I still missing? Thanks sparkprime and skeen for your help so far!
skeen
Posts: 24
Joined: Wed Dec 08, 2010 11:59 am

Re: Collision detection between two btBvhTriangleMeshes

Post by skeen »

About the debugdrawing, maybe its because btGImpactMeshShape is more like an extension, and therefore dont offer the same functionality (wild guess). - And sadly I have no experience with the; 'btGImpactMeshShape'
sparkprime
Posts: 508
Joined: Fri May 30, 2008 2:51 am
Location: Ossining, New York

Re: Collision detection between two btBvhTriangleMeshes

Post by sparkprime »

I'm pretty sure I've had gimpact work with debug drawing before. However you do have to register some code to do the debug drawing to get any output at all. You also have to turn various flags on and off I think.

I've never tried just using bullet for collision detection so I'm not sure if you are using the API correctly to perform the actual step.
jstolarz
Posts: 14
Joined: Thu Dec 09, 2010 9:32 pm
Location: Glendale, California

Re: Collision detection between two btBvhTriangleMeshes

Post by jstolarz »

Yes, I've made and registered a DebugDraw class and turned on the various options I was interested in. It's how I got the meshes and bounding boxes displayed in the images I posted before. I guess I'll take a look at that next to see if there are any special cases for GImpact... the fact that the broadphase returns 0 when I call getOverlappingPairCache() (it used to return 4 with bvhMeshes) makes me think there's something else wrong, however (sorry, forgot to mention that in my last post).
ProfessionalUser
Posts: 14
Joined: Fri Oct 14, 2011 12:10 am

Re: Collision detection between two btBvhTriangleMeshes

Post by ProfessionalUser »

I ran into the same issue, GImpactMeshShape won't draw in debugDraw. Can anyone offer a solution?

Thanks

Update: I got AABB's drawing correctly after calling btGImpactMeshShape::udpateBounds().
User avatar
dphil
Posts: 237
Joined: Tue Jun 29, 2010 10:27 pm

Re: Collision detection between two btBvhTriangleMeshes

Post by dphil »

I assume you've written your own debug drawer that you've registered with the collision world? I am able to have GImpactMeshShapes drawn... Keep in mind, however, that the current implementation of btCollisionWorld tells the debug drawer to just draw lines for a triangle mesh shape. So if you've implemented the line drawing methods, you should be seeing something. To make it call drawTriangle instead of drawLine, I had to subclass btCollisionWorld and subclass the DebugDrawCallback class (which is where the mesh triangles are processed), replacing the drawLine calls. I then overrode debugDrawObject to make use of my DebugDrawCallback subclass instead of DebugDrawCallback.

If you are unsure if/what methods are getting called, just implement all of the debug drawer methods and put output logs in each one. It helped sort out some confusion for me when I implemented it.