NVIDIAGameWorks / PhysX

NVIDIA PhysX SDK
Other
3.11k stars 793 forks source link

Found bug in Gu::sweepCapsuleTriangles_Precise #600

Open bleston opened 1 year ago

bleston commented 1 year ago

Gu::sweepCapsuleTriangles_Precise may miss initial overlap when sweep dir is parallel with triangle.

Below code show this:

void testSweepCapsuleTriangle()
{
    const PxVec3 vertices[3] = { {0.f, 0.f, 0.f}, {1.f, 0.f, 0.f }, {0.f, 0.f, -1.0f} };
    const PxU32 indices[3] = { 0, 1, 2 };

    static float radius = 0.3;
    static float halfHeight = 1.f;

    const PxVec3 startPoint{ 0.f, 0.f, 0.f };
    const PxQuat rot{ 0.f, 0.f, 0.f, 1.f };
    const PxVec3 unitDir{ -1.f, 0.f, 0.f };
    const PxReal distance{ 1.0f };

    const physx::PxTransform pose0{ startPoint, rot };
    const physx::PxTransform poseTri{ PxIdentity };

    PxHitFlags hitFlags{ physx::PxHitFlag::eDEFAULT | physx::PxHitFlag::eMESH_BOTH_SIDES };

    PxTriangleMeshDesc meshDesc;
    meshDesc.points.count = 3;
    meshDesc.points.data = vertices;
    meshDesc.points.stride = sizeof(PxVec3);
    meshDesc.triangles.count = 1;
    meshDesc.triangles.data = indices;
    meshDesc.triangles.stride = 3 * sizeof(PxU32);
    PxCookingParams params = gCooking->getParams();

    PxTriangleMesh* triMesh = NULL;
    triMesh = gCooking->createTriangleMesh(meshDesc, gPhysics->getPhysicsInsertionCallback());

    PxTriangleMeshGeometry triGeom{ triMesh };
    PxCapsuleGeometry capsuleGeom{ radius, halfHeight };

    bool isInitOverlap = PxGeometryQuery::overlap(capsuleGeom, pose0, triGeom, poseTri);
    printf("isInitOverlap = %d.\n", isInitOverlap);

    physx::PxSweepHit hit;
    PxU32 hitCount = PxGeometryQuery::sweep(unitDir, distance, capsuleGeom, pose0, triGeom, poseTri, hit, hitFlags);
    printf("\nSweep capsule hitCount = %d.\n", hitCount);
    if (hitCount > 0)
    {
        printf("hit position is (%f, %f, %f).\n", hit.position.x, hit.position.y, hit.position.z);
        printf("hit normal is (%f, %f, %f).\n", hit.normal.x, hit.normal.y, hit.normal.z);
        printf("hit distance is %f.\n", hit.distance);
    }

    triMesh->release();
}

This bug is because rejectTriangle before intersectCapsuleTriangle in Gu::sweepCapsuleTriangles_Precise.