void PxVehicleUpdateCMassLocalPose(const PxTransform& oldCMassLocalPose, const PxTransform& newCMassLocalPose, const PxU32 gravityDirection, PxVehicleWheels* vehicle) { PX_CHECK_AND_RETURN(areEqual(PxQuat::createIdentity(), oldCMassLocalPose.q), "Only center of mass poses with identity rotation are supported"); PX_CHECK_AND_RETURN(areEqual(PxQuat::createIdentity(), newCMassLocalPose.q), "Only center of mass poses with identity rotation are supported"); PX_CHECK_AND_RETURN(0==gravityDirection || 1==gravityDirection || 2==gravityDirection, "gravityDirection must be 0 or 1 or 2."); //Update the offsets from the rigid body center of mass. PxVec3 wheelCenterCMOffsets[PX_MAX_NB_WHEELS]; const PxU32 nbWheels = vehicle->mWheelsSimData.getNbWheels(); for(PxU32 i = 0; i < nbWheels; i++) { wheelCenterCMOffsets[i] = vehicle->mWheelsSimData.getWheelCentreOffset(i) + oldCMassLocalPose.p - newCMassLocalPose.p; vehicle->mWheelsSimData.setWheelCentreOffset(i, vehicle->mWheelsSimData.getWheelCentreOffset(i) + oldCMassLocalPose.p - newCMassLocalPose.p); vehicle->mWheelsSimData.setSuspForceAppPointOffset(i, vehicle->mWheelsSimData.getSuspForceAppPointOffset(i) + oldCMassLocalPose.p - newCMassLocalPose.p); vehicle->mWheelsSimData.setTireForceAppPointOffset(i, vehicle->mWheelsSimData.getTireForceAppPointOffset(i) + oldCMassLocalPose.p - newCMassLocalPose.p); } //Now update the sprung masses. PxF32 sprungMasses[PX_MAX_NB_WHEELS]; PxVehicleComputeSprungMasses(nbWheels, wheelCenterCMOffsets, PxVec3(0,0,0), vehicle->getRigidDynamicActor()->getMass(), gravityDirection, sprungMasses); for(PxU32 i = 0; i < nbWheels; i++) { PxVehicleSuspensionData suspData = vehicle->mWheelsSimData.getSuspensionData(i); suspData.setMassAndPreserveNaturalFrequency(sprungMasses[i]); vehicle->mWheelsSimData.setSuspensionData(i, suspData); } }
void Vehicle::setupWheelsSimulationData (const PxF32 wheelMass, const PxF32 wheelMOI, const PxF32 wheelRadius, const PxF32 wheelWidth, const PxU32 numWheels, const PxVec3* wheelCenterActorOffsets, const PxVec3& chassisCMOffset, const PxF32 chassisMass, PxVehicleWheelsSimData* wheelsSimData) { //Set up the wheels. PxVehicleWheelData wheels[PX_MAX_NB_WHEELS]; { //Set up the wheel data structures with mass, moi, radius, width. for (PxU32 i = 0; i < numWheels; i++) { wheels[i].mMass = wheelMass; wheels[i].mMOI = wheelMOI; wheels[i].mRadius = wheelRadius; wheels[i].mWidth = wheelWidth; } //Enable the handbrake for the rear wheels only. wheels[PxVehicleDrive4WWheelOrder::eREAR_LEFT].mMaxHandBrakeTorque = 4000.0f; wheels[PxVehicleDrive4WWheelOrder::eREAR_RIGHT].mMaxHandBrakeTorque = 4000.0f; //Enable steering for the front wheels only. wheels[PxVehicleDrive4WWheelOrder::eFRONT_LEFT].mMaxSteer = PxPi*0.25f; wheels[PxVehicleDrive4WWheelOrder::eFRONT_RIGHT].mMaxSteer = PxPi*0.25f; } //Set up the tires. PxVehicleTireData tires[PX_MAX_NB_WHEELS]; { //Set up the tires. for (PxU32 i = 0; i < numWheels; i++) { tires[i].mType = TIRE_TYPE_NORMAL; } } //Set up the suspensions PxVehicleSuspensionData suspensions[PX_MAX_NB_WHEELS]; { //Compute the mass supported by each suspension spring. PxF32 suspSprungMasses[PX_MAX_NB_WHEELS]; PxVehicleComputeSprungMasses (numWheels, wheelCenterActorOffsets, chassisCMOffset, chassisMass, 1, suspSprungMasses); //Set the suspension data. for (PxU32 i = 0; i < numWheels; i++) { suspensions[i].mMaxCompression = 0.3f; suspensions[i].mMaxDroop = 0.1f; suspensions[i].mSpringStrength = 35000.0f; suspensions[i].mSpringDamperRate = 4500.0f; suspensions[i].mSprungMass = suspSprungMasses[i]; } //Set the camber angles. const PxF32 camberAngleAtRest = 0.0; const PxF32 camberAngleAtMaxDroop = 0.01f; const PxF32 camberAngleAtMaxCompression = -0.01f; for (PxU32 i = 0; i < numWheels; i += 2) { suspensions[i + 0].mCamberAtRest = camberAngleAtRest; suspensions[i + 1].mCamberAtRest = -camberAngleAtRest; suspensions[i + 0].mCamberAtMaxDroop = camberAngleAtMaxDroop; suspensions[i + 1].mCamberAtMaxDroop = -camberAngleAtMaxDroop; suspensions[i + 0].mCamberAtMaxCompression = camberAngleAtMaxCompression; suspensions[i + 1].mCamberAtMaxCompression = -camberAngleAtMaxCompression; } } //Set up the wheel geometry. PxVec3 suspTravelDirections[PX_MAX_NB_WHEELS]; PxVec3 wheelCentreCMOffsets[PX_MAX_NB_WHEELS]; PxVec3 suspForceAppCMOffsets[PX_MAX_NB_WHEELS]; PxVec3 tireForceAppCMOffsets[PX_MAX_NB_WHEELS]; { //Set the geometry data. for (PxU32 i = 0; i < numWheels; i++) { //Vertical suspension travel. suspTravelDirections[i] = PxVec3(0, -1, 0); //Wheel center offset is offset from rigid body center of mass. wheelCentreCMOffsets[i] = wheelCenterActorOffsets[i] - chassisCMOffset; //Suspension force application point 0.3 metres below //rigid body center of mass. suspForceAppCMOffsets[i] = PxVec3(wheelCentreCMOffsets[i].x, -0.3f, wheelCentreCMOffsets[i].z); //Tire force application point 0.3 metres below //rigid body center of mass. tireForceAppCMOffsets[i] = PxVec3(wheelCentreCMOffsets[i].x, -0.3f, wheelCentreCMOffsets[i].z); } } //Set up the filter data of the raycast that will be issued by each suspension. PxFilterData qryFilterData; setupNonDrivableSurface(qryFilterData); //Set the wheel, tire and suspension data. //Set the geometry data. //Set the query filter data for (PxU32 i = 0; i < numWheels; i++) { wheelsSimData->setWheelData(i, wheels[i]); wheelsSimData->setTireData(i, tires[i]); wheelsSimData->setSuspensionData(i, suspensions[i]); wheelsSimData->setSuspTravelDirection(i, suspTravelDirections[i]); wheelsSimData->setWheelCentreOffset(i, wheelCentreCMOffsets[i]); wheelsSimData->setSuspForceAppPointOffset(i, suspForceAppCMOffsets[i]); wheelsSimData->setTireForceAppPointOffset(i, tireForceAppCMOffsets[i]); wheelsSimData->setSceneQueryFilterData(i, qryFilterData); wheelsSimData->setWheelShapeMapping(i, i); } }