Browse Source

Documentation for internal edge removal algorithm

Jorrit Rouwe 1 year ago
parent
commit
92ddd83ace

+ 1 - 0
Docs/APIChanges.md

@@ -6,6 +6,7 @@ Changes that make some state saved through SaveBinaryState from a prior version
 
 ## Changes between v4.0.2 and latest
 
+* 20240120 - *SBS* - Implemented enhanced internal edge removal algorithm. This breaks the binary serialization format for BodyCreationSettings. (94c1ad811b95c72f4d3bb6841c73c1c3461caa91)
 * 20240113 - VehicleConstraint::CombineFunction now calculates both longitudinal and lateral friction in 1 call so there can be dependencies between the two. (d6ed5b3e7b22904af555088b6ae4770f8fb0e00f)
 * 20240105 - CharacterVirtual will now receive an OnContactAdded callback when it collides with a sensor (but will have no further interaction). You may need to update the logic in your CharacterContactListener to ignore those contacts. (fb778c568d3ba14556559324671ffec172957f5c)
 * 20240101 - Renamed SensorDetectsStatic to CollideKinematicVsNonDynamic and made it work for non-sensors. This means that kinematic bodies can now get collision callbacks when they collide with other static / kinematic objects. It can also affect the order in which bodies are passed in the ContactListener::OnContactValidate callback. (2d607c4161a65201d66558a2cc76d1265aea527e)

+ 18 - 0
Docs/Architecture.md

@@ -411,6 +411,24 @@ Fast rotating long objects are also to be avoided, as the LinearCast motion qual
 
 ![Even with the LinearCast motion quality the blue object rotates through the green object in a single time step.](Images/LongAndThin.jpg)
 
+## Ghost Collisions {#ghost-collisions}
+
+A ghost collision can occur when a body slides over another body and hits an internal edge of that body. The most common case is where a body hits an edge of a triangle in a mesh shape but it can also happen on 2 box shapes as shown below.
+
+![A blue box sliding over 2 green boxes. Because the blue box can sink into the green box a little bit, it can hit the edge between the two boxes. This will cause the box to stop or jump up.](Images/GhostCollision.jpg)
+
+There are a couple of ways to avoid ghost collisions in Jolt. MeshShape and HeightFieldShape keep track of active edges during construction.
+
+![An inactive edge (concave) and an active edge (convex, angle > threshold angle).](Images/ActiveEdge.jpg)
+
+Whenever a body hits an inactive edge, the contact normal is the face normal. When it hits an active edge, it can be somewhere in between the connecting face normals so the movement of the body is impeded in the scenario below.
+
+![Contact normal (red) of hitting an active vs an inactive edge.](Images/ActiveVsInactiveContactNormal.jpg)
+
+By tweaking MeshShapeSettings::mActiveEdgeCosThresholdAngle or HeightFieldShapeSettings::mActiveEdgeCosThresholdAngle you can determine the angle at which an edge is considered an active edge. By default this is 5 degrees, making this bigger reduces the amount of ghost collisions but can create simulation artifacts if you hit the edge straight on.
+
+To further reduce ghost collisions, you can turn on BodyCreationSettings::mEnhancedInternalEdgeRemoval. When enabling this setting, additional checks will be made at run-time to detect if an edge is active or inactive based on all of the contact points between the two bodies. Beware that this algorithm only considers 2 bodies at a time, so if the two green boxes above belong to two different bodies, the ghost collision can still occur. Use a StaticCompoundShape to combine the boxes in a single body to allow the system to eliminate ghost collisions between the blue and the two green boxes. You can also use this functionality for your custom collision tests by making use of InternalEdgeRemovingCollector. 
+
 # Character Controllers {#character-controllers}
 
 The [Character](@ref Character) and [CharacterVirtual](@ref CharacterVirtual) classes can be used to create a character controller. These are usually used to represent the player as a simple capsule or tall box and perform collision detection while the character navigates through the world.

BIN
Docs/Images/ActiveEdge.jpg


BIN
Docs/Images/ActiveVsInactiveContactNormal.jpg


BIN
Docs/Images/GhostCollision.jpg


+ 1 - 0
Docs/ReleaseNotes.md

@@ -20,6 +20,7 @@ For breaking API changes see [this document](https://github.com/jrouwe/JoltPhysi
 * Renamed SensorDetectsStatic to CollideKinematicVsNonDynamic and made it work for non-sensors. This means that kinematic bodies can now get collision callbacks when they collide with other static / kinematic objects.
 * CharacterVirtual will now receive an OnContactAdded callback when it collides with a sensor (but will have no further interaction).
 * Added support for a vertex radius for soft bodies. This keeps the vertices a fixed distance away from the surface which can be used to avoid z-fighting while rendering the soft body.
+* Implemented enhanced internal edge removal algorithm. This should help reduce ghost collisions. See BodyCreationSettings::mEnhancedInternalEdgeRemoval.
 
 ### Improvements
 * Multithreading the SetupVelocityConstraints job. This was causing a bottleneck in the case that there are a lot of constraints but very few possible collisions.

+ 2 - 2
Jolt/Physics/Collision/InternalEdgeRemovingCollector.h

@@ -15,8 +15,8 @@
 
 JPH_NAMESPACE_BEGIN
 
-// Removes internal edges from collision results. Can be used to filter out 'ghost collisions'.
-// Based on: Contact generation for meshes - Pierre Terdiman (https://www.codercorner.com/MeshContacts.pdf)
+/// Removes internal edges from collision results. Can be used to filter out 'ghost collisions'.
+/// Based on: Contact generation for meshes - Pierre Terdiman (https://www.codercorner.com/MeshContacts.pdf)
 class InternalEdgeRemovingCollector : public CollideShapeCollector
 {
 	static constexpr uint cMaxDelayedResults = 16;