DanielChappuis / reactphysics3d

Open source C++ physics engine library in 3D
http://www.reactphysics3d.com
zlib License
1.54k stars 223 forks source link

Assert fails whenever a new capsule is added #150

Closed macmv closed 4 years ago

macmv commented 4 years ago

This assert keeps crashing my game:

https://github.com/DanielChappuis/reactphysics3d/blob/5c736565a78ad2838524957d59797c5ebb643b96/src/collision/NarrowPhaseInfo.cpp#L68

It is being called from

https://github.com/DanielChappuis/reactphysics3d/blob/5c736565a78ad2838524957d59797c5ebb643b96/src/collision/narrowphase/SAT/SATAlgorithm.cpp#L439

Which is called from

https://github.com/DanielChappuis/reactphysics3d/blob/5c736565a78ad2838524957d59797c5ebb643b96/src/collision/narrowphase/SAT/SATAlgorithm.cpp#L265

And this contactNormal, or normalWorld, is created here:

https://github.com/DanielChappuis/reactphysics3d/blob/5c736565a78ad2838524957d59797c5ebb643b96/src/collision/narrowphase/SAT/SATAlgorithm.cpp#L253

The world I have setup is a static body with a concave mesh containing 20000 triangles, and a cube. The capsule is being created nearby the cube and nearby the mesh. If the capsule is created too close to the mesh, then this error happens.

DanielChappuis commented 4 years ago

Thanks for reporting this.

Can I ask you the value of the contactNormal vector ? Is it a zero vector ?

macmv commented 4 years ago

It is never zero. It varies between tests , as I haven't found a consistent way to reproduce this. On the most recent test, for example, it was {x = 0.00103093591, y = 0.4852705, z = 0.456292152}. When running it again, I got {x = -0.194580257, y = 0.589551449, z = 0.0647938699}

I'm working on making a re-producible program that demonstrates this.

DanielChappuis commented 4 years ago

It's a unit contact normal and therefore its length should be 1.

It would be great if you can help me reproduce this issue on my side.

macmv commented 4 years ago

I was able to make a small program to re-produce this issue. The file is attached. I'm running this on version 0.7.1, not on master. I created a plane, from four vertices, as a concave mesh. I then put this in the world as a static object, at the origin. I then made a capsule at (0, 0.1, 0), with size (1, 1). When I run this program, the first update call causes the assert, with the contactNormal being (0, 0, 0). I'm not sure if this is the same issue, as my other program was failing with non-zero contactNormals, but it definitely seems similar.

test.cpp.tar.gz

macmv commented 4 years ago

That program updates the simulation by zero time, not 1/20 of a second. Changing it to 1/20.0, or 1/60.0, does not affect the result.

macmv commented 4 years ago

If I create the capsule at (0, 1, 0), it fails when the capsule hits the ground. However, if I create it at (0, 1, 0), and rotated by the quaternion rp3d::Quaternion::fromEulerAngles(0, 0, 10), then it does not fail at all.

DanielChappuis commented 4 years ago

I have been able to reproduce your case on my side. The issue seems to happen when two neighbor triangle faces of the mesh have normals in the opposite direction. I have made a change in this commit in the master branch to avoid zero normal in this case. It solves the issue with your example. Not sure if it will solve the problem for your bigger mesh.

For instance, in your simple example your two faces are not oriented in the same direction. One is oriented clockwise and the other is oriented counter clockwise and therefore your two triangle faces have normal in the opposite direction. I am not sure it is wanted but it is a bit strange for a mesh to have two neighbor faces with normals in the opposite direction.

macmv commented 4 years ago

That does indeed fix the problem with the test program, however my larger program is still failing. I do not think it is an issue with the normals, as I am using the same data to render all of the triangles in that mesh, and they all appear to be facing the correct direction in the render. I am still trying to re-create the original bug in a testing environment.

I mixed up the normals in that sample program. The intent was for them to both be facing upward.

macmv commented 4 years ago

It turns out that whenever you construct a body with a non-unit quaternion, then it makes the normalWorld not a unit vector. I have been doing this by accident, which has caused the error. I think to fix this, you will need to either require the Transform that people pass to DynamicsWorld::createRigidBody to have a unit quaternion, or you will need to normalize it yourself.

Fell free to close this issue if I missed something in the docs that said this, otherwise I can make a patch that fixes this.

DanielChappuis commented 4 years ago

Thanks for your feedback.

I have added some checks when creating a body in this commit in the develop branch. Note that this will be part of the next version of the library which will be release probably this week.

I am closing this issue.