From 3dfe2108cfab31ba3ee5527e217d0d8e99a51162 Mon Sep 17 00:00:00 2001 From: git perforce import user Date: Tue, 25 Oct 2016 12:29:14 -0600 Subject: Initial commit: PhysX 3.4.0 Update @ 21294896 APEX 1.4.0 Update @ 21275617 [CL 21300167] --- .../SampleVehicle/SampleVehicle_VehicleManager.cpp | 1171 ++++++++++++++++++++ 1 file changed, 1171 insertions(+) create mode 100644 PhysX_3.4/Samples/SampleVehicle/SampleVehicle_VehicleManager.cpp (limited to 'PhysX_3.4/Samples/SampleVehicle/SampleVehicle_VehicleManager.cpp') diff --git a/PhysX_3.4/Samples/SampleVehicle/SampleVehicle_VehicleManager.cpp b/PhysX_3.4/Samples/SampleVehicle/SampleVehicle_VehicleManager.cpp new file mode 100644 index 00000000..930804c8 --- /dev/null +++ b/PhysX_3.4/Samples/SampleVehicle/SampleVehicle_VehicleManager.cpp @@ -0,0 +1,1171 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and related documentation and +// any modifications thereto. Any use, reproduction, disclosure, or +// distribution of this software and related documentation without an express +// license agreement from NVIDIA Corporation is strictly prohibited. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#include "SampleVehicle.h" +#include "SampleVehicle_VehicleManager.h" +#include "SampleVehicle_VehicleCooking.h" +#include "SampleVehicle_SceneQuery.h" +#include "SampleVehicle_WheelQueryResults.h" +#include "RendererMemoryMacros.h" +#include "vehicle/PxVehicleSDK.h" +#include "vehicle/PxVehicleDrive4W.h" +#include "vehicle/PxVehicleDriveNW.h" +#include "vehicle/PxVehicleDriveTank.h" +#include "vehicle/PxVehicleUpdate.h" +#include "vehicle/PxVehicleTireFriction.h" +#include "vehicle/PxVehicleUtilSetup.h" +#include "PxRigidDynamic.h" +#include "PxScene.h" +#include "geometry/PxConvexMesh.h" +#include "geometry/PxConvexMeshGeometry.h" +#include "SampleAllocatorSDKClasses.h" + +#include "PxVehicleSerialization.h" + +/////////////////////////////////// + +SampleVehicle_VehicleManager::SampleVehicle_VehicleManager() +: mNumVehicles(0), + mSqWheelRaycastBatchQuery(NULL), + mIsIn3WMode(false), + mSerializationRegistry(NULL) +{ +} + +SampleVehicle_VehicleManager::~SampleVehicle_VehicleManager() +{ +} + +void SampleVehicle_VehicleManager::init(PxPhysics& physics, const PxMaterial** drivableSurfaceMaterials, const PxVehicleDrivableSurfaceType* drivableSurfaceTypes) +{ +#if defined(SERIALIZE_VEHICLE_RPEX) || defined(SERIALIZE_VEHICLE_BINARY) + mSerializationRegistry = PxSerialization::createSerializationRegistry(physics); +#endif + + //Initialise the sdk. + PxInitVehicleSDK(physics, mSerializationRegistry); + + //Set the basis vectors. + PxVec3 up(0,1,0); + PxVec3 forward(0,0,1); + PxVehicleSetBasisVectors(up,forward); + + //Set the vehicle update mode to be immediate velocity changes. + PxVehicleSetUpdateMode(PxVehicleUpdateMode::eVELOCITY_CHANGE); + + //Initialise all vehicle ptrs to null. + for(PxU32 i=0;isetup(MAX_NUM_TIRE_TYPES,MAX_NUM_SURFACE_TYPES,drivableSurfaceMaterials,drivableSurfaceTypes); + for(PxU32 i=0;isetTypePairFriction(i,j,TireFrictionMultipliers::getValue(i, j)); + } + } +} + +void SampleVehicle_VehicleManager::shutdown() +{ + //Remove the N-wheeled vehicles. + for(PxU32 i=0;igetVehicleType()) + { + case PxVehicleTypes::eDRIVE4W: + { + PxVehicleDrive4W* veh=(PxVehicleDrive4W*)mVehicles[i]; + veh->free(); + } + break; + case PxVehicleTypes::eDRIVENW: + { + PxVehicleDriveNW* veh=(PxVehicleDriveNW*)mVehicles[i]; + veh->free(); + } + break; + case PxVehicleTypes::eDRIVETANK: + { + PxVehicleDriveTank* veh=(PxVehicleDriveTank*)mVehicles[i]; + veh->free(); + } + break; + default: + PX_ASSERT(false); + break; + } + } + + //Deallocate simulation data that was used to switch from 3-wheeled to 4-wheeled cars by switching simulation data. + mWheelsSimData4W->free(); + + //Deallocate scene query data that was used for suspension raycasts. + mSqData->free(); + + //Deallocate buffers that store wheel reports. + mWheelQueryResults->free(); + + //Release the friction values used for combinations of tire type and surface type. + mSurfaceTirePairs->release(); + + //Scene query. + if(mSqWheelRaycastBatchQuery) + { + mSqWheelRaycastBatchQuery=NULL; + } + + PxCloseVehicleSDK(mSerializationRegistry); + + if(mSerializationRegistry) + mSerializationRegistry->release(); +} + +void SampleVehicle_VehicleManager::addVehicle(const PxU32 i, PxVehicleWheels* vehicle) +{ + mVehicles[i] = vehicle; + + const PxU32 numWheels = vehicle->mWheelsSimData.getNbWheels(); + mVehicleWheelQueryResults[i].nbWheelQueryResults = numWheels; + mVehicleWheelQueryResults[i].wheelQueryResults = mWheelQueryResults->addVehicle(numWheels); + + mNumVehicles++; +} + + +void SampleVehicle_VehicleManager::resetNWCar(const PxTransform& transform, const PxU32 vehicleId) +{ + PX_ASSERT(vehicleIdsetUpBatchedSceneQuery(scene); + } + //Raycasts. + PxSceneReadLock scopedLock(*scene); + PxVehicleSuspensionRaycasts(mSqWheelRaycastBatchQuery,mNumVehicles,mVehicles,mSqData->getRaycastQueryResultBufferSize(),mSqData->getRaycastQueryResultBuffer()); +} + + +#if PX_DEBUG_VEHICLE_ON + +void SampleVehicle_VehicleManager::updateAndRecordTelemetryData +(const PxF32 timestep, const PxVec3& gravity, PxVehicleWheels* focusVehicle, PxVehicleTelemetryData* telemetryData) +{ + PX_ASSERT(focusVehicle && telemetryData); + + //Update all vehicles except for focusVehicle. + PxVehicleWheels* vehicles[MAX_NUM_4W_VEHICLES+MAX_NUM_6W_VEHICLES]; + PxVehicleWheelQueryResult vehicleWheelQueryResults[MAX_NUM_4W_VEHICLES+MAX_NUM_6W_VEHICLES]; + PxVehicleWheelQueryResult focusVehicleWheelQueryResults[1]; + PxU32 numVehicles=0; + for(PxU32 i=0;igetVehicleType()) + { + case PxVehicleTypes::eDRIVE4W: + { + PxVehicleDrive4W* vehDrive4W=(PxVehicleDrive4W*)vehWheels; + //Set the car back to its rest state. + vehDrive4W->setToRestState(); + //Set the car to first gear. + vehDrive4W->mDriveDynData.forceGearChange(PxVehicleGearsData::eFIRST); + } + break; + case PxVehicleTypes::eDRIVENW: + { + PxVehicleDriveNW* vehDriveNW=(PxVehicleDriveNW*)vehWheels; + //Set the car back to its rest state. + vehDriveNW->setToRestState(); + //Set the car to first gear. + vehDriveNW->mDriveDynData.forceGearChange(PxVehicleGearsData::eFIRST); + } + break; + case PxVehicleTypes::eDRIVETANK: + { + PxVehicleDriveTank* vehDriveTank=(PxVehicleDriveTank*)vehWheels; + //Set the car back to its rest state. + vehDriveTank->setToRestState(); + //Set the car to first gear. + vehDriveTank->mDriveDynData.forceGearChange(PxVehicleGearsData::eFIRST); + } + break; + default: + PX_ASSERT(false); + break; + } + + //Set the car's transform to be the start transform. + PxRigidDynamic* actor=vehWheels->getRigidDynamicActor(); + PxSceneWriteLock scopedLock(*actor->getScene()); + actor->setGlobalPose(startTransform); +} + +void setupActor +(PxRigidDynamic* vehActor, + const PxFilterData& vehQryFilterData, + const PxGeometry** wheelGeometries, const PxTransform* wheelLocalPoses, const PxU32 numWheelGeometries, const PxMaterial* wheelMaterial, const PxFilterData& wheelCollFilterData, + const PxGeometry** chassisGeometries, const PxTransform* chassisLocalPoses, const PxU32 numChassisGeometries, const PxMaterial* chassisMaterial, const PxFilterData& chassisCollFilterData, + const PxVehicleChassisData& chassisData, + PxPhysics* physics) +{ + //Add all the wheel shapes to the actor. + for(PxU32 i=0;isetQueryFilterData(vehQryFilterData); + wheelShape->setSimulationFilterData(wheelCollFilterData); + wheelShape->setLocalPose(wheelLocalPoses[i]); + } + + //Add the chassis shapes to the actor. + for(PxU32 i=0;isetQueryFilterData(vehQryFilterData); + chassisShape->setSimulationFilterData(chassisCollFilterData); + chassisShape->setLocalPose(chassisLocalPoses[i]); + } + + vehActor->setMass(chassisData.mMass); + vehActor->setMassSpaceInertiaTensor(chassisData.mMOI); + vehActor->setCMassLocalPose(PxTransform(chassisData.mCMOffset,PxQuat(PxIdentity))); +} + +PxRigidDynamic* createVehicleActor4W +(const PxVehicleChassisData& chassisData, + PxConvexMesh** wheelConvexMeshes, PxConvexMesh* chassisConvexMesh, + PxScene& scene, PxPhysics& physics, const PxMaterial& material) +{ + //We need a rigid body actor for the vehicle. + //Don't forget to add the actor the scene after setting up the associated vehicle. + PxRigidDynamic* vehActor=physics.createRigidDynamic(PxTransform(PxIdentity)); + + //We need to add wheel collision shapes, their local poses, a material for the wheels, and a simulation filter for the wheels. + PxConvexMeshGeometry frontLeftWheelGeom(wheelConvexMeshes[0]); + PxConvexMeshGeometry frontRightWheelGeom(wheelConvexMeshes[1]); + PxConvexMeshGeometry rearLeftWheelGeom(wheelConvexMeshes[2]); + PxConvexMeshGeometry rearRightWheelGeom(wheelConvexMeshes[3]); + const PxGeometry* wheelGeometries[4]={&frontLeftWheelGeom,&frontRightWheelGeom,&rearLeftWheelGeom,&rearRightWheelGeom}; + const PxTransform wheelLocalPoses[4]={PxTransform(PxIdentity),PxTransform(PxIdentity),PxTransform(PxIdentity),PxTransform(PxIdentity)}; + const PxMaterial& wheelMaterial=material; + PxFilterData wheelCollFilterData; + wheelCollFilterData.word0=COLLISION_FLAG_WHEEL; + wheelCollFilterData.word1=COLLISION_FLAG_WHEEL_AGAINST; + + //We need to add chassis collision shapes, their local poses, a material for the chassis, and a simulation filter for the chassis. + PxConvexMeshGeometry chassisConvexGeom(chassisConvexMesh); + const PxGeometry* chassisGeoms[1]={&chassisConvexGeom}; + const PxTransform chassisLocalPoses[1]={PxTransform(PxIdentity)}; + const PxMaterial& chassisMaterial=material; + PxFilterData chassisCollFilterData; + chassisCollFilterData.word0=COLLISION_FLAG_CHASSIS; + chassisCollFilterData.word1=COLLISION_FLAG_CHASSIS_AGAINST; + + //Create a query filter data for the car to ensure that cars + //do not attempt to drive on themselves. + PxFilterData vehQryFilterData; + SampleVehicleSetupVehicleShapeQueryFilterData(&vehQryFilterData); + + //Set up the physx rigid body actor with shapes, local poses, and filters. + setupActor + (vehActor, + vehQryFilterData, + wheelGeometries,wheelLocalPoses,4,&wheelMaterial,wheelCollFilterData, + chassisGeoms,chassisLocalPoses,1,&chassisMaterial,chassisCollFilterData, + chassisData, + &physics); + + return vehActor; +} + +void computeWheelWidthsAndRadii(PxConvexMesh** wheelConvexMeshes, PxF32* wheelWidths, PxF32* wheelRadii) +{ + for(PxU32 i=0;i<4;i++) + { + const PxU32 numWheelVerts=wheelConvexMeshes[i]->getNbVertices(); + const PxVec3* wheelVerts=wheelConvexMeshes[i]->getVertices(); + PxVec3 wheelMin(PX_MAX_F32,PX_MAX_F32,PX_MAX_F32); + PxVec3 wheelMax(-PX_MAX_F32,-PX_MAX_F32,-PX_MAX_F32); + for(PxU32 j=0;jgetNbVertices(); + const PxVec3* chassisVerts=chassisConvexMesh->getVertices(); + PxVec3 chassisMin(PX_MAX_F32,PX_MAX_F32,PX_MAX_F32); + PxVec3 chassisMax(-PX_MAX_F32,-PX_MAX_F32,-PX_MAX_F32); + for(PxU32 i=0;isetup(&physics,vehActor,*wheelsSimData,driveSimData,0); + + //Free the sim data because we don't need that any more. + wheelsSimData->free(); + + //Don't forget to add the actor to the scene. + { + PxSceneWriteLock scopedLock(scene); + scene.addActor(*vehActor); + } + + + //Set up the mapping between wheel and actor shape. + car->mWheelsSimData.setWheelShapeMapping(0,0); + car->mWheelsSimData.setWheelShapeMapping(1,1); + car->mWheelsSimData.setWheelShapeMapping(2,2); + car->mWheelsSimData.setWheelShapeMapping(3,3); + + //Set up the scene query filter data for each suspension line. + PxFilterData vehQryFilterData; + SampleVehicleSetupVehicleShapeQueryFilterData(&vehQryFilterData); + car->mWheelsSimData.setSceneQueryFilterData(0, vehQryFilterData); + car->mWheelsSimData.setSceneQueryFilterData(1, vehQryFilterData); + car->mWheelsSimData.setSceneQueryFilterData(2, vehQryFilterData); + car->mWheelsSimData.setSceneQueryFilterData(3, vehQryFilterData); + + //Set the transform and the instantiated car and set it be to be at rest. + resetNWCar(startTransform,car); + //Set the autogear mode of the instantiate car. + car->mDriveDynData.setUseAutoGears(useAutoGearFlag); + + //Increment the number of vehicles + mVehicles[mNumVehicles]=car; + mVehicleWheelQueryResults[mNumVehicles].nbWheelQueryResults=4; + mVehicleWheelQueryResults[mNumVehicles].wheelQueryResults=mWheelQueryResults->addVehicle(4); + mNumVehicles++; +} + +PxRigidDynamic* createVehicleActor6W +(const PxVehicleChassisData& chassisData, + PxConvexMesh** wheelConvexMeshes, PxConvexMesh* chassisConvexMesh, + PxScene& scene, PxPhysics& physics, const PxMaterial& material) +{ + PxTransform ident=PxTransform(PxIdentity); + + //We need a rigid body actor for the vehicle. + //Don't forget to add the actor the scene after setting up the associated vehicle. + PxRigidDynamic* vehActor=physics.createRigidDynamic(PxTransform(PxIdentity)); + + //We need to add wheel collision shapes, their local poses, a material for the wheels, and a simulation filter for the wheels. + PxConvexMeshGeometry frontLeftWheelGeom(wheelConvexMeshes[0]); + PxConvexMeshGeometry frontRightWheelGeom(wheelConvexMeshes[1]); + PxConvexMeshGeometry rearLeftWheelGeom(wheelConvexMeshes[2]); + PxConvexMeshGeometry rearRightWheelGeom(wheelConvexMeshes[3]); + PxConvexMeshGeometry extraWheel0(wheelConvexMeshes[0]); + PxConvexMeshGeometry extraWheel1(wheelConvexMeshes[1]); + const PxGeometry* wheelGeoms[6]={&frontLeftWheelGeom,&frontRightWheelGeom,&rearLeftWheelGeom,&rearRightWheelGeom,&extraWheel0,&extraWheel1}; + const PxTransform wheelLocalPoses[6]={ident,ident,ident,ident,ident,ident}; + const PxMaterial& wheelMaterial=material; + PxFilterData wheelCollFilterData; + wheelCollFilterData.word0=COLLISION_FLAG_WHEEL; + wheelCollFilterData.word1=COLLISION_FLAG_WHEEL_AGAINST; + + //We need to add chassis collision shapes, their local poses, a material for the chassis, and a simulation filter for the chassis. + PxConvexMeshGeometry chassisConvexGeom(chassisConvexMesh); + const PxGeometry* chassisGeoms[1]={&chassisConvexGeom}; + const PxTransform chassisLocalPoses[1]={ident}; + const PxMaterial& chassisMaterial=material; + PxFilterData chassisCollFilterData; + chassisCollFilterData.word0=COLLISION_FLAG_CHASSIS; + chassisCollFilterData.word1=COLLISION_FLAG_CHASSIS_AGAINST; + + //Create a query filter data for the car to ensure that cars + //do not attempt to drive on themselves. + PxFilterData vehQryFilterData; + SampleVehicleSetupVehicleShapeQueryFilterData(&vehQryFilterData); + + //Set up the physx rigid body actor with shapes, local poses, and filters. + setupActor( + vehActor, + vehQryFilterData, + wheelGeoms,wheelLocalPoses,6,&wheelMaterial,wheelCollFilterData, + chassisGeoms,chassisLocalPoses,1,&chassisMaterial,chassisCollFilterData, + chassisData, + &physics); + + return vehActor; +} + +void createVehicle6WSimulationData +(const PxF32 chassisMass, const PxVec3* wheelCentreOffsets4, PxConvexMesh* chassisConvexMesh, PxConvexMesh** wheelConvexMeshes4, + PxVehicleWheelsSimData& wheelsSimData6W, PxVehicleDriveSimData4W& driveSimData6W, PxVehicleChassisData& chassisData6W) +{ + //Start by constructing the simulation data for a 4-wheeled vehicle. + PxVehicleWheelsSimData* wheelsSimData4W=PxVehicleWheelsSimData::allocate(4); + PxVehicleDriveSimData4W driveData4W; + PxVehicleChassisData chassisData4W; + createVehicle4WSimulationData( + chassisMass,chassisConvexMesh, + 20.0f,wheelConvexMeshes4,wheelCentreOffsets4, + *wheelsSimData4W,driveData4W,chassisData4W); + + //Quickly setup the simulation data for the 6-wheeled vehicle. + //(this will copy wheel4 from wheel0 and wheel5 from wheel1). + driveSimData6W=driveData4W; + wheelsSimData6W.copy(*wheelsSimData4W,0,0); + wheelsSimData6W.copy(*wheelsSimData4W,1,1); + wheelsSimData6W.copy(*wheelsSimData4W,2,2); + wheelsSimData6W.copy(*wheelsSimData4W,3,3); + wheelsSimData6W.copy(*wheelsSimData4W,0,4); + wheelsSimData6W.copy(*wheelsSimData4W,1,5); + wheelsSimData6W.setTireLoadFilterData(wheelsSimData4W->getTireLoadFilterData()); + chassisData6W = chassisData4W; + + //Make sure that the two non-driven wheels don't respond to the handbrake. + PxVehicleWheelData wheelData; + wheelData=wheelsSimData6W.getWheelData(4); + wheelData.mMaxHandBrakeTorque=0.0f; + wheelsSimData6W.setWheelData(4,wheelData); + wheelData=wheelsSimData6W.getWheelData(5); + wheelData.mMaxHandBrakeTorque=0.0f; + wheelsSimData6W.setWheelData(5,wheelData); + + //We've now got a 6-wheeled vehicle but the offsets of the 2 extra wheels are still incorrect. + //Lets set up the 2 extra wheels to lie on an axle that goes through the centre of the car + //and is parallel to the front and rear axles. + { + PxVec3 w; + PxF32 offsetLeft; + PxF32 offsetRight; + + offsetLeft=0.5f*(wheelsSimData6W.getWheelCentreOffset(0).z+wheelsSimData6W.getWheelCentreOffset(2).z); + w=wheelsSimData4W->getWheelCentreOffset(0); + w.z=offsetLeft; + wheelsSimData6W.setWheelCentreOffset(4,w); + offsetRight=0.5f*(wheelsSimData6W.getWheelCentreOffset(1).z+wheelsSimData6W.getWheelCentreOffset(3).z); + w=wheelsSimData6W.getWheelCentreOffset(1); + w.z=offsetRight; + wheelsSimData6W.setWheelCentreOffset(5,w); + + offsetLeft=0.5f*(wheelsSimData6W.getSuspForceAppPointOffset(0).z+wheelsSimData6W.getSuspForceAppPointOffset(2).z); + w=wheelsSimData4W->getSuspForceAppPointOffset(0); + w.z=offsetLeft; + wheelsSimData6W.setSuspForceAppPointOffset(4,w); + offsetRight=0.5f*(wheelsSimData6W.getSuspForceAppPointOffset(1).z+wheelsSimData6W.getSuspForceAppPointOffset(3).z); + w=wheelsSimData6W.getSuspForceAppPointOffset(1); + w.z=offsetRight; + wheelsSimData6W.setSuspForceAppPointOffset(5,w); + + offsetLeft=0.5f*(wheelsSimData6W.getTireForceAppPointOffset(0).z+wheelsSimData6W.getTireForceAppPointOffset(2).z); + w=wheelsSimData4W->getTireForceAppPointOffset(0); + w.z=offsetLeft; + wheelsSimData6W.setTireForceAppPointOffset(4,w); + offsetRight=0.5f*(wheelsSimData6W.getTireForceAppPointOffset(1).z+wheelsSimData6W.getTireForceAppPointOffset(3).z); + w=wheelsSimData6W.getTireForceAppPointOffset(1); + w.z=offsetRight; + wheelsSimData6W.setTireForceAppPointOffset(5,w); + } + + //The first 4 wheels were all set up to support a mass M but now that mass is + //distributed between 6 wheels. Adjust the suspension springs accordingly + //and try to preserve the natural frequency and damping ratio of the springs. + for(PxU32 i=0;i<4;i++) + { + PxVehicleSuspensionData suspData=wheelsSimData6W.getSuspensionData(i); + suspData.mSprungMass*=0.6666f; + suspData.mSpringStrength*=0.666f; + suspData.mSpringDamperRate*=0.666f; + wheelsSimData6W.setSuspensionData(i,suspData); + } + const PxF32 sprungMass=(wheelsSimData6W.getSuspensionData(0).mSprungMass+wheelsSimData6W.getSuspensionData(3).mSprungMass)/2.0f; + const PxF32 strength=(wheelsSimData6W.getSuspensionData(0).mSpringStrength+wheelsSimData6W.getSuspensionData(3).mSpringStrength)/2.0f; + const PxF32 damperRate=(wheelsSimData6W.getSuspensionData(0).mSpringDamperRate+wheelsSimData6W.getSuspensionData(3).mSpringDamperRate)/2.0f; + PxVehicleSuspensionData suspData4=wheelsSimData6W.getSuspensionData(4); + suspData4.mSprungMass=sprungMass; + suspData4.mSpringStrength=strength; + suspData4.mSpringDamperRate=damperRate; + wheelsSimData6W.setSuspensionData(4,suspData4); + PxVehicleSuspensionData suspData5=wheelsSimData6W.getSuspensionData(5); + suspData5.mSprungMass=sprungMass; + suspData5.mSpringStrength=strength; + suspData5.mSpringDamperRate=damperRate; + wheelsSimData6W.setSuspensionData(5,suspData5); + + //Free the 4W sim data because we don't need this any more. + wheelsSimData4W->free(); +} + + +void createVehicle6WSimulationData +(const PxF32 chassisMass, const PxVec3* wheelCentreOffsets4, PxConvexMesh* chassisConvexMesh, PxConvexMesh** wheelConvexMeshes4, + PxVehicleWheelsSimData& wheelsSimData6W, PxVehicleDriveSimDataNW& driveSimData6W, PxVehicleChassisData& chassisData6W) +{ + //Start by constructing the simulation data for a 4-wheeled vehicle. + PxVehicleWheelsSimData* wheelsSimData4W=PxVehicleWheelsSimData::allocate(4); + PxVehicleDriveSimData4W driveData4W; + PxVehicleChassisData chassisData4W; + createVehicle4WSimulationData( + chassisMass,chassisConvexMesh, + 20.0f,wheelConvexMeshes4,wheelCentreOffsets4, + *wheelsSimData4W,driveData4W,chassisData4W); + + //Quickly setup the simulation data for the 6-wheeled vehicle. + //(this will copy wheel4 from wheel0 and wheel5 from wheel1). + driveSimData6W.setAutoBoxData(driveData4W.getAutoBoxData()); + driveSimData6W.setClutchData(driveData4W.getClutchData()); + driveSimData6W.setEngineData(driveData4W.getEngineData()); + driveSimData6W.setGearsData(driveData4W.getGearsData()); + PxVehicleDifferentialNWData diffNW; + diffNW.setDrivenWheel(0,true); + diffNW.setDrivenWheel(1,true); + diffNW.setDrivenWheel(2,true); + diffNW.setDrivenWheel(3,true); + diffNW.setDrivenWheel(4,true); + diffNW.setDrivenWheel(5,true); + driveSimData6W.setDiffData(diffNW); + wheelsSimData6W.copy(*wheelsSimData4W,0,0); + wheelsSimData6W.copy(*wheelsSimData4W,1,1); + wheelsSimData6W.copy(*wheelsSimData4W,2,2); + wheelsSimData6W.copy(*wheelsSimData4W,3,3); + wheelsSimData6W.copy(*wheelsSimData4W,0,4); + wheelsSimData6W.copy(*wheelsSimData4W,1,5); + wheelsSimData6W.setTireLoadFilterData(wheelsSimData4W->getTireLoadFilterData()); + chassisData6W = chassisData4W; + + //Make sure that the two non-driven wheels don't respond to the handbrake. + PxVehicleWheelData wheelData; + wheelData=wheelsSimData6W.getWheelData(4); + wheelData.mMaxHandBrakeTorque=0.0f; + wheelsSimData6W.setWheelData(4,wheelData); + wheelData=wheelsSimData6W.getWheelData(5); + wheelData.mMaxHandBrakeTorque=0.0f; + wheelsSimData6W.setWheelData(5,wheelData); + + //We've now got a 6-wheeled vehicle but the offsets of the 2 extra wheels are still incorrect. + //Lets set up the 2 extra wheels to lie on an axle that goes through the centre of the car + //and is parallel to the front and rear axles. + { + PxVec3 w; + PxF32 offsetLeft; + PxF32 offsetRight; + + offsetLeft=0.5f*(wheelsSimData6W.getWheelCentreOffset(0).z+wheelsSimData6W.getWheelCentreOffset(2).z); + w=wheelsSimData4W->getWheelCentreOffset(0); + w.z=offsetLeft; + wheelsSimData6W.setWheelCentreOffset(4,w); + offsetRight=0.5f*(wheelsSimData6W.getWheelCentreOffset(1).z+wheelsSimData6W.getWheelCentreOffset(3).z); + w=wheelsSimData6W.getWheelCentreOffset(1); + w.z=offsetRight; + wheelsSimData6W.setWheelCentreOffset(5,w); + + offsetLeft=0.5f*(wheelsSimData6W.getSuspForceAppPointOffset(0).z+wheelsSimData6W.getSuspForceAppPointOffset(2).z); + w=wheelsSimData4W->getSuspForceAppPointOffset(0); + w.z=offsetLeft; + wheelsSimData6W.setSuspForceAppPointOffset(4,w); + offsetRight=0.5f*(wheelsSimData6W.getSuspForceAppPointOffset(1).z+wheelsSimData6W.getSuspForceAppPointOffset(3).z); + w=wheelsSimData6W.getSuspForceAppPointOffset(1); + w.z=offsetRight; + wheelsSimData6W.setSuspForceAppPointOffset(5,w); + + offsetLeft=0.5f*(wheelsSimData6W.getTireForceAppPointOffset(0).z+wheelsSimData6W.getTireForceAppPointOffset(2).z); + w=wheelsSimData4W->getTireForceAppPointOffset(0); + w.z=offsetLeft; + wheelsSimData6W.setTireForceAppPointOffset(4,w); + offsetRight=0.5f*(wheelsSimData6W.getTireForceAppPointOffset(1).z+wheelsSimData6W.getTireForceAppPointOffset(3).z); + w=wheelsSimData6W.getTireForceAppPointOffset(1); + w.z=offsetRight; + wheelsSimData6W.setTireForceAppPointOffset(5,w); + } + + //The first 4 wheels were all set up to support a mass M but now that mass is + //distributed between 6 wheels. Adjust the suspension springs accordingly + //and try to preserve the natural frequency and damping ratio of the springs. + for(PxU32 i=0;i<4;i++) + { + PxVehicleSuspensionData suspData=wheelsSimData6W.getSuspensionData(i); + suspData.mSprungMass*=0.6666f; + suspData.mSpringStrength*=0.666f; + suspData.mSpringDamperRate*=0.666f; + wheelsSimData6W.setSuspensionData(i,suspData); + } + const PxF32 sprungMass=(wheelsSimData6W.getSuspensionData(0).mSprungMass+wheelsSimData6W.getSuspensionData(3).mSprungMass)/2.0f; + const PxF32 strength=(wheelsSimData6W.getSuspensionData(0).mSpringStrength+wheelsSimData6W.getSuspensionData(3).mSpringStrength)/2.0f; + const PxF32 damperRate=(wheelsSimData6W.getSuspensionData(0).mSpringDamperRate+wheelsSimData6W.getSuspensionData(3).mSpringDamperRate)/2.0f; + PxVehicleSuspensionData suspData4=wheelsSimData6W.getSuspensionData(4); + suspData4.mSprungMass=sprungMass; + suspData4.mSpringStrength=strength; + suspData4.mSpringDamperRate=damperRate; + wheelsSimData6W.setSuspensionData(4,suspData4); + PxVehicleSuspensionData suspData5=wheelsSimData6W.getSuspensionData(5); + suspData5.mSprungMass=sprungMass; + suspData5.mSpringStrength=strength; + suspData5.mSpringDamperRate=damperRate; + wheelsSimData6W.setSuspensionData(5,suspData5); + + //Free the 4W sim data because we don't need this any more. + wheelsSimData4W->free(); +} + +void SampleVehicle_VehicleManager::create6WVehicle +(PxScene& scene, PxPhysics& physics, PxCooking& cooking, const PxMaterial& material, + const PxF32 chassisMass, const PxVec3* wheelCentreOffsets4, PxConvexMesh* chassisConvexMesh, PxConvexMesh** wheelConvexMeshes4, + const PxTransform& startTransform, const bool useAutoGearFlag) +{ + PX_ASSERT(mNumVehiclessetup(&physics,vehActor,*wheelsSimData,driveSimData,6); + + //Free the sim data because we don't need that any more. + wheelsSimData->free(); + + //Don't forget to add the actor to the scene. + { + PxSceneWriteLock scopedLock(scene); + scene.addActor(*vehActor); + } + + //Set up the mapping between wheel and actor shape. + car->mWheelsSimData.setWheelShapeMapping(0,0); + car->mWheelsSimData.setWheelShapeMapping(1,1); + car->mWheelsSimData.setWheelShapeMapping(2,2); + car->mWheelsSimData.setWheelShapeMapping(3,3); + car->mWheelsSimData.setWheelShapeMapping(4,4); + car->mWheelsSimData.setWheelShapeMapping(5,5); + + //Set up the scene query filter data for each suspension line. + PxFilterData vehQryFilterData; + SampleVehicleSetupVehicleShapeQueryFilterData(&vehQryFilterData); + car->mWheelsSimData.setSceneQueryFilterData(0, vehQryFilterData); + car->mWheelsSimData.setSceneQueryFilterData(1, vehQryFilterData); + car->mWheelsSimData.setSceneQueryFilterData(2, vehQryFilterData); + car->mWheelsSimData.setSceneQueryFilterData(3, vehQryFilterData); + car->mWheelsSimData.setSceneQueryFilterData(4, vehQryFilterData); + car->mWheelsSimData.setSceneQueryFilterData(5, vehQryFilterData); + + //Set the transform and the instantiated car and set it be to be at rest. + resetNWCar(startTransform,car); + //Set the autogear mode of the instantiate car. + car->mDriveDynData.setUseAutoGears(useAutoGearFlag); + + //Increment the number of vehicles + mVehicles[mNumVehicles]=car; + mVehicleWheelQueryResults[mNumVehicles].nbWheelQueryResults=6; + mVehicleWheelQueryResults[mNumVehicles].wheelQueryResults=mWheelQueryResults->addVehicle(6); + mNumVehicles++; +} + +void setTank4WCustomisations(PxVehicleWheelsSimData& suspWheelTyreData, PxVehicleDriveSimData& coreData, const PxVehicleDriveTankControlModel::Enum tankDriveModel) +{ + //Increase damping, especially when the clutch isn't engaged. + for(PxU32 i=0;i<4;i++) + { + PxVehicleWheelData wheelData=suspWheelTyreData.getWheelData(i); + wheelData.mDampingRate=2.0f; + suspWheelTyreData.setWheelData(i,wheelData); + } + PxVehicleEngineData engineData=coreData.getEngineData(); + engineData.mDampingRateZeroThrottleClutchEngaged=2.0f; + engineData.mDampingRateZeroThrottleClutchDisengaged=0.5f; + engineData.mDampingRateFullThrottle=0.5f; + //engineData.mPeakTorque=1500; + coreData.setEngineData(engineData); + + if(PxVehicleDriveTankControlModel::eSPECIAL==tankDriveModel) + { + PxVehicleGearsData gearsData=coreData.getGearsData(); + gearsData.mFinalRatio=16; + coreData.setGearsData(gearsData); + } +} + +void SampleVehicle_VehicleManager::create4WTank +(PxScene& scene, PxPhysics& physics, PxCooking& cooking, const PxMaterial& material, + const PxF32 chassisMass, const PxVec3* wheelCentreOffsets4, PxConvexMesh* chassisConvexMesh, PxConvexMesh** wheelConvexMeshes4, + const PxTransform& startTransform, const bool useAutoGearFlag, const PxVehicleDriveTankControlModel::Enum tankDriveModel) +{ + PX_ASSERT(mNumVehicles<(MAX_NUM_4W_VEHICLES+MAX_NUM_6W_VEHICLES)); + + //Create simulation data for 4W drive car. + PxVehicleWheelsSimData* wheelsSimData = PxVehicleWheelsSimData::allocate(4); + PxVehicleDriveSimData4W driveSimData; + PxVehicleChassisData chassisData; + createVehicle4WSimulationData( + chassisMass,chassisConvexMesh, + 20.0f,wheelConvexMeshes4,wheelCentreOffsets4, + *wheelsSimData,driveSimData,chassisData); + + //Copy the relevant tank data and customise. + PxVehicleDriveSimData tankDriveSimData; + tankDriveSimData.setEngineData(driveSimData.getEngineData()); + tankDriveSimData.setGearsData(driveSimData.getGearsData()); + tankDriveSimData.setClutchData(driveSimData.getClutchData()); + tankDriveSimData.setAutoBoxData(driveSimData.getAutoBoxData()); + setTank4WCustomisations(*wheelsSimData,tankDriveSimData,tankDriveModel); + + //Instantiate and finalize the vehicle using physx. + PxRigidDynamic* vehActor=createVehicleActor4W(chassisData,wheelConvexMeshes4,chassisConvexMesh,scene,physics,material); + + //Create a tank. + PxVehicleDriveTank* tank = PxVehicleDriveTank::allocate(4); + tank->setup(&physics,vehActor,*wheelsSimData,tankDriveSimData,4); + + //Free the sim data because we don't need that any more. + wheelsSimData->free(); + + //Don't forget to add the actor to the scene. + scene.addActor(*vehActor); + + //Set up the mapping between wheel and actor shape. + tank->mWheelsSimData.setWheelShapeMapping(0,0); + tank->mWheelsSimData.setWheelShapeMapping(1,1); + tank->mWheelsSimData.setWheelShapeMapping(2,2); + tank->mWheelsSimData.setWheelShapeMapping(3,3); + + //Set up the scene query filter data for each suspension line. + PxFilterData vehQryFilterData; + SampleVehicleSetupVehicleShapeQueryFilterData(&vehQryFilterData); + tank->mWheelsSimData.setSceneQueryFilterData(0, vehQryFilterData); + tank->mWheelsSimData.setSceneQueryFilterData(1, vehQryFilterData); + tank->mWheelsSimData.setSceneQueryFilterData(2, vehQryFilterData); + tank->mWheelsSimData.setSceneQueryFilterData(3, vehQryFilterData); + + //Set the transform and the instantiated car and set it be to be at rest. + resetNWCar(startTransform,tank); + //Set the autogear mode of the instantiate car. + tank->mDriveDynData.setUseAutoGears(useAutoGearFlag); + //Set the drive model. + tank->setDriveModel(tankDriveModel); + + //Increment the number of vehicles + mVehicles[mNumVehicles]=tank; + mVehicleWheelQueryResults[mNumVehicles].nbWheelQueryResults=4; + mVehicleWheelQueryResults[mNumVehicles].wheelQueryResults=mWheelQueryResults->addVehicle(4); + mNumVehicles++; +} + +void setTank6WCustomisations(PxVehicleWheelsSimData& suspWheelTyreData, PxVehicleDriveSimData& coreData, const PxVehicleDriveTankControlModel::Enum tankDriveModel) +{ + //Increase damping, especially when the clutch isn't engaged. + for(PxU32 i=0;i<6;i++) + { + PxVehicleWheelData wheelData=suspWheelTyreData.getWheelData(i); + wheelData.mDampingRate=2.0f; + suspWheelTyreData.setWheelData(i,wheelData); + } + PxVehicleEngineData engineData=coreData.getEngineData(); + engineData.mDampingRateZeroThrottleClutchEngaged=2.0f; + engineData.mDampingRateZeroThrottleClutchDisengaged=0.5f; + engineData.mDampingRateFullThrottle=0.5f; + //engineData.mPeakTorque=1500; + coreData.setEngineData(engineData); + + if(PxVehicleDriveTankControlModel::eSPECIAL==tankDriveModel) + { + PxVehicleGearsData gearsData=coreData.getGearsData(); + gearsData.mFinalRatio=16; + coreData.setGearsData(gearsData); + } +} + +void SampleVehicle_VehicleManager::create6WTank +(PxScene& scene, PxPhysics& physics, PxCooking& cooking, const PxMaterial& material, + const PxF32 chassisMass, const PxVec3* wheelCentreOffsets4, PxConvexMesh* chassisConvexMesh, PxConvexMesh** wheelConvexMeshes4, + const PxTransform& startTransform, const bool useAutoGearFlag, const PxVehicleDriveTankControlModel::Enum tankDriveModel) +{ + //Create simulation data for 4W drive car. + PxVehicleWheelsSimData* wheelsSimData=PxVehicleWheelsSimData::allocate(6); + PxVehicleDriveSimData4W driveSimData; + PxVehicleChassisData chassisData; + createVehicle6WSimulationData(chassisMass,wheelCentreOffsets4,chassisConvexMesh,wheelConvexMeshes4,*wheelsSimData,driveSimData,chassisData); + + //Copy the relevant tank data and customize. + PxVehicleDriveSimData tankDriveSimData; + tankDriveSimData.setEngineData(driveSimData.getEngineData()); + tankDriveSimData.setGearsData(driveSimData.getGearsData()); + tankDriveSimData.setClutchData(driveSimData.getClutchData()); + tankDriveSimData.setAutoBoxData(driveSimData.getAutoBoxData()); + setTank6WCustomisations(*wheelsSimData,tankDriveSimData,tankDriveModel); + + //Instantiate and finalize the vehicle using physx. + PxRigidDynamic* vehActor=createVehicleActor6W(chassisData,wheelConvexMeshes4,chassisConvexMesh,scene,physics,material); + + //Create a tank. + PxVehicleDriveTank* tank = PxVehicleDriveTank::allocate(6); + tank->setup(&physics,vehActor,*wheelsSimData,tankDriveSimData,6); + + //Free the sim data because we don't need that any more. + wheelsSimData->free(); + + //Don't forget to add the actor to the scene. + scene.addActor(*vehActor); + + //Set up the mapping between wheel and actor shape. + tank->mWheelsSimData.setWheelShapeMapping(0,0); + tank->mWheelsSimData.setWheelShapeMapping(1,1); + tank->mWheelsSimData.setWheelShapeMapping(2,2); + tank->mWheelsSimData.setWheelShapeMapping(3,3); + tank->mWheelsSimData.setWheelShapeMapping(4,4); + tank->mWheelsSimData.setWheelShapeMapping(5,5); + + //Set up the scene query filter data for each suspension line. + PxFilterData vehQryFilterData; + SampleVehicleSetupVehicleShapeQueryFilterData(&vehQryFilterData); + tank->mWheelsSimData.setSceneQueryFilterData(0, vehQryFilterData); + tank->mWheelsSimData.setSceneQueryFilterData(1, vehQryFilterData); + tank->mWheelsSimData.setSceneQueryFilterData(2, vehQryFilterData); + tank->mWheelsSimData.setSceneQueryFilterData(3, vehQryFilterData); + tank->mWheelsSimData.setSceneQueryFilterData(4, vehQryFilterData); + tank->mWheelsSimData.setSceneQueryFilterData(5, vehQryFilterData); + + //Set the transform and the instantiated car and set it be to be at rest. + resetNWCar(startTransform,tank); + //Set the autogear mode of the instantiate car. + tank->mDriveDynData.setUseAutoGears(useAutoGearFlag); + //set the drive model + tank->setDriveModel(tankDriveModel); + + //Increment the number of vehicles + mVehicles[mNumVehicles]=tank; + mVehicleWheelQueryResults[mNumVehicles].nbWheelQueryResults=6; + mVehicleWheelQueryResults[mNumVehicles].wheelQueryResults=mWheelQueryResults->addVehicle(6); + mNumVehicles++; +} + +void SampleVehicle_VehicleManager::switchTo3WDeltaMode(const PxU32 vehicleId) +{ + //Get the vehicle that will be in 3-wheeled mode. + PX_ASSERT(mVehicles[vehicleId]->getVehicleType()==PxVehicleTypes::eDRIVE4W); + PxVehicleDrive4W* veh=(PxVehicleDrive4W*)mVehicles[vehicleId]; + if(mIsIn3WMode) + { + switchTo4WMode(vehicleId); + } + else + { + veh->mWheelsSimData=*mWheelsSimData4W; + veh->mDriveSimData=mDriveSimData4W; + } + PxVehicle4WEnable3WDeltaMode(veh->mWheelsSimData, veh->mWheelsDynData, veh->mDriveSimData); + mIsIn3WMode=true; +} + +void SampleVehicle_VehicleManager::switchTo3WTadpoleMode(const PxU32 vehicleId) +{ + //Get the vehicle that will be in 3-wheeled mode. + PX_ASSERT(mVehicles[vehicleId]->getVehicleType()==PxVehicleTypes::eDRIVE4W); + PxVehicleDrive4W* veh=(PxVehicleDrive4W*)mVehicles[vehicleId]; + if(mIsIn3WMode) + { + switchTo4WMode(vehicleId); + } + else + { + veh->mWheelsSimData=*mWheelsSimData4W; + veh->mDriveSimData=mDriveSimData4W; + } + PxVehicle4WEnable3WTadpoleMode(veh->mWheelsSimData, veh->mWheelsDynData, veh->mDriveSimData); + mIsIn3WMode=true; +} + +void SampleVehicle_VehicleManager::switchTo4WMode(const PxU32 vehicleId) +{ + //Get the vehicle that will be in 3-wheeled mode. + PX_ASSERT(mVehicles[vehicleId]->getVehicleType()==PxVehicleTypes::eDRIVE4W); + PxVehicleDrive4W* veh=(PxVehicleDrive4W*)mVehicles[vehicleId]; + + *mWheelsSimData4W=veh->mWheelsSimData; + mDriveSimData4W=veh->mDriveSimData; + mIsIn3WMode=false; +} + + + -- cgit v1.2.3