TriMesh with CapsuleZ fails

Post Reply
frogdog
Posts: 4
Joined: Wed Sep 16, 2015 4:17 pm

TriMesh with CapsuleZ fails

Post by frogdog »

Hello,

I am using btBvhTriangleMeshShape for all static geometry in my game. I then have spears which are represented by rigid bodies using btCapsuleShapeZ shapes.

The spears fall through only certain parts of the geometry, but always the same parts. I have simplified the issue in a modified version of the BasicDemo, which is attached, where the capsule is dropped onto the exact problem part of the geometry in question.

I have tried scaling up the world so as to get the spears radius (possibly the problem part?) into a more suitable range, but it didn't appear to make much of a difference.

I have also tried setting CCD for the spear, which also had no effect.

I have checked the normals, which do appear to be all facing the same (correct) way.

I'd be grateful if anyone has seen and found a way of fixing this issue?

Many thanks.
Attachments
BasicDemo.zip
Capsule falling through tri mesh geometry
(40.31 KiB) Downloaded 263 times
frogdog
Posts: 4
Joined: Wed Sep 16, 2015 4:17 pm

Re: TriMesh with CapsuleZ fails

Post by frogdog »

Does anyone have any solution or advice for the above problem?
Maximinus
Posts: 3
Joined: Wed Jan 28, 2015 6:41 pm

Re: TriMesh with CapsuleZ fails

Post by Maximinus »

Hi frogdog, I do have encountered the same issue.

I've come up with two counter-measures that, while not perfect, do satisfyingly mitigate the problem.

My diagnosis of the problem is "some collisions against btBvhTriangleMeshShape and btHeightfieldTerrainShape
fail : they either do not generate a contact point observable with btIDebugDraw,
or collide with the "back sides of the polygon" and get pushed in the direction
opposite to the expected one".

An important condition to trigger the bug (and to find counter measures) is that the bug does
happen when the 2 colliding objects have vastly different sizes, that is, the size of the triangles
of btBvhTriangleMeshShape and the size of the collShape of the colliding object.

One thing I tried that did not work is enabling continuous collision detection. It does not change
the behavior of the observed problem, and it is not allowed/implemented for btCompoundShape
(it needs collShape with isConvex() returning true to work).

This problem is observable in the official Demo "ConcaveConvexcastDemo" from version 2.82 r2704 :
many boxes do fall through on colliding with the floor.
The problem does no longer happen after doubling the box size :

Code: Select all

ConcaveConvexcastDemo.cpp:367 btCollisionShape* colShape = new btBoxShape(btVector3(2,2,2));
It also does no longer happen after halving the floor triangle size :

Code: Select all

ConcaveConvexcastDemo.cpp:33 const float TRIANGLE_SIZE=4.f;
For the newer version 2.83, I did not manage to compile it with my toolchain (Mingw32),
and compiling it with Visual Studio 2012, I could not find this demo.

Counter-Measure #1 : flip the normal in the collision-added-callback on some condition.
I've found this thread on the forums http://bulletphysics.org/Bullet/phpBB3/ ... hp?p=34385, in short it says
- register a callback

Code: Select all

 gContactAddedCallback = myCustomMaterialCombinerCallback; 
- for offending objects, set their collision flags to process the custom callback

Code: Select all

 body->setCollisionFlags(body->getCollisionFlags() | btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK); 
- on contact involving a shape of type triangle, flip the normal if it points the wrong way

Code: Select all

if (colObj1Wrap->getCollisionShape()->getShapeType() == TRIANGLE_SHAPE_PROXYTYPE)
{
    auto triShape = static_cast<const btTriangleShape*>( colObj1Wrap->getCollisionShape() );
    const btVector3* v = triShape->m_vertices1;
    btVector3 faceNormalLs = btCross(v[1] - v[0], v[2] - v[0]);
    faceNormalLs.normalize();
    btVector3 faceNormalWs = colObj1Wrap->getWorldTransform().getBasis() * faceNormalLs;
    float nDotF = btDot( faceNormalWs, cp.m_normalWorldOnB );
    if ( nDotF <= 0.0f )
    {
        // flip the contact normal to be aligned with the face normal
        cp.m_normalWorldOnB += -2.0f * nDotF * faceNormalWs;
    }
}
Counter-Measure #2 : sub-divide the triangles of my btBvhTriangleMeshShape to have smaller shapes
The implementation would depend on your particular implementation, with my car game it goes like this :

Large road segments : vehicle falls through when colliding the rigid body (the chassis) with high velocity :
Image

Short road segments : vehicle does not fall through
Image

After some testing, I've come to the conclusion that the issue is mitigated with both counter-measures
applied. Do keep me informed if you have any other ideas, or if these suggestions work for you.

@Erwin Coumans : any suggestion?
Last edited by Maximinus on Wed Apr 24, 2019 4:18 pm, edited 1 time in total.
frogdog
Posts: 4
Joined: Wed Sep 16, 2015 4:17 pm

Re: TriMesh with CapsuleZ fails

Post by frogdog »

Hi Maximinus,

Yes your observations align completely with my own. Size difference appears to be the root cause, however the size difference does not appear to be extreme.

Not only does the size difference between rigid body and static mesh tri appear to cause the bug, but it can also be triggered fairly reliably if the size differences of a collision shape primitive is large (a box of dimensions 1, 1, 20, and also a thin cylinder of radius 20 and thickness of 1).

As for the custom material callback, I've had that bit of code in for a while, recently taken out so as to get a direction of contact normal back from ray cast results (rays can hit same tris as rigid bodies collide with, so would be flagged as using custom material callback). I didn't recall this fixing the issue, though like you said, did mitigate it.

I could sub divide the collision mesh coming in from the models (In fact I will try this and cross my fingers :wink: ), though the size difference in my linked demo doesn't appear as though it should cause an issue.

I'll let you know if that solves the issue.

Thanks.
Post Reply