-
Notifications
You must be signed in to change notification settings - Fork 23
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
some collision shapes fall through a flat terrain with contact filtering #40
Comments
Experiments using the Small shapes seem more likely to pass through than larger ones, which makes intuitive sense. Initial focus will be on specific combinations of shapes known to be problematic, such as the one reported by ndebruyn. |
Changing the parameters of the |
Here's the pared-down test for Minie: flyCam.setEnabled(false);
cam.setLocation(new Vector3f(-10.0f, 5.0f, 10.0f));
cam.setRotation(new Quaternion(0.064f, 0.9106f, -0.156f, 0.377f));
BulletAppState bulletAppState = new BulletAppState();
bulletAppState.setDebugEnabled(true);
stateManager.attach(bulletAppState);
PhysicsSpace physicsSpace = bulletAppState.getPhysicsSpace();
Sphere sphere = new Sphere(5, 7, 1f);
HullCollisionShape hullShape = new HullCollisionShape(sphere);
PhysicsRigidBody ballBody = new PhysicsRigidBody(hullShape);
ballBody.setPhysicsLocation(new Vector3f(0f, 5f, 0f));
physicsSpace.add(ballBody);
CollisionShape heightShape = new HeightfieldCollisionShape(
new float[9], new Vector3f(2f, 1f, 2f));
PhysicsRigidBody terrainBody
= new PhysicsRigidBody(heightShape, PhysicsBody.massForStatic);
//heightShape.setContactFilterEnabled(false);
physicsSpace.add(terrainBody);
Material solidGray = new Material(assetManager, Materials.UNSHADED);
solidGray.setColor("Color", ColorRGBA.DarkGray);
terrainBody.setDebugMaterial(solidGray); |
Activating CCD solves the issue, which I find surprising since the ball doesn't move very fast. During step 52, just before making contact, the ball moves about 0.145 PSU, about 7% of its diameter. At such low speeds, CCD shouldn't be necessary. Without CCD: With CCD: ballBody.setCcdMotionThreshold(0.1f);
ballBody.setCcdSweptSphereRadius(1f); ... |
Debugging in Java as long as possible (to postpone the use of GDB) ... With both contact filtering and CCD disabled, the maximum number of contact manifolds is 1. tick 51 y=1.3866501 vy=-8.338497 numManifolds=0
tick 52 y=1.2449502 vy=-8.501997 numManifolds=0
tick 53 y=1.1005253 vy=-8.665497 numManifolds=1
tick 54 y=0.95337534 vy=-8.828997 numManifolds=1
created manifold 140193185722400
processed point 140193185722616
processed point 140193185722408
tick 55 y=0.9631649 vy=-0.47508544 numManifolds=1
processed point 140193185722616
processed point 140193185722408
tick 56 y=0.97778815 vy=0.03134674 numManifolds=1
processed point 140193185722616
processed point 140193185722408 With contact filtering enabled (and CCD still disabled), the maximum number of contact manifolds is still 1: tick 51 y=1.3866501 vy=-8.338497 numManifolds=0
tick 52 y=1.2449502 vy=-8.501997 numManifolds=0
tick 53 y=1.1005253 vy=-8.665497 numManifolds=1
tick 54 y=0.95337534 vy=-8.828997 numManifolds=1
tick 55 y=0.8035004 vy=-8.9924965 numManifolds=1
tick 56 y=0.6509005 vy=-9.155996 numManifolds=1
tick 57 y=0.49557555 vy=-9.319496 numManifolds=1
tick 58 y=0.3375256 vy=-9.482996 numManifolds=1
tick 59 y=0.17675067 vy=-9.646496 numManifolds=1
tick 60 y=0.013250738 vy=-9.809996 numManifolds=1
tick 61 y=-0.15297419 vy=-9.9734955 numManifolds=1
tick 62 y=-0.32192412 vy=-10.136995 numManifolds=1
tick 63 y=-0.49359906 vy=-10.300495 numManifolds=1
tick 64 y=-0.66799897 vy=-10.463995 numManifolds=1
tick 65 y=-0.8451239 vy=-10.627495 numManifolds=1
tick 66 y=-1.0249739 vy=-10.790995 numManifolds=1
created manifold 140535113322528
processed point 140535113322536
tick 67 y=-1.2075487 vy=-10.954494 numManifolds=1
removed manifold 140535113322528
tick 68 y=-1.3928486 vy=-11.117994 numManifolds=1
tick 69 y=-1.5808735 vy=-11.281494 numManifolds=0 The original manifold (added during tick 52) has little or no effect on the ball's motion. Also, there seem to be no A second manifold is created as the ball emerges out the bottom of the terrain, but by then it's too late to stop the ball's descent. (Minie's contact bookkeeping is confusing!) With both contact filtering and CCD enabled, the maximum number of contact manifolds increases to 2: tick 51 y=1.3866501 vy=-8.338497 numManifolds=0
tick 52 y=1.2449502 vy=-8.501997 numManifolds=0
tick 53 y=1.1005253 vy=-8.665497 numManifolds=1
tick 54 y=1.04 vy=-3.6315176 numManifolds=2
removed manifold 140034432357264
created manifold 140034432356384
processed point 140034432356392
tick 55 y=1.0412261 vy=0.07357079 numManifolds=1
processed point 140034432356392
tick 56 y=1.0417278 vy=0.03009659 numManifolds=1
processed point 140034432356392 It's a good bet that the new manifold (added during tick 53) originates from CCD. For debugging, it would nice to visualize It also would be nice to visualize all contact points [as Bullet does ... see |
Actually, |
Enabling CCD doesn't solve the issue with ndebruyn's test. The ball still falls through, albeit more slowly. |
With contact filtering enabled and CCD disabled, the 1st persistent manifold is created without any contact points, which may explain why it's ineffective. |
Contact filtering is mainly implemented in #0 btManifoldResult::addContactPoint
#1 btGjkPairDetector::getClosestPointsNonVirtual
#2 btGjkPairDetector::getClosestPoints
#3 btConvexConvexAlgorithm::processCollision
#4 btConvexTriangleCallback::processTriangle
#5 btHeightfieldTerrainShape::processAllTriangles
#6 btConvexConcaveCollisionAlgorithm::processCollision
#7 btCollisionDispatcher::defaultNearCallback
#8 btCollisionPairCallback::processOverlap
#9 btHashedOverlappingPairCache::processAllOverlappingPairs
#10 btHashedOverlappingPairCache::processAllOverlappingPairs
#11 btCollisionDispatcher::dispatchAllCollisionPairs
#12 btCollisionWorld::performDiscreteCollisionDetection
#13 btDiscreteDynamicsWorld::internalSingleStepSimulation
#14 btDiscreteDynamicsWorld::stepSimulation
Stepping through Stepping through All 9 heightfield squares will be processed. I set a breakpoint on btTriangleCallback.h line 51... After that, the This time: The next Next step: instrument the code to get a more complete picture of which triangles invalidate which contact points. |
Actually, there are only 4 heightfield squares, thus 8 triangles, none of which failed the bounding-box test. Note |
tick 52 y=1.2449502 vy=-8.501997 manifolds={}
tick 53 y=1.1005253 vy=-8.665497 manifolds={7f1359960020<0>}
tick 54 y=0.95337534 vy=-8.828997 manifolds={7f1359960020<0>}
Contact at (-0.222396,0.0381531,0.00952136) on tri(0,0) inside tri(1,1)
coords (-2,0,0)(0,0,2)(0,0,0)
marg=0.039960 oldCnt=0
Contact at (-0.0147381,0.0380638,0.00264857) on tri(1,0) inside tri(0,0)
coords (-2,0,-2)(-2,0,0)(0,0,0)
marg=0.039960 oldCnt=0
Contact at (-0.0147381,0.0380638,0.00264857) on tri(1,0) inside tri(1,1)
coords (-2,0,0)(0,0,2)(0,0,0)
marg=0.039960 oldCnt=1
Contact at (-0.00890616,0.0389959,0) on tri(2,0) inside tri(0,0)
coords (-2,0,-2)(-2,0,0)(0,0,0)
marg=0.039960 oldCnt=0
Contact at (-0.00890616,0.0389959,0) on tri(2,0) inside tri(1,0)
coords (-2,0,-2)(0,0,0)(0,0,-2)
marg=0.039960 oldCnt=1
Contact at (-0.00890616,0.0389959,0) on tri(2,0) inside tri(1,1)
coords (-2,0,0)(0,0,2)(0,0,0)
marg=0.039960 oldCnt=2
Contact at (-0.2224,0.0381437,-0.00956095) on tri(1,1) inside tri(0,0)
coords (-2,0,-2)(-2,0,0)(0,0,0)
marg=0.039960 oldCnt=0
Contact at (-0.00890623,0.0389959,0) on tri(2,1) inside tri(0,0)
coords (-2,0,-2)(-2,0,0)(0,0,0)
marg=0.039960 oldCnt=0
Contact at (-0.00890623,0.0389959,0) on tri(2,1) inside tri(1,0)
coords (-2,0,-2)(0,0,0)(0,0,-2)
marg=0.039960 oldCnt=1
Contact at (-0.00890623,0.0389959,0) on tri(2,1) inside tri(1,1)
coords (-2,0,0)(0,0,2)(0,0,0)
marg=0.039960 oldCnt=2
Contact at (-0.00890623,0.0389959,0) on tri(3,1) inside tri(0,0)
coords (-2,0,-2)(-2,0,0)(0,0,0)
marg=0.039960 oldCnt=0
Contact at (-0.00890623,0.0389959,0) on tri(3,1) inside tri(1,0)
coords (-2,0,-2)(0,0,0)(0,0,-2)
marg=0.039960 oldCnt=1
Contact at (-0.00890623,0.0389959,0) on tri(3,1) inside tri(1,1)
coords (-2,0,0)(0,0,2)(0,0,0)
marg=0.039960 oldCnt=2
tick 55 y=0.8035004 vy=-8.9924965 manifolds={7f1359960020<0>} |
Surprise: 6 contacts, all with Y < 0.03996 |
All 6 contacts lie close together near the center of the grid, where 6 triangles meet... The 3 contacts with Z=0 lie on the -X side of the grid, on the edge shared by tri(0,0) and tri(1,1):
The other 3 contacts (with non-zero Z) also lie very near that same edge:
I still need to understand why none of the Y values is 0.040, which probably means understanding the Gilbert-Johnson-Keerthi distance algorithm. |
In For the first invocation of If |
Still using "DebugDp" natives ... The first loop in getClosestPointsNonVirtual exits from line 794 with The second loop exits from line 911 with
Note the normal isn't vertical, and it's the same as the normal passed to |
Reading this article has me wondering whether |
At the start of tick 54, the lowest vertex of the hull shape is vertex[0] with world location (-0.22234385, -0.021553636, 0.0) |
Stepping through Changing Next step will be to add mechanisms to configure the depth solver at runtime and compare performance. |
After many digressions, I got the Minkowski PDS working in Minie. Using |
I've been busy with other issues. Unless this issue is solved before the next Minie release, I'll probably disable contact filtering by default. (The option has been enabled by default since it was introduced in 2021.) |
I disabled contact filtering by default in Libbulletjme v21.2.1, but now I'm having second thoughts about that decision. In The next step would be to create more simple testcases for detailed study, including some that fail even with filtering disabled. |
Simple testcases aren't easy to find. |
Focusing on drops that fall through: after studying more than a dozen instances, all were among the first 16 drops created after restarting the scenario. |
Concentrating the drops helps a little, but probably not enough to "crack" this issue. It occurs to me that |
Bullet collision shapes for rigid bodies fall into 3 categories: convex (defined by supporting vertices), concave (composed of thin triangles), and compound (composed of sub-shapes). Perhaps there's a need for a new terrain shape, one with greater thickness, implemented more like a compound shape than a concave. |
As discussed at the JME forum: https://hub.jmonkeyengine.org/t/rounded-object-falls-through-terrain/47584
Changes to the test app that prevent fallthrough:
SphereCollisionShape
orMultiSphere
Changes to the test app that don't prevent fallthrough:
GImpactCollisionShape
The text was updated successfully, but these errors were encountered: