Browse Source

Decreased tolerance in GetBaryCentricCoordinates to avoid detecting ghost collisions (#511)

Added the problem case in a unit test. A sphere that was cast to a very small triangle would detect that it collided with one of the edges of the triangle because GetBaryCentricCoordinates thought the triangle was too small and returned the closest point on an edge.
Jorrit Rouwe 2 years ago
parent
commit
fa2f450a8a

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

@@ -2,7 +2,7 @@ name: Determinism Check
 
 
 env:
 env:
     CONVEX_VS_MESH_HASH: '0x3c55fb5709fda28c'
     CONVEX_VS_MESH_HASH: '0x3c55fb5709fda28c'
-    RAGDOLL_HASH: '0x22cf464f3c2d6b14'
+    RAGDOLL_HASH: '0x5f3b8e4a9e166453'
 
 
 on:
 on:
   push:
   push:

+ 2 - 2
Jolt/Geometry/ClosestPoint.h

@@ -64,7 +64,7 @@ namespace ClosestPoint
 			float d01 = v0.Dot(v1); 
 			float d01 = v0.Dot(v1); 
 		
 		
 			float denominator = d00 * d11 - d01 * d01; 
 			float denominator = d00 * d11 - d01 * d01; 
-			if (abs(denominator) < FLT_EPSILON)
+			if (abs(denominator) < 1.0e-12f)
 			{
 			{
 				// Degenerate triangle, return coordinates along longest edge
 				// Degenerate triangle, return coordinates along longest edge
 				if (d00 > d11)
 				if (d00 > d11)
@@ -93,7 +93,7 @@ namespace ClosestPoint
 			float d12 = v1.Dot(v2); 
 			float d12 = v1.Dot(v2); 
 		
 		
 			float denominator = d11 * d22 - d12 * d12; 
 			float denominator = d11 * d22 - d12 * d12; 
-			if (abs(denominator) < FLT_EPSILON)
+			if (abs(denominator) < 1.0e-12f)
 			{
 			{
 				// Degenerate triangle, return coordinates along longest edge
 				// Degenerate triangle, return coordinates along longest edge
 				if (d11 > d22)
 				if (d11 > d22)

+ 18 - 0
UnitTests/Geometry/ClosestPointTests.cpp

@@ -91,4 +91,22 @@ TEST_SUITE("ClosestPointTests")
 
 
 		TestClosestPointToTriangle(a, b, c, Vec3::sZero(), expected_closest, 0b0101);
 		TestClosestPointToTriangle(a, b, c, Vec3::sZero(), expected_closest, 0b0101);
 	}
 	}
+
+	TEST_CASE("TestSmallTriangleWithPlaneGoingThroughOrigin")
+	{
+		// A small but non-degenerate triangle whose plane almost goes through the origin
+		Vec3 a(-0.132395342f, -0.294095188f, -0.164812326f);
+		Vec3 b(-0.126054004f, -0.283950001f, -0.159065604f);
+		Vec3 c(-0.154956535f, -0.284792334f, -0.160523415f);
+
+		float u, v, w;
+		ClosestPoint::GetBaryCentricCoordinates(a, b, c, u, v, w);
+
+		// Closest point should be close to origin
+		Vec3 p = a * u + b * v + c * w;
+		CHECK_APPROX_EQUAL(p, Vec3::sZero());
+
+		// Closest point should be outside triangle
+		CHECK((u < 0.0f || v > 0.0f || w < 0.0f));
+	}
 }
 }