Ammo convexSweepTest wrong results

In the last few days I fiddled around with ammos convexSweepTest function to create a custom character controller.
On the way I’ve hit a few road blocks:

  1. hitNormalWorld:
    I expected the hitNormalWorld to be the normal of the tri that was hit by the convexSweepTest. As it turns out that’s not the case and the hitNormalWorld is instead the vector which connects the two closest points on each shape.
    Ok fine I guess, getting the normal of the tri might still be achievable by doing something like this. However I have to edit the ammo bindings, as those don’t exist yet.

  2. convexSweepTest is returning hits although it shouldn’t:
    For this I’ve created a test project. Where I sweep test a 1m box shape onto another 1m box shape. For some reason there is a hit although mathematically they shouldn’t hit as they are 1.0001m distant from each other. Collision margins of both shapes are set to 0.
    This test also proves my first point is valid, as the normal (shown in blue) is pointing away from the box in the direction of the positive Z axis.
    I don’t have a explanation for this behaviour. I’m guessing it’s a floating point precision issue? Although 1.0001 isn’t too precise.

I am no expert in Ammo shape casts, but you should be able to get contact normals on the surface of a collider. I’ve looked at your project briefly and noticed you are setting a convex margin of zero on a box. This should technically give you a zero normal vector, if points coincide in world space. You generally don’t want to have a zero margin, unless “you really know what you are sacrificing with”.

Try giving it a few cm, like 0.04 or something. I think PlayCanvas sets it to 1 cm, which is already borderline lowest, considering the default cube is 1x1x1m. Yes, you will have a tiny penetration, but it will perform better and you should get proper normals. If the penetration is too large, you can adjust the visual mesh slightly.

I also did a custom build some years ago to get the triangle data from a raycast. I can tell you right away - it was a pain, because it was not enough to expose the tridata to IDL, you would have to create your own raycast class and expose that instead. I’m afraid I no longer have that build and don’t want to remember the dark times. You are on your own, if you’d want to proceed with it.

According to my understanding setting margin to 0 uses the actually box geometry as collision shape. If it’s set to a higher value the faces are extruded and you get a chamfer box, which means at the edges you will acutally get smoothed normals. Thats what I want to avoid as I basically want near “pixel perfect” collision detection.

Regarding performance: I understand that collision margins are a performance optimization. However the only Ammo related stuff I do per frame are about 5 convexSweepTests. So I don’t think I will get performance problems any time soon.

And thanks for the heads up on extending the ammo bindings. I think of it as a learning experince, so I may still try it out. We will see how far I get :smiley:

Good luck :slight_smile: And no, not only for rounding a shape, margin is used for collision detection resolution. You will have artifacts with a zero margin, as it is used to calculate the contact normal.

1 Like