CompoundShape messes up the contact manifold(?)

jackskelyton
Posts: 32
Joined: Mon Nov 05, 2007 3:52 pm

CompoundShape messes up the contact manifold(?)

Post by jackskelyton »

We're having a bug that seems linked to using the btCompoundShape. We're doing a simple check to see if the character can jump: we traverse the PersistentManifold and for every pair of colliding objects we average all the contact points into a single point, then pass that vector into an "OnCollision" function that checks the Y value against the Y value of the colliding RigidBodies. If the RigidBody's Y is greater than the contact point Y (i.e. the collision is occurring in the lower half of the RigidBody's collision shape) then we allow jump. It seems to work fine if we use a simple primitive like a box or sphere, but when we use a compound shape we get all kinds of bizarre values for the contact points. Our code:

Code: Select all

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

         Actor* actorA = (Actor*)(obA->getUserPointer());
         Actor* actorB = (Actor*)(obB->getUserPointer());

         if (actorA == actorB) {
            continue;
         }

         int numContacts = contactManifold->getNumContacts();

         if (numContacts) {
            // Average the contact points
            SFVector3d finalContact(0.0, 0.0, 0.0);
            btVector3 averageA(0.0, 0.0, 0.0);
            btVector3 averageB(0.0, 0.0, 0.0);

            for (int j = 0; j < numContacts; j++) {
               btManifoldPoint& point = contactManifold->getContactPoint(j);
               averageA += point.getPositionWorldOnA();
               averageB += point.getPositionWorldOnB();
            }

            double finalX = ((averageA.getX() + averageB.getX())/numContacts) * 0.5;
            double finalY = ((averageA.getY() + averageB.getY())/numContacts) * 0.5;
            double finalZ = ((averageA.getZ() + averageB.getZ())/numContacts) * 0.5;

            finalContact.Set(finalX, finalY, finalZ);

	    contactManifold->clearManifold();
            
            // Call actors' event handlers
            actorA->OnCollision(actorB, &finalContact);
            actorB->OnCollision(actorA, &finalContact);
         }
      }
   }
Our OnCollision method passes the two colliding actors and three double values: the X, Y, and Z of that averaged contact point. From the passed actors we drill down to their btRigidBodies and get the WorldTransform to compare against the contact point.

With a simple box, the difference between the character's Y and the contact point Y holds steady at around 0.4 when the character is standing on flat ground. But with a compound shape, we get values for the contact point Y that range from 0.35 to -1.24e-005.

I have implemented a number of watches and noticed something curious: the PersistentManifold will record the character-to-groundmesh collision pair twice: once with 1 contact point, and again with 4 contact points. The instance with 4 points always returns a reliable result, but the instance with 1 point tend to be one of those "1e-005" numbers. I've even seen the Manifold record a collision pair in which the character collides with itself---again, only something that happens with a compound shape. And finally (haha, I know), we tend to get an inexplicable memory leak when deallocating compound shapes. Any idea what's going on?
User avatar
Erwin Coumans
Site Admin
Posts: 4221
Joined: Sun Jun 26, 2005 6:43 pm
Location: California, USA

Re: CompoundShape messes up the contact manifold(?)

Post by Erwin Coumans »

I'm not aware of any issues related to btCompoundShape, so we need a reproduction case in Bullet.

What steps will reproduce the problem?

Which Bullet version are you using?

Thanks,
Erwin
jackskelyton
Posts: 32
Joined: Mon Nov 05, 2007 3:52 pm

Re: CompoundShape messes up the contact manifold(?)

Post by jackskelyton »

We're using 2.67. Our process is to get properties from an XML file created by our level designers and create a btRigidBody from that information. We store a pointer to our "Actor" class in the userPointer variable so that when we traverse the manifold (the code I posted above) we can manipulate the colliding actors. I can the parts of my code that create the physics object, is that what you mean?
User avatar
Erwin Coumans
Site Admin
Posts: 4221
Joined: Sun Jun 26, 2005 6:43 pm
Location: California, USA

Re: CompoundShape messes up the contact manifold(?)

Post by Erwin Coumans »

We'll upload a new Bullet 2.67 beta today, and it contains an improved ColladaConverter that allows you to make XML snapshots from an existing Bullet btDynamicsWorld. It should be fairly straightforward to use, for example:

Code: Select all

#include "ColladaConverter.h"
[...]

             m_physicsWorld->stepSimulation(timeStep);

	static bool justOnce = true;
	if (justOnce)
	{
		justOnce = false;
		ColladaConverter* converter = new ColladaConverter(m_physicsWorld);
		converter->save("c:\bullet_dump.dae");
	}
This dumps a COLLADA Physics xml file, including all collision shapes, rigidbody information and constraints in the btDynamicsWorld. Note that this snapshot save feature is new, so we try to get feedback to make improvements.

I'll post when this new beta with updated ColladaConverter is available, so you can try it, ok?
Thanks,
Erwin
jackskelyton
Posts: 32
Joined: Mon Nov 05, 2007 3:52 pm

Re: CompoundShape messes up the contact manifold(?)

Post by jackskelyton »

Sure, that would be very helpful. Thanks!