find a way of fixing wrong collision normals in edge collisions
Asked Answered
P

1

1

The main problem is that Bullet 2 (2.82, to be specific - and perhaps Bullet 3 too, haven't checked it yet) processes edge collisions lousily, generating skewed reaction normals.

Test case 1: a small btBoxShape, positioned (0,9,0), aligned vertically, falls onto another box's (made from btBoxShape also) face, coaligned. The normal is computed properly, the collision happens only in Y (vertical) axis. The box slightly bounces on OY axis and stays centered around it.

case1

Test case 2: a small box, positioned (0,9,0) aligned vertically, (ditto) falls onto another box's face, (this time made from btBvhTriangleMeshShape made from 2 coplanar triangles), also coaligned. The normal is computed improperly, the collision happens in all axes. The box bounces to the side, sometimes (depending on specific collision coordinates) very visibly.

case2

Even hard-coding the normal and recalculating the collision points based on it (see below) doesn't help.

//newNormal was set to hard-coded value of (0,-1,0) before
cp.m_normalWorldOnB = colObj0Wrap -> getWorldTransform().getBasis() * newNormal;
cp.m_positionWorldOnB = cp.m_positionWorldOnA - cp.m_normalWorldOnB * cp.m_distance1;
cp.m_localPointB = colObj0Wrap -> getWorldTransform().invXform( cp.m_positionWorldOnB 

NB using btAdjustInternalEdgeContacts doesn't help in any visible way, despite setting tri info properly and verifying the code is executing alright. While it does work and gives some minor improvement to simulation's reliability (although at quite high CPU cost), it still doesn't solve this particular issue.

The question is: how to fix case 2's behaviour to match case 1's. Any advice how to avoid this situation (code kludges welcome), or why this doesn't work the way it should are welcome.

Further reference:

https://github.com/bulletphysics/bullet3/issues/92

http://www.bulletphysics.org/Bullet/phpBB3/viewtopic.php?f=9&t=8113

https://bullet.googlecode.com/files/GDC10_Coumans_Erwin_Contact.pdf

https://code.google.com/p/bullet/issues/detail?id=27

http://www.bulletphysics.org/Bullet/phpBB3/viewtopic.php?f=9&t=4603

Parliamentarianism answered 7/11, 2014 at 16:25 Comment(0)
P
1

The problem happened because there are multiple collisions happening between the two objects - the same goes with sphere<->tri collision. Not only does the collision detector detects the tri surface collision, ending the iteration for the surface triangle (as expected), but also it keeps traversing the BVH (also as kind-of-expected), resulting in another collision with the adjacent triangle's edge. This can be reproduced in many ways, e.g. by throwing an object close to a trimesh edge (but still on the inside part of the mesh!), by throwing an object near an internal tri border (edge) but asymmetrically (symmetric drop would result in edge forces canceling out). The object will fly to the side (sometimes wildly) even if the surface is perfectly flat at that point.

The only versatile solution that came to my mind and doesn't require a thorough rewrite of Bullet 2 code is to filter the colliding object's manifold in e.g. in gContactStartedCallback, finding all surface collisions and removing all edge collisions for all edges adjacent to that surface. Watching for numContacts >= 2 on given trimesh's manifolds is usually the way to go; this shouldn't happen too often, and checking a couple of points on a manifold is not that CPU intensive.

Removing contacts based on their distance also works wonders here, although that's way too crude/context specific of a fix to be used in production code IMO. I'm still looking for a simpler and more efficient solution though.

Also, a partial workaround (as noted in one of the forum discussions) was to change the timestep values; the default one fails for triangle meshes vs any object moving with reasonable speed. For "regular speeds", fixed timestep of max 1/300 is needed, for "high speeds" 1/600 or even less, YMMV. Note that it increases the CPU load a lot and only reduces the problem, in many situations not solving it at all.

The related issue has been posted on Bullet's issue tracker here.

Parliamentarianism answered 18/11, 2014 at 13:49 Comment(4)
Thank. +1 It would be even better if you also attach a link to some (official?) tutorials, in addition to the bug tracker. XDEmbroil
Specifically, I am trying to solve #25606159 : a btRigidBody sliding on 2 very-near btRigidBody. Unfortunately, its current best answer (using ray) is a hack. It is too expensive & tedious for random debris. I guess the way to fix would involve btInternalEdgeUtility or ContactAddedCallback. However, it probably works only to resolve normal conflict within a single btBvhTriangleMeshShape.Embroil
@Embroil the only advice I can give you in that case is to manually filter the collision, indeed by using callbacks (like I've mentioned, btInternalEdgeUtility didn't work too good in my case). In my app, in ContactAddedCallback I've added (amongst other things) a call to a filtering method, gist.github.com/FyiurAmron/3fa2d6b55fd96e50a6cce93f5859f680 - having something similar is IMVHO the best solution here, if recompiling Bullet with custom filtering code ain't an option. Just check if both contacts are the ones you want to detect, and if so, remove them (or one of them).Parliamentarianism
Hmm, it sounds good. If you decide to post this snippet as a solution in that capsule question, I will upvote it there too. Thank.Embroil

© 2022 - 2024 — McMap. All rights reserved.