[SOLVED] No contact points for collision between Kinematic Actor and Static Triangle Mesh

Hi everybody!

I’m having some difficulty detecting collisions between a Kinematic Box and a Static Triangle Mesh using PhysX 3.3.1. I have enabled the eENABLE_KINEMATIC_STATIC_PAIRS flag (before creating the scene), and implemented a simple filter shader which results in PxSimulationEventCallback::onContact() getting called. Once inside the callback I can see the actors involved, and the eNOTIFY_TOUCH_FOUND flag is raised, but my problem is that I get an empty contact stream :(

To further investigate, I added a contact modification callback; at this point multiple contact points are present, so I’m guessing something is happening when the contact is “solved”, resulting in the empty stream I see later in the pipeline?

I further simplified the problem by using a simple triangle mesh consisting of two co-planar triangles, as the mesh I was previously using contained a few thousand triangles. In this case, I do get contact points when the kinematic object is moved through the mesh.

Does anybody have any idea why this might be happening? Are there special considerations that need to be made when dealing with complex triangle meshes? Any suggestions would be awesome, as I’m running out of avenues of investigation… :(

For reference, here’s the filter shader:

// Only care about collisions involving kinematic actors.
if(!(physx::PxFilterObjectIsKinematic(attributes0) || physx::PxFilterObjectIsKinematic(attributes1)))
            return physx::PxFilterFlag::eKILL;

pairFlags|=physx::PxPairFlag::eSOLVE_CONTACT;
pairFlags|=physx::PxPairFlag::eDETECT_DISCRETE_CONTACT;
pairFlags|=physx::PxPairFlag::eNOTIFY_CONTACT_POINTS;
pairFlags|=physx::PxPairFlag::eNOTIFY_TOUCH_FOUND;

return physx::PxFilterFlag::eDEFAULT;

Eventually, I figured this out. It wasn’t related to the complexity of the triangle mesh, or even that the type of the static object was a mesh.

In fact, the culprit was the filter shader code I posted above.

The empty contact stream was only generated when the bounding volumes of the objects initially overlapped. If I started my kinematic object within the bounding volume of the triangle mesh, then moved it outside of the volume, then attempted a collision, it worked okay.

I noticed that the documentation for the return value of the filter shader discusses collision behaviour when the bounding volumes intersect, which seemed related to the problem I was observing. That’s when I realised that the filter shader above is really bad, as it actually kills all collision behaviour in PhysX for anything other than kinematic objects.

So I modified it to the following:

if(physx::PxFilterObjectIsKinematic(attributes0) || physx::PxFilterObjectIsKinematic(attributes1)) {
  pair_flags|=physx::PxPairFlag::eNOTIFY_CONTACT_POINTS;
  pair_flags|=physx::PxPairFlag::eNOTIFY_TOUCH_FOUND;
}

pair_flags|=physx::PxPairFlag::eSOLVE_CONTACT;
pair_flags|=physx::PxPairFlag::eDETECT_DISCRETE_CONTACT;

return physx::PxFilterFlag::eDEFAULT;

And my problem was solved! (Note that this shader effectively provides default collision behaviour for all objects, but only notifies when one of the objects is kinematic.)

As for precisely why this fixes the problem, I’m not 100% certain; as my scene consists of only two actors, and one is kinematic, I wouldn’t have expected the filter shader to ever return eKILL… if anybody has a good explanation, I’d be interested in hearing it!