btHeightfieldTerrainShape : item collides but falls through

Post Reply
tardygrade
Posts: 5
Joined: Tue Nov 11, 2014 9:42 pm

btHeightfieldTerrainShape : item collides but falls through

Post by tardygrade »

Hi,

I am very new to bullet physics and so far I made a quick test with one btstaticplane collision shape to serve as a terrain and one object that falls on it. That worked well. But then I wanted to try a more complex shape to represent terrain and opted for btHeightfieldTerrainShape. To make things simple I just set all heights to 0 for my tests. But now I am having a problem - the item hits the field ( I can see that it direction changes when it hits the mesh), but also falls through, as shown in the pictures. In first pic you can see it falling down. In the second one you see that it falls under the terrain but it did collide and the collision changed it's direction.

Does anyone have any ideas ? I spent a couple of hours so far, but can't figure out what the issue is. (I also tried flipping quads in the heightfield constructor but that didn't seem to help).

Thanks !

P.S. The output is from debug draw, so this is what bullet has. One odd thing is that I don't see any normals on heightfield terrain, but I dont know if that's the problem or not.
phys1.png
phys1.png (24.38 KiB) Viewed 19991 times
phys2.png
phys2.png (24 KiB) Viewed 19991 times
tardygrade
Posts: 5
Joined: Tue Nov 11, 2014 9:42 pm

Re: btHeightfieldTerrainShape : item collides but falls thro

Post by tardygrade »

UPDATE: This seems to be related to the object size. If , in VehicleDemo.cpp app I go to DemoApplication::setShootBoxShape () and change the box Vector from

btVector3(0.5, 0.5, 0.5)

TO

btVector3(0.022, 0.500, 0.008)

the default app will start "misbehaving" as well. Basically it will shoot out these stick-objects , they will hit the ground , spin, etc, but once they are done spinning they will just fall through the ground. So this seems to have something to do with object size and terrain heightfield interaction.

Any ideas ?
xexuxjy
Posts: 225
Joined: Wed Jan 07, 2009 11:43 am
Location: London

Re: btHeightfieldTerrainShape : item collides but falls thro

Post by xexuxjy »

The 'standard' collision margin on bullet is 0.04 so if your objects have sizes below that you're going to run into difficulties.
It's generally recommended to scale up your objects up based on the following :

http://www.bulletphysics.org/mediawiki- ... _The_World
lunkhound
Posts: 99
Joined: Thu Nov 21, 2013 8:57 pm

Re: btHeightfieldTerrainShape : item collides but falls thro

Post by lunkhound »

The heightfield collision shape is treated as just a thin polygonal surface. The terrain has no thickness to it. This can cause 2 issues:
  • 1. fast moving small objects (without CCD enabled) can fall right through and never even detect a collision (just turn on CCD for such objects)
    2. if an object ends up penetrating the heightfield deeply enough, it can start colliding with the back sides of the polygons and end up getting pushed deeper underground
For the second issue, I use a contact-added callback to flip the normal if bullet detects a collision with the backside of a triangle. Note this works with static concave triangle meshes as well as heightfields.
Normally Bullet doesn't care about triangle winding order, but in order to use this callback, the winding order matters.
Here is the code I'm using for one-sided triangle collision:

Code: Select all

static bool myCustomMaterialCombinerCallback(
    btManifoldPoint& cp,
    const btCollisionObjectWrapper* colObj0Wrap,
    int partId0,
    int index0,
    const btCollisionObjectWrapper* colObj1Wrap,
    int partId1,
    int index1
    )
{
    // one-sided triangles
	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;
        }
    }

    //this return value is currently ignored, but to be on the safe side: return false if you don't calculate friction
    return false;
}

void BulletPhysics::init()
{
    // somewhere in your init code you need to setup the callback
    gContactAddedCallback = myCustomMaterialCombinerCallback;
}
tardygrade
Posts: 5
Joined: Tue Nov 11, 2014 9:42 pm

Re: btHeightfieldTerrainShape : item collides but falls thro

Post by tardygrade »

Thanks for the replies !

Yeah - I was trying to mess around with sizes but only at 10 centimeters minimum per dimension it started working. But even then it seems like it would have some issues now and then.

The second solution must be it - thats exactly what's happening. It's not a fast object, so i don't need CCD, but its gotta be the second thing. It's basically falls, hits, then dangles on the floor as if it's hitting something (probably those backfaces you're refrring to), then falls through it.

I am going to try your code out and see if that helps - thanks !
tardygrade
Posts: 5
Joined: Tue Nov 11, 2014 9:42 pm

Re: btHeightfieldTerrainShape : item collides but falls thro

Post by tardygrade »

Wow... Literally a 10-second cut and paste of the code you posted and hours of frustration gone. I only had to add

_terrain->setCollisionFlags(_floor->getCollisionFlags() | btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK);

Weird that they wouldn't include this behavior by default in btTerrainHeighfieldShape - who would want the current behavior by default !?? But maybe it's just me not getting the whole picture yet and there's some deeper reasoning behind it.

In any case - thanks again !
lunkhound
Posts: 99
Joined: Thu Nov 21, 2013 8:57 pm

Re: btHeightfieldTerrainShape : item collides but falls thro

Post by lunkhound »

Glad to hear it worked!

Yes the default behavior -- colliding with the back faces of triangles -- doesn't seem very useful. It caused me lots of problems.
It is really bad when you have a jointed object like a ragdoll and one of its collision objects manages to penetrate the ground or a wall deep enough to start colliding with the back faces, meanwhile the rest of the ragdoll is colliding with the front faces. It leads to an endless herky-jerky vibration on the ragdoll as the constraint solver tries to solve the unsolveable.

Oh and thanks for pointing out the collision flag I forgot!
Flix
Posts: 456
Joined: Tue Dec 25, 2007 1:06 pm

Re: btHeightfieldTerrainShape : item collides but falls thro

Post by Flix »

I've not tried the fix proposed by lunkhound yet, but it looks interesting and I guess it could be useful for fixing problems with small bodies (such as parts of convex-decomposed shapes) getting stuck under the ground (when the ground mesh has a proper winding). Thanks for sharing it :D

There are still two things I'm not sure about:
1) btAdjustInternalEdgeContacts(...) [the method that can be used inside the same callback to fix some possible internal edge problems] already calculates a normal AFAIK: so it's probably not possible to use both approaches together.
2) the faceNormals are calculated on the fly. Maybe they can be cached somewhere and reused.

Beside that, it seems a good solution :) Thanks again.

P.S. I don't have enough knowledge [of btAdjustInternalEdgeContacts(...), btTriangleInfoMap and btGenerateInternalEdgeInfo(...)] to understand if a similiar approach can be embedded inside a new "type" of btAdjustInternalEdgeContacts(...) or not...

[Edit:] I've found out that btAdjustInternalEdgeContacts(...) already accepts the following flags:

Code: Select all

enum btInternalEdgeAdjustFlags
{
	BT_TRIANGLE_CONVEX_BACKFACE_MODE = 1,
	BT_TRIANGLE_CONCAVE_DOUBLE_SIDED = 2, //double sided options are experimental, single sided is recommended
	BT_TRIANGLE_CONVEX_DOUBLE_SIDED = 4
};
However I'm not sure that one-sided and double-sided refers to one-sided and double-sided collision (most likely it's just the the internal edge fix that is applied on one or both sides).
Maximinus
Posts: 3
Joined: Wed Jan 28, 2015 6:41 pm

Re: btHeightfieldTerrainShape : item collides but falls thro

Post by Maximinus »

lunkhound wrote:The heightfield collision shape is treated as just a thin polygonal surface. The terrain has no thickness to it. This can cause 2 issues:
  • 1. fast moving small objects (without CCD enabled) can fall right through and never even detect a collision (just turn on CCD for such objects)
    2. if an object ends up penetrating the heightfield deeply enough, it can start colliding with the back sides of the polygons and end up getting pushed deeper underground
For the second issue, I use a contact-added callback to flip the normal if bullet detects a collision with the backside of a triangle.
Well, yes, very much so. I want to thank you both lunkhound and tardygrade for these great question and answer. I'm developing an open-world car game using Bullet and a btHeightfieldTerrainShape, and I have this very exact problem that you listed as number 2. I had trouble understanding it but after I read your post, and implemented your fix, I am very pleased with the results. Works like a charm now.

Here's a demonstration video (quite old, I'll do a newer one soon) https://www.youtube.com/watch?v=KgmqcfUzccI

And here's a screenshot (not showing the bug)
Image
kingpin1177
Posts: 1
Joined: Sun Jul 22, 2018 9:44 pm

Re: btHeightfieldTerrainShape : item collides but falls through

Post by kingpin1177 »

I've integrated the contact-added callback solution provided by Lunkhound and am still having rigid-body objects fall through the btHeightfieldTerrainShape. I've scaled down the size of triangles which helps a bit, but doesn't solve the problem completely. Any other suggestions would be greatly appreciated!
User avatar
drleviathan
Posts: 849
Joined: Tue Sep 30, 2014 6:03 pm
Location: San Francisco

Re: btHeightfieldTerrainShape : item collides but falls through

Post by drleviathan »

I tested lunkhound's solution to try to solve a problem I've been having with thin objects falling through mesh floors. It didn't help with that problem but in the process I discovered that I was setting the continuous collision detection (CCD) parameters wrong on these thin objects. I was setting both CcdSweptSphereRadius and CcdMotionThreshold too big. Using a proxy sphere closer to the thickness of my thin objects and setting the motion threshold to be the sphere's diameter appears to have solved my tunneling problems.

Meanwhile, I did apply lunkhound's solution to my character object so that it could walk out through back-facing triangles in mesh geometry. It works well for that, and also helps the penetration resolution code work better.

I note that lunkhound's algorithm assumes the triangle always corresponds to colObj1Wrap rather than colObj0Wrap. This appears to always be true for the cases I was checking... but I wonder if it could ever fail.
User avatar
drleviathan
Posts: 849
Joined: Tue Sep 30, 2014 6:03 pm
Location: San Francisco

Re: btHeightfieldTerrainShape : item collides but falls through

Post by drleviathan »

Update: I was using lunkhound's collision normal callback trick for the game character so it could walk through backfacing triangles in the event it was trapped behind the mesh. However we discovered that this introduced an occasional glitch when the character moved across seams between two mesh objects -- the character would get launched when it suddenly discovered it was in penetration with a previously ignored triangle. I had to remove the callback.

Image
Post Reply