From 12e56eb496b48dce7369464cc6ea31eae8951114 Mon Sep 17 00:00:00 2001 From: Pro-Ly <849297348@qq.com> Date: Sun, 26 May 2024 21:02:24 +0800 Subject: [PATCH] Fix ConvexHullPairTester get wrong contacts with parallel edges cases --- .../CollisionTasks/ConvexHullPairTester.cs | 66 ++++++++----------- 1 file changed, 29 insertions(+), 37 deletions(-) diff --git a/BepuPhysics/CollisionDetection/CollisionTasks/ConvexHullPairTester.cs b/BepuPhysics/CollisionDetection/CollisionTasks/ConvexHullPairTester.cs index d07a8a1a..53b86946 100644 --- a/BepuPhysics/CollisionDetection/CollisionTasks/ConvexHullPairTester.cs +++ b/BepuPhysics/CollisionDetection/CollisionTasks/ConvexHullPairTester.cs @@ -153,46 +153,38 @@ public static unsafe void Test(ref ConvexHullWide a, ref ConvexHullWide b, ref V if (numerator < earliestExit * denominator) earliestExit = numerator / denominator; } - else if (numerator < 0) - { - //The B edge is parallel and outside the edge A, so there can be no intersection. - earliestExit = float.MinValue; - latestEntry = float.MaxValue; - } + //Parallel edges are ignored. If the edge is parallel, it will not contribute to the contact manifold. } - //We now have bounds on B's edge. - //Denominator signs are opposed; comparison flipped. - if (latestEntry <= earliestExit) + + //This edge of B was actually contained in A's face. Add contacts for it. + latestEntry = latestEntry < 0 ? 0 : latestEntry; + earliestExit = earliestExit > 1 ? 1 : earliestExit; + //Create max contact if max >= min. + //Create min if min < max and min > 0. + var startId = (previousIndexB.BundleIndex << BundleIndexing.VectorShift) + previousIndexB.InnerIndex; + var endId = (indexB.BundleIndex << BundleIndexing.VectorShift) + indexB.InnerIndex; + var baseFeatureId = (startId ^ endId) << 8; + if (earliestExit >= latestEntry && candidateCount < maximumCandidateCount) { - //This edge of B was actually contained in A's face. Add contacts for it. - latestEntry = latestEntry < 0 ? 0 : latestEntry; - earliestExit = earliestExit > 1 ? 1 : earliestExit; - //Create max contact if max >= min. - //Create min if min < max and min > 0. - var startId = (previousIndexB.BundleIndex << BundleIndexing.VectorShift) + previousIndexB.InnerIndex; - var endId = (indexB.BundleIndex << BundleIndexing.VectorShift) + indexB.InnerIndex; - var baseFeatureId = (startId ^ endId) << 8; - if (earliestExit >= latestEntry && candidateCount < maximumCandidateCount) - { - //Create max contact. - var point = edgeOffsetB * earliestExit + previousVertexB - bFaceOrigin; - var newContactIndex = candidateCount++; - ref var candidate = ref candidates[newContactIndex]; - candidate.X = Vector3.Dot(point, bFaceX); - candidate.Y = Vector3.Dot(point, bFaceY); - candidate.FeatureId = baseFeatureId + endId; - } - if (latestEntry < earliestExit && latestEntry > 0 && candidateCount < maximumCandidateCount) - { - //Create min contact. - var point = edgeOffsetB * latestEntry + previousVertexB - bFaceOrigin; - var newContactIndex = candidateCount++; - ref var candidate = ref candidates[newContactIndex]; - candidate.X = Vector3.Dot(point, bFaceX); - candidate.Y = Vector3.Dot(point, bFaceY); - candidate.FeatureId = baseFeatureId + startId; - } + //Create max contact. + var point = edgeOffsetB * earliestExit + previousVertexB - bFaceOrigin; + var newContactIndex = candidateCount++; + ref var candidate = ref candidates[newContactIndex]; + candidate.X = Vector3.Dot(point, bFaceX); + candidate.Y = Vector3.Dot(point, bFaceY); + candidate.FeatureId = baseFeatureId + endId; } + if (latestEntry < earliestExit && latestEntry > 0 && candidateCount < maximumCandidateCount) + { + //Create min contact. + var point = edgeOffsetB * latestEntry + previousVertexB - bFaceOrigin; + var newContactIndex = candidateCount++; + ref var candidate = ref candidates[newContactIndex]; + candidate.X = Vector3.Dot(point, bFaceX); + candidate.Y = Vector3.Dot(point, bFaceY); + candidate.FeatureId = baseFeatureId + startId; + } + previousIndexB = indexB; previousVertexB = vertexB; }