Bullet Physics - Objects pass through certain triangles in mesh

Started by
6 comments, last by Conoktra 9 years, 10 months ago

Hello.

I am using Bullet Physics 2.82 and am getting some weird results. I build some voxel terrain and pass the mesh information to Bullet Physics (via btTriangleIndexVertexArray with btBvhTriangleMeshShape). It works fantastically, except that in certain spots basic shapes can fall through the terrain. Here is a video of it:

I have tried quite a bit to fix it, and post here as a "last resort" of sorts. Help is very much appreciated! I have tried:

  • Rebuilding Bullet Physics with double precision.
  • Increasing the cycles-per second to 120 and even 240 simulations/second.
  • Increased all objects' collision margins (btCollisionShape::setMargin()) to larger values (0.1, 0.5, 1.0).
  • Reversed the vertex winding order (in-case it was a backward facing polygon allowing the fall-through).

And still objects fall through the terrain! There is no visual deformity-- the terrain is built and displayed correctly. The debug drawer also shows the terrain is built in that area. The physics shape is built off of the same data that is used for the rendering. Any idea on what could cause this?

Terrain initialization (performed on each chunk of the terrain's octree):


// pre-filled, just here to show you the declaration
s32 * indices;
btScalar * vertices;

physicsMesh = new btTriangleIndexVertexArray(mesh->indices.size() / 3, indices, sizeof(s32) * 3, mesh->vertices.size(), vertices, sizeof(btScalar) * 3);

physicsShape = new btBvhTriangleMeshShape(physicsMesh, true, true);
physicsShape->setMargin(0.04); // tried changing to 0.1/0.5/1.0

btVector3 inertia(0, 0, 0);
physicsShape->calculateLocalInertia(0.0, inertia);

physicsMotionState = new btDefaultMotionState(btTransform(btQuaternion(0, 0, 0, 1), btVector3(0, 0, 0)));
btRigidBody::btRigidBodyConstructionInfo rigidBodyCI(
	0,  // mass
	physicsMotionState,// initial position
	physicsShape,      // collision shape of body
	inertia   // local inertia
);

physicsRigidBody = new btRigidBody(rigidBodyCI);
physicsRigidBody->setLinearVelocity(btVector3(0, 0, 0));
physicsRigidBody->setAngularVelocity(btVector3(0, 0, 0));
physicsRigidBody->setFriction(1.0);

// This is done in a separate threads.  Making it single-threaded made no difference.
bulletManager.lock();
bulletManager.addRigidBody(physicsRigidBody);
bulletManager.unlock();

Basic shape initialization:


physicsShape = new btSphereShape(minGroupRange);
physicsShape->setMargin(0.04); // tried 0.1/0.5/1.0

btVector3 inertia(0, 0, 0);
physicsShape->calculateLocalInertia(1.0, inertia);

btRigidBody::btRigidBodyConstructionInfo rigidBodyCI(
	1.0,   // mass
	this,  // initial position
	physicsShape,  // collision shape of body
	inertia // local inertia
);

physicsRigidBody = new btRigidBody(rigidBodyCI);
physicsRigidBody->clearForces();
physicsRigidBody->setLinearVelocity(btVector3(0, 0, 0));
physicsRigidBody->setAngularVelocity(btVector3(0, 0, 0));
//physicsRigidBody->setActivationState(DISABLE_DEACTIVATION);

BulletManager::get().addRigidBody(physicsRigidBody);

And updating Bullet Physics:


dynamicsWorld->stepSimulation(timer.getDeltaTime_Seconds());
//dynamicsWorld->stepSimulation(timer.getDeltaTime_Seconds(), 10, 1.0 / 240);
Advertisement
It is hard to see in the video (it is low res for me) the physics objects seem pretty small.

Physics objects work best when they are pretty large for most physics engines, small objects tend to teleport through surfaces pretty easily. Some engines support flags to test if an object passed through a surface and then back up iteratively and do the work, but usually it requires extra flags since it needs extra processing. I don't know if bullet has such flags.

Also searching the Bullet docs, they have problems with small objects (<10cm) in their engine. The recommendation seems to be to scale the physics, being careful to set things to linear, exponential, or other scales as needed.
After many hours of watching, I think I see the problem.
It appears that some of the objects are…how you say…“falling through” parts of the terrain.


In a mesh-based collision test the most common reason for this is “slivers”. These are long thin triangles that cause issues with intersection formulas on computers, particularly with floating-point values (less so with doubles).

Why don’t you check the original mesh in that area in a tool or draw its triangles and check it in your engine and see what kind of triangles are living there?


L. Spiro

I restore Nintendo 64 video-game OST’s into HD! https://www.youtube.com/channel/UCCtX_wedtZ5BoyQBXEhnVZw/playlists?view=1&sort=lad&flow=grid

Hmm... watching your video, it seems to happen at the transition between the left and right terrain-blocks. At some times you can observe, that the sphere movement got blocked for a small duration until it falls through the mesh. Maybe it got caught between two different tri -meshes and the upper one (+gravity) pressed it through the other one. Double check the transition of your two blocks, check if it works on a single block only. Check your forces (are they building up too fast ? ).

Why don’t you check the original mesh in that area in a tool or draw its triangles and check it in your engine and see what kind of triangles are living there?


Following up on Spiro, I suggest you add the ability to draw a wireframe of your mesh, highlight shared edges and non-shared edges (and vertices), draw normals for each vertex and face, and counts triangles, slivers, denormalized triangles, etc.

The very first thing you should ever get up and running in any graphics engines is your debug drawing facilities. smile.png

Sean Middleditch – Game Systems Engineer – Join my team!

Bullet debug draw should give you the ability to draw contact normals and so on which should help.

Does this problem occur with all collision shapes for just spheres ? 2.82 seems to have have a few new issues with heightfield and triangle mesh collisions which previous versions didn't so that might also be worth looking at.

What is the size of your sphere (minGroupRange ) ?

I had same or similar problem

Try changing m_fixContactNormalDirection from 1 to 0 in constructors of btGjkPairDetector

That helped me.

Thank you to everyone the help! It turns out it was the "sliver" problem. Marching cubes was making some triangles that where simply too small and narrow in certain places. Tweaking the scale was able to increase the stability. Thanks again.

This topic is closed to new replies.

Advertisement