Browse Source

Bugfix: The friction applied during continuous collision detection could be sqrt(2) times too large. (#583)

The problem was that the friction was applied in two perpendicular axis instead of just the perpendicular axis in the direction of the relative velocity.
Jorrit Rouwe 2 years ago
parent
commit
f215a88ea8
2 changed files with 15 additions and 12 deletions
  1. 2 2
      .github/workflows/determinism_check.yml
  2. 13 10
      Jolt/Physics/PhysicsSystem.cpp

+ 2 - 2
.github/workflows/determinism_check.yml

@@ -1,8 +1,8 @@
 name: Determinism Check
 
 env:
-    CONVEX_VS_MESH_HASH: '0x694f34b44c755f7'
-    RAGDOLL_HASH: '0xea156c841e796fc9'
+    CONVEX_VS_MESH_HASH: '0x412693f5fd7ee9f6'
+    RAGDOLL_HASH: '0x62f3cf349a172dd4'
 
 on:
   push:

+ 13 - 10
Jolt/Physics/PhysicsSystem.cpp

@@ -2043,18 +2043,21 @@ void PhysicsSystem::JobResolveCCDContacts(PhysicsUpdateContext *ioContext, Physi
 					// Apply friction
 					if (ccd_body->mContactSettings.mCombinedFriction > 0.0f)
 					{
-						Vec3 tangent1 = ccd_body->mContactNormal.GetNormalizedPerpendicular();
-						Vec3 tangent2 = ccd_body->mContactNormal.Cross(tangent1);
-
-						float max_lambda_f = ccd_body->mContactSettings.mCombinedFriction * contact_constraint.GetTotalLambda();
+						// Calculate friction direction by removing normal velocity from the relative velocity
+						Vec3 friction_direction = relative_velocity - normal_velocity * ccd_body->mContactNormal;
+						float friction_direction_len_sq = friction_direction.LengthSq();
+						if (friction_direction_len_sq > 1.0e-12f)
+						{
+							// Normalize friction direction
+							friction_direction /= sqrt(friction_direction_len_sq);
 
-						AxisConstraintPart friction1;
-						friction1.CalculateConstraintProperties(body1, r1_plus_u, body2, r2, tangent1);
-						friction1.SolveVelocityConstraint(body1, body2, tangent1, -max_lambda_f, max_lambda_f);
+							// Calculate max friction impulse
+							float max_lambda_f = ccd_body->mContactSettings.mCombinedFriction * contact_constraint.GetTotalLambda();
 
-						AxisConstraintPart friction2;
-						friction2.CalculateConstraintProperties(body1, r1_plus_u, body2, r2, tangent2);
-						friction2.SolveVelocityConstraint(body1, body2, tangent2, -max_lambda_f, max_lambda_f);
+							AxisConstraintPart friction;
+							friction.CalculateConstraintProperties(body1, r1_plus_u, body2, r2, friction_direction);
+							friction.SolveVelocityConstraint(body1, body2, friction_direction, -max_lambda_f, max_lambda_f);
+						}
 					}
 
 					// Clamp velocities