We are using PhysX 4.1.2. Our QA reports a bug, that a sphere character get stuck in a geometry and I found that is caused by initial overlap with distance = 0 (exactly), and the normal is always (-1)*(sweepDir). The sphere looks just touching the flower bed (red line in image below), which is a triangle mesh, and the contact feature should be the edge.
I walked through the calculations inside physx::Gu::computeCapsule_TriangleMeshMTD, and at line 278:
hadContacts = calculateMTD(....)
it returns no contacts. So setupSweepHitForMTD report that sweepHit.normal = -unitDir;
Then I checked PCMCapsuleVsMeshContactGeneration::processTriangle, found that
- generateContacts returns no contact, because the sphere center's project point on the triangle is not inside (con0/con1 is false)
- generateEEContactsMTD also returns no contact, because for a sphere, PCMCapsuleVsMeshContactGeneration::generateEEMTD always return false at line 818, the comment says "If both points in the same side as the plane, no intersect points".
Now I just work around to check at first, if it is a sphere, just calculate contact using pcmDistancePointTriangleSquared.
const FloatV sqInflatedRadius = FMul(inflatedRadius, inflatedRadius);
// Sphere fast path: degenerate capsule (p0==p1). generateEEMTD always exits early for
// this case because pq=(0,0,0) => npq=0, and generateContacts fails when the diagonal
// projection lands outside the triangle face. Use direct point-triangle query instead.
// W stores raw distance (consistent with generateContacts / generateEEMTD convention),
// so the outer loop's distV = mtd - capsuleV.radius gives the correct signed penetration.
const Vec3V capsulePQ = V3Sub(capsule.p1, capsule.p0);
if(FAllEq(V3Dot(capsulePQ, capsulePQ), zero))
{
Vec3V closestP;
bool generateContact = false, faceContact = false;
const FloatV sqD = pcmDistancePointTriangleSquared(
capsule.p0, p0, p1, p2, trigFlag, closestP, generateContact, faceContact);
if(FAllGrtr(sqInflatedRadius, sqD) && generateContact)
{
const Vec3V contactNormal = faceContact
? n
: V3Normalize(V3Sub(capsule.p0, closestP));
manifoldContacts[numContacts].mLocalPointA = capsule.p0;
manifoldContacts[numContacts].mLocalPointB = closestP;
manifoldContacts[numContacts].mLocalNormalPen =
V4SetW(Vec4V_From_Vec3V(contactNormal), FSqrt(sqD));
manifoldContacts[numContacts++].mFaceIndex = triangleIndex;
}
return true;
}
FloatV t, u, v;
const FloatV sqDist = pcmDistanceSegmentTriangleSquared(capsule.p0, capsule.p1, p0, p1, p2, t, u, v);
But I'm not that sure, and wonder what is the best way to fix this.
We are using PhysX 4.1.2. Our QA reports a bug, that a sphere character get stuck in a geometry and I found that is caused by initial overlap with distance = 0 (exactly), and the normal is always (-1)*(sweepDir). The sphere looks just touching the flower bed (red line in image below), which is a triangle mesh, and the contact feature should be the edge.
I walked through the calculations inside physx::Gu::computeCapsule_TriangleMeshMTD, and at line 278:
hadContacts = calculateMTD(....)
it returns no contacts. So setupSweepHitForMTD report that sweepHit.normal = -unitDir;
Then I checked PCMCapsuleVsMeshContactGeneration::processTriangle, found that
Now I just work around to check at first, if it is a sphere, just calculate contact using pcmDistancePointTriangleSquared.
But I'm not that sure, and wonder what is the best way to fix this.