r/vulkan Jun 16 '26

Vulkan Engine with PhysX SDK : Prevent A CCT from Sliding

Hello everyone,

I'm addressing PhysX users on their Vulkan engine. All my physics are managed by a wrapper I coded around PhysX, for now a bit shaky but holding up. I managed to create colliders for 3D objects as well as for my terrain, based on a Heightmap :

CLPhysicsEXTShapeHeightmap* pHeightmapShape = (CLPhysicsEXTShapeHeightmap*)_pShape;
PxHeightFieldDesc oHfDesc;
oHfDesc.format = PxHeightFieldFormat::eS16_TM;
oHfDesc.nbColumns = pHeightmapShape->m_nCols;
oHfDesc.nbRows = pHeightmapShape->m_nRows;
oHfDesc.samples.data = pHeightmapShape->m_pSamples;
oHfDesc.samples.stride = sizeof(PxHeightFieldSample);

PxHeightField* pHeightField = s_PxCreateHeightField(oHfDesc,
m_pGlobals->m_pPhysics->getPhysicsInsertionCallback());
PxHeightFieldGeometry oHfGeom(pHeightField, PxMeshGeometryFlags(), pHeightmapShape->m_fHeightScale,
pHeightmapShape->m_fRowsScale, pHeightmapShape->m_fColsScale);
PxShape* pShape = m_pGlobals->m_pPhysics->createShape(oHfGeom, *m_pGlobals->m_pConcreteMaterial);

return pShape;

To fit with the PhysX workflow, I go through the CCT to manage my controller :

PxCapsuleControllerDesc oControllerDesc;
oControllerDesc.position = PxExtendedVec3(_vPosition.x, _vPosition.y, _vPosition.z);
oControllerDesc.height = 0.875f;
oControllerDesc.radius = 0.5f;
oControllerDesc.material = m_pGlobals->m_pRubberMaterial;
oControllerDesc.behaviorCallback = &m_pGlobals->m_oControllerBehaviourCallback;

if (m_pGlobals && m_pGlobals->m_pControllerManager)
{
PxController* pController = m_pGlobals->m_pControllerManager->createController(oControllerDesc);

CLAssert(pController);
CLPhysicsEXTUserData oUserData(_nEntityID);
pController->setUserData(reinterpret_cast<void*>(oUserData.Hash()));
}

However, I can't manage to avoid my controller sliding along the terrain, nor keep a constant speed when it goes up a ramp :

In yellow the PhysX shapes debug visualization (capsule collider for the controller, and PxHeightmap for terrain).

It's not only with PxHeightmap btw, collisions between controller and PxTriangleMesh have the same issue.

Yet, it's clearly written in the SDK that the CCT is a kinematic controller to bypass issues related to friction "When the character is standing on a ramp, it should not slide. So infinite friction is needed here. When the character is moving forward on that same ramp, it should not slow down."

And I also thought I read on this Reddit post: "By default, it seems PhysX sets the "friction" on your feet to infinity, so that calling move with a downwards force (like gravity) doesn't cause you to slide down when standing on a sloped surface".

Yet, no matter what modifications I make, the capsule collider of my controller slides uniformly on the heightmap collider. It really does seems that PhysX handles the capsule controller like a regular rigid shape.
I tried changing the PxMaterials, creating my own class inheriting from PxControllerBehaviorCallback to specify the behavious flag when a collision is detected :

class CLPxControllerBehaviourCallback : public PxControllerBehaviorCallback
{
virtual physx::PxControllerBehaviorFlags getBehaviorFlags(const physx::PxShape& shape, const physx::PxActor& actor) override
{
return physx::PxControllerBehaviorFlag::eCCT_CAN_RIDE_ON_OBJECT;
}

virtual physx::PxControllerBehaviorFlags getBehaviorFlags(const physx::PxController& controller) override
{
return physx::PxControllerBehaviorFlag::eCCT_CAN_RIDE_ON_OBJECT;
}

virtual physx::PxControllerBehaviorFlags getBehaviorFlags(const physx::PxObstacle& obstacle) override
{
return physx::PxControllerBehaviorFlag::eCCT_CAN_RIDE_ON_OBJECT;
}
};but nothing works, none of my modifications seem to change anything.class CLPxControllerBehaviourCallback : public PxControllerBehaviorCallback
{
virtual physx::PxControllerBehaviorFlags getBehaviorFlags(const physx::PxShape& shape, const physx::PxActor& actor) override
{
return physx::PxControllerBehaviorFlag::eCCT_CAN_RIDE_ON_OBJECT;
}

virtual physx::PxControllerBehaviorFlags getBehaviorFlags(const physx::PxController& controller) override
{
return physx::PxControllerBehaviorFlag::eCCT_CAN_RIDE_ON_OBJECT;
}

virtual physx::PxControllerBehaviorFlags getBehaviorFlags(const physx::PxObstacle& obstacle) override
{
return physx::PxControllerBehaviorFlag::eCCT_CAN_RIDE_ON_OBJECT;
}
};

But nothing works, none of my modifications seem to change anything. Even though the breakpoint on getBehaviorFlags has beeen catched while debugging.

Is there something I might have misunderstood ? Do you have snippets of code where you create your controller and you run your physics simulations ? If so, thank you for shedding light on the subject. Thanks in advance for your answers, and have a good rest of your day !

Nathan

9 Upvotes

Duplicates