@@ -650,7 +650,6 @@ inline __device__ bool projectTriangleOntoTriangle(const T1* incTri,
650650 centroid.z = T2 (0.0 );
651651
652652 area = T2 (0.0 );
653- depth = maxPenetration;
654653 if (numInputVerts >= 3 ) {
655654 for (int i = 0 ; i < numInputVerts; ++i) {
656655 centroid = centroid + inputPoly[i];
@@ -665,6 +664,38 @@ inline __device__ bool projectTriangleOntoTriangle(const T1* incTri,
665664 area += sqrt (dot (crossProd, crossProd));
666665 }
667666 area *= T2 (0.5 );
667+
668+ // Calculate 2D MTV: minimum distance to move the clipped polygon away from reference triangle
669+ // This prevents artifacts from "side strips" where tiny edge penetrations create large forces
670+ T2 minMTV = maxPenetration; // Start with 3D penetration as upper bound
671+
672+ // Test each edge of the reference triangle
673+ for (int edge = 0 ; edge < 3 ; ++edge) {
674+ T1 edgeStart = refTri[edge];
675+ T1 edgeEnd = refTri[(edge + 1 ) % 3 ];
676+ T1 edgeDir = edgeEnd - edgeStart;
677+ T1 edgeNormal = cross (refNormal, edgeDir);
678+ T2 edgeNormalLen2 = dot (edgeNormal, edgeNormal);
679+ if (edgeNormalLen2 > DEME_TINY_FLOAT) {
680+ T1 edgeNormalNormalized = edgeNormal * rsqrt (edgeNormalLen2);
681+
682+ // Find maximum penetration of clipped polygon vertices beyond this edge
683+ T2 maxDist = T2 (0.0 );
684+ for (int i = 0 ; i < numInputVerts; ++i) {
685+ T2 dist = dot (inputPoly[i] - edgeStart, edgeNormalNormalized);
686+ if (dist > maxDist) {
687+ maxDist = dist;
688+ }
689+ }
690+
691+ // Update minimum MTV
692+ if (maxDist > DEME_TINY_FLOAT && maxDist < minMTV) {
693+ minMTV = maxDist;
694+ }
695+ }
696+ }
697+
698+ depth = minMTV;
668699 return true ;
669700 } else {
670701 // Degenerate clipping polygon
0 commit comments