Speculative CCD & contact reports from passing objects

Hi,

this might be a feature and not a bug, but I’ll ask anyway. I have a test setup with a ground plane and a fast-moving dynamic box moving above the plane but not touching it. The code looks like this:

physx::PxShape* pPlaneShape = m_pPhysicsAPI->getPhysics()->createShape( physx::PxPlaneGeometry(), *m_pPhysicsAPI->getDefaultMaterial(), true );
physx::PxRigidStatic* pRigidStatic = m_pPhysicsAPI->getPhysics()->createRigidStatic( physx::PxTransform( physx::PxVec3( 0.0f, 2.0f, 0.0f ), physx::PxQuat( 0.5f * M_PI, physx::PxVec3( 0.0f, 0.0f, 1.0f ) ) ) );
pRigidStatic->attachShape( *pPlaneShape );
pPlaneShape->release();

m_pScene->lockWrite();
m_pScene->addActor( *pRigidStatic );
m_pScene->unlockWrite();

physx::PxShape* pBoxShape = m_pPhysicsAPI->getPhysics()->createShape( physx::PxBoxGeometry( 0.1f, 0.1f, 0.1f ), *m_pPhysicsAPI->getDefaultMaterial(), true );
physx::PxRigidDynamic* pRigidDynamic = m_pPhysicsAPI->getPhysics()->createRigidDynamic( physx::PxTransform( physx::PxVec3( 0.0f, 2.2f, 0.0f ) ) );
pRigidDynamic->setLinearVelocity( physx::PxVec3( 0.0f, 0.0f, 20.0f ) );
pRigidDynamic->attachShape( *pBoxShape );

pRigidDynamic->setRigidBodyFlag( physx::PxRigidBodyFlag::eENABLE_SPECULATIVE_CCD, true );
pBoxShape->release();

m_pScene->lockWrite();
m_pScene->addActor( *pRigidDynamic );
m_pScene->unlockWrite();

If I set eNOTIFY_TOUCH_FOUND for the collision pair, I’ll get contact reports between the plane and the box with a high separation and an impulse of exactly 0. If I set eNOTIFY_THRESHOLD_FORCE_FOUND with threshold 0, nothing gets reported. I guess the way speculative CCD works makes it generate contacts where the regular CCD doesn’t, but should it still report the contacts even if the they don’t cause an impulse to be applied on the body? I can of course filter out the reported contacts if the impulse is 0, but I’d rather do the filtering inside PhysX for performance (and it’d be a little less confusing too).

I also sometimes get actual contacts with impulses applied for similar passing objects with speculative CCD. So far I’ve only seen it near some triangle meshes with large triangles, so I’m guessing it’s just a narrow phase problem and unrelated to the other problem. Unfortunately I don’t have a simple test case for this.

I lied, here’s a test case for the second problem. Note that gravity is 0 for both test cases. Here I’m not even using triangle meshes, just dynamic & static boxes. The problem only repros with speculative CCD enabled.

for ( int x = -1; x <= 1; ++x )
{
	for( int z = -1; z <= 1; ++z )
	{
		physx::PxShape* pPlaneShape = m_pPhysicsAPI->getPhysics()->createShape( physx::PxBoxGeometry( 4.0f, 0.01f, 4.0f ), *m_pPhysicsAPI->getDefaultMaterial(), true );
		physx::PxRigidStatic* pRigidStatic = m_pPhysicsAPI->getPhysics()->createRigidStatic( physx::PxTransform( physx::PxVec3( 8.0f * x, 2.0f, 8.0f * z ) ) );
		pRigidStatic->attachShape( *pPlaneShape );
		pPlaneShape->release();

		m_pScene->lockWrite();
		m_pScene->addActor( *pRigidStatic );
		m_pScene->unlockWrite();
	}
}

for ( int i = 0; i != 30; ++i )
{
	float fAngle = 2 * M_PI * float( i ) / 30.0f;

	physx::PxVec3 dir( 20.0f * sin( fAngle ), -0.01f, 20.0f * cos( fAngle ) );

	physx::PxShape* pBoxShape = m_pPhysicsAPI->getPhysics()->createShape( physx::PxBoxGeometry( 0.1f, 0.1f, 0.1f ), *m_pPhysicsAPI->getDefaultMaterial(), true );
	physx::PxRigidDynamic* pRigidDynamic = m_pPhysicsAPI->getPhysics()->createRigidDynamic( physx::PxTransform( physx::PxVec3( dir.x * 0.1f, 2.5f, dir.z * 0.1f ) ) );
	pRigidDynamic->setLinearVelocity( 2 * dir );
	pRigidDynamic->attachShape( *pBoxShape );

	pRigidDynamic->setRigidBodyFlag( physx::PxRigidBodyFlag::eENABLE_SPECULATIVE_CCD, true );
	pBoxShape->release();

	m_pScene->lockWrite();
	m_pScene->addActor( *pRigidDynamic );
	m_pScene->unlockWrite();
}

Speculative CCD works by introducing a large contact distance around the shapes to generate potential contacts and then solving this increased contact set inside the solver. It treats these distant contacts a little differently than the contacts that are generated if speculative CCD is disabled and contact distance was set to a large value but the set of contacts that are produced by contact generation are the same.

The benefits of this approach are that you get a relatively inexpensive CCD solution that handles both fast-moving linear and angular motion and that supports CCD on kinematic bodies.

The drawbacks of this approach are that its not as robust as the sweep-based CCD and that it can report phantom contacts. Phantom contacts are contacts that were generated that actually should not have contributed to the simulation. They are caused by PhysX inflating contact distance based on the speed that the bodies are moving at. Usually, these redundant distant contacts have no impulse applied by the solver so they have no influence on the resulting motion of the bodies. Sometimes, these contacts may have had some impulse applied and this means that the solver determined that the constraint imposed by these distant contacts would have bene violated.

Unfortunately, this is how this CCD approach works. It’s a new feature in PhysX 3.4 and we will be making some improvements but there is an inherent risk of false collisions reporting with this approach. As you noticed, if you filter contacts by applied impulse by some small tolerance, this should remove most of the false contacts. The overall motion of the bodies is usually not influenced by these false contacts.

Please note that speculative CCD and sweep-based CCD are not an either/or thing. You can mix both modes of CCD in a scene, but you cannot enable both modes on the same body. Therefore, you could (as an example) have sweep-based CCD on a ping pong ball while you have speculative CCD enabled on the (kinematic?) paddle that your character holds to hit it.

Thanks for the reply.

OK, I wasn’t aware that the false contacts are a feature of speculative CCD. Since the documentation (Advanced Collision Detection — NVIDIA PhysX SDK 3.4.0 Documentation) doesn’t mention false contacts explicitly, I had just assumed that the “less robust” bit in there referred only to the tunneling problems (which haven’t been much of a problem for my use-case).

Are there any upcoming fixes to the specific problem of false contacts from passing objects generating impulses, or is this as good as it’ll get?

I’m actually already using both speculative CCD and sweep-based CCD in the same scene to work around this issue. Unfortunately for some of the objects in my scene neither option works well: for speculative CCD I have the problem of false contacts, and for sweep-based CCD I have the problem of “bouncy” contacts for collision shapes that are small and offset relatively far from the rigid body (not the CoM) center.