This is the initPhysics function with the modifications :).
void initPhysics()
{
gFoundation = PxCreateFoundation(PX_FOUNDATION_VERSION, gAllocator, gErrorCallback);
gPvd = PxCreatePvd(*gFoundation);
PxPvdTransport* transport = PxDefaultPvdSocketTransportCreate(PVD_HOST, 5425, 10);
gPvd->connect(*transport,PxPvdInstrumentationFlag::eALL);
gPhysics = PxCreatePhysics(PX_PHYSICS_VERSION, *gFoundation, PxTolerancesScale(),true, gPvd);
PxSceneDesc sceneDesc(gPhysics->getTolerancesScale());
sceneDesc.gravity = PxVec3(0.0f, -9.81f, 0.0f);
PxU32 numWorkers = 1;
gDispatcher = PxDefaultCpuDispatcherCreate(numWorkers);
sceneDesc.cpuDispatcher = gDispatcher;
sceneDesc.filterShader = VehicleFilterShader; //Set the filter shader
sceneDesc.contactModifyCallback = &gWheelContactModifyCallback; //Enable contact modification
sceneDesc.ccdContactModifyCallback = &gWheelCCDContactModifyCallback; //Enable ccd contact modification
sceneDesc.flags |= PxSceneFlag::eENABLE_CCD; //Enable ccd
gScene = gPhysics->createScene(sceneDesc);
PxPvdSceneClient* pvdClient = gScene->getScenePvdClient();
if(pvdClient)
{
pvdClient->setScenePvdFlag(PxPvdSceneFlag::eTRANSMIT_CONSTRAINTS, true);
pvdClient->setScenePvdFlag(PxPvdSceneFlag::eTRANSMIT_CONTACTS, true);
pvdClient->setScenePvdFlag(PxPvdSceneFlag::eTRANSMIT_SCENEQUERIES, true);
}
gMaterial = gPhysics->createMaterial(0.1f, 0.1f, 0.01f);
gCooking = PxCreateCooking(PX_PHYSICS_VERSION, *gFoundation, PxCookingParams(PxTolerancesScale()));
/////////////////////////////////////////////
PxInitVehicleSDK(*gPhysics);
PxVehicleSetBasisVectors(PxVec3(0,1,0), PxVec3(0,0,-1));
PxVehicleSetUpdateMode(PxVehicleUpdateMode::eVELOCITY_CHANGE);
PxVehicleSetSweepHitRejectionAngles(POINT_REJECT_ANGLE, NORMAL_REJECT_ANGLE);
PxVehicleSetMaxHitActorAcceleration(MAX_ACCELERATION);
//Create the batched scene queries for the suspension sweeps.
//Use the post-filter shader to reject hit shapes that overlap the swept wheel at the start pose of the sweep.
PxQueryHitType::Enum(*sceneQueryPreFilter)(PxFilterData, PxFilterData, const void*, PxU32, PxHitFlags&);
PxQueryHitType::Enum(*sceneQueryPostFilter)(PxFilterData, PxFilterData, const void*, PxU32, const PxQueryHit&);
#if BLOCKING_SWEEPS
sceneQueryPreFilter = &WheelSceneQueryPreFilterBlocking;
sceneQueryPostFilter = &WheelSceneQueryPostFilterBlocking;
#else
sceneQueryPreFilter = &WheelSceneQueryPreFilterNonBlocking;
sceneQueryPostFilter = &WheelSceneQueryPostFilterNonBlocking;
#endif
gVehicleSceneQueryData = VehicleSceneQueryData::allocate(NUM_VEHICLES, PX_MAX_NB_WHEELS, gNbQueryHitsPerWheel, NUM_VEHICLES, sceneQueryPreFilter, sceneQueryPostFilter, gAllocator);
gBatchQuery = VehicleSceneQueryData::setUpBatchedSceneQuery(0, *gVehicleSceneQueryData, gScene);
//Create the friction table for each combination of tire and surface type.
gFrictionPairs = createFrictionPairs(gMaterial);
//Create a plane to drive on.
PxFilterData groundPlaneSimFilterData(COLLISION_FLAG_GROUND, COLLISION_FLAG_GROUND_AGAINST, 0, 0);
PxShape* shape = NULL;
PxU16 nbColumns = PxU16(1024);
PxU16 nbRows = PxU16(1024);
PxHeightFieldDesc heightfieldDesc;
heightfieldDesc.nbColumns = nbColumns;
heightfieldDesc.nbRows = nbRows;
PxHeightFieldSample* samplesData = (PxHeightFieldSample*)malloc(sizeof(PxHeightFieldSample) * (nbColumns * nbRows));
heightfieldDesc.samples.data = samplesData;
heightfieldDesc.samples.stride = sizeof(PxHeightFieldSample);
heightfieldDesc.convexEdgeThreshold = 0;
PxHeightFieldSample* currentByte = (PxHeightFieldSample*)heightfieldDesc.samples.data;
for (PxU32 column = 0; column < nbRows * nbColumns; column++)
{
//for(PxU32 row = 0; row < nbRows; row++)
{
PxHeightFieldSample* currentSample = (PxHeightFieldSample*)currentByte;
currentSample->height = 0;
currentSample->materialIndex0 = 0;
currentSample->materialIndex1 = 0;
currentSample->clearTessFlag();
currentByte++;
}
}
heightfieldDesc.isValid();
PxHeightField* heightfield = gCooking->createHeightField(heightfieldDesc, gPhysics->getPhysicsInsertionCallback());
delete samplesData;
shape = gPhysics->createShape(PxHeightFieldGeometry(heightfield, PxMeshGeometryFlags(), 1.f, 1, 1), *gMaterial);
PxFilterData simFilterData;
simFilterData.word0 = COLLISION_FLAG_GROUND;
simFilterData.word1 = COLLISION_FLAG_GROUND_AGAINST;
shape->setSimulationFilterData(simFilterData);
physx::PxFilterData qryFilterData;
qryFilterData.word3 = DRIVABLE_SURFACE;
shape->setQueryFilterData(qryFilterData);
shape->setFlag(PxShapeFlag::ePARTICLE_DRAIN, true);
shape->setFlag(PxShapeFlag::eSIMULATION_SHAPE, true);
PxTransform trs = PxTransform(PxIdentity);
trs.p.x -= 100;
trs.p.z -= 100;
PxRigidStatic* groundPlane = gPhysics->createRigidStatic(trs);
groundPlane->attachShape(*shape);
gScene->addActor(*groundPlane);
//Create several static obstacles for the first vehicle to drive on.
// (i) collide only with wheel shapes
// (ii) have continuous collision detection (CCD) enabled
//(iii) have contact modification enabled
// (iv) are configured to be drivable surfaces
const PxF32 capsuleRadii[4] = {0.05f, 0.1f, 0.125f, 0.135f};
const PxF32 capsuleZ[4] = {5.0f, 10.0f, 15.0f, 20.0f};
for(PxU32 i = 0; i < 4; i++)
{
PxTransform t(PxVec3(xCoordVehicleStarts[0], capsuleRadii[i], capsuleZ[i]), PxQuat(PxIdentity));
PxRigidStatic* rd = gPhysics->createRigidStatic(t);
PxCapsuleGeometry capsuleGeom(capsuleRadii[i], 3.0f);
PxShape* shape = PxRigidActorExt::createExclusiveShape(*rd, capsuleGeom, *gMaterial);
PxFilterData simFilterData(COLLISION_FLAG_OBSTACLE, COLLISION_FLAG_WHEEL, PxPairFlag::eMODIFY_CONTACTS | PxPairFlag::eDETECT_CCD_CONTACT, 0);
shape->setSimulationFilterData(simFilterData);
PxFilterData qryFilterData;
setupDrivableSurface(qryFilterData);
shape->setQueryFilterData(qryFilterData);
gScene->addActor(*rd);
}
const PxF32 boxHalfHeights[1] = {1.0f};
const PxF32 boxZ[1] = {30.0f};
for(PxU32 i = 0; i < 1; i++)
{
PxTransform t(PxVec3(xCoordVehicleStarts[0], boxHalfHeights[i], boxZ[i]), PxQuat(PxIdentity));
PxRigidStatic* rd = gPhysics->createRigidStatic(t);
PxBoxGeometry boxGeom(PxVec3(3.0f, boxHalfHeights[i], 3.0f));
PxShape* shape = PxRigidActorExt::createExclusiveShape(*rd, boxGeom, *gMaterial);
PxFilterData simFilterData(COLLISION_FLAG_OBSTACLE, COLLISION_FLAG_WHEEL, PxPairFlag::eMODIFY_CONTACTS | PxPairFlag::eDETECT_CCD_CONTACT, 0);
shape->setSimulationFilterData(simFilterData);
PxFilterData qryFilterData;
setupDrivableSurface(qryFilterData);
shape->setQueryFilterData(qryFilterData);
gScene->addActor(*rd);
}
//Create a pile of dynamic objects for the second vehicle to drive on.
// (i) collide only with wheel shapes
// (ii) have continuous collision detection (CCD) enabled
//(iii) have contact modification enabled
// (iv) are configured to be drivable surfaces
{
for (PxU32 i = 0; i < 64; i++)
{
PxTransform t(PxVec3(xCoordVehicleStarts[1] + i*0.01f, 2.0f + i*0.25f, 20.0f + i*0.025f), PxQuat(PxPi*0.5f, PxVec3(0, 1, 0)));
PxRigidDynamic* rd = gPhysics->createRigidDynamic(t);
PxBoxGeometry boxGeom(PxVec3(0.08f, 0.25f, 1.0f));
PxShape* shape = PxRigidActorExt::createExclusiveShape(*rd, boxGeom, *gMaterial);
PxFilterData simFilterData(COLLISION_FLAG_OBSTACLE, COLLISION_FLAG_OBSTACLE_AGAINST, PxPairFlag::eMODIFY_CONTACTS | PxPairFlag::eDETECT_CCD_CONTACT, 0);
shape->setSimulationFilterData(simFilterData);
PxFilterData qryFilterData;
setupDrivableSurface(qryFilterData);
shape->setQueryFilterData(qryFilterData);
PxRigidBodyExt::updateMassAndInertia(*rd, 30.0f);
gScene->addActor(*rd);
}
}
//Create two vehicles that will drive on the obstacles.
//The vehicles are configured with wheels that
// (i) collide with obstacles
// (ii) have continuous collision detection (CCD) enabled
//(iii) have contact modification enabled
//The vehicle chassis only collides with the ground to highlight the collision between the wheels and the obstacles.
for (PxU32 i = 0; i < NUM_VEHICLES; i++)
{
PxFilterData chassisSimFilterData(COLLISION_FLAG_CHASSIS, COLLISION_FLAG_GROUND, 0, 0);
PxFilterData wheelSimFilterData(COLLISION_FLAG_WHEEL, COLLISION_FLAG_WHEEL, PxPairFlag::eDETECT_CCD_CONTACT | PxPairFlag::eMODIFY_CONTACTS, 0);
VehicleDesc vehicleDesc = initVehicleDesc(chassisSimFilterData, wheelSimFilterData, i);
gVehicle4W[i] = createVehicle4W(vehicleDesc, gPhysics, gCooking);
PxTransform startTransform(PxVec3(xCoordVehicleStarts[i], (vehicleDesc.chassisDims.y*0.5f + vehicleDesc.wheelRadius + 1.0f), 0), PxQuat(PxIdentity));
gVehicle4W[i]->getRigidDynamicActor()->setGlobalPose(startTransform);
gVehicle4W[i]->getRigidDynamicActor()->setRigidBodyFlag(PxRigidBodyFlag::eENABLE_CCD, true);
gScene->addActor(*gVehicle4W[i]->getRigidDynamicActor());
//Set the vehicle to rest in first gear.
//Set the vehicle to use auto-gears.
gVehicle4W[i]->setToRestState();
gVehicle4W[i]->mDriveDynData.forceGearChange(PxVehicleGearsData::eFIRST);
gVehicle4W[i]->mDriveDynData.setUseAutoGears(true);
}
}