diff options
| author | git perforce import user <a@b> | 2016-10-25 12:29:14 -0600 |
|---|---|---|
| committer | Sheikh Dawood Abdul Ajees <Sheikh Dawood Abdul Ajees> | 2016-10-25 18:56:37 -0500 |
| commit | 3dfe2108cfab31ba3ee5527e217d0d8e99a51162 (patch) | |
| tree | fa6485c169e50d7415a651bf838f5bcd0fd3bfbd /PhysX_3.4/Samples/SampleVehicle/SampleVehicle_VehicleManager.cpp | |
| download | physx-3.4-3dfe2108cfab31ba3ee5527e217d0d8e99a51162.tar.xz physx-3.4-3dfe2108cfab31ba3ee5527e217d0d8e99a51162.zip | |
Initial commit:
PhysX 3.4.0 Update @ 21294896
APEX 1.4.0 Update @ 21275617
[CL 21300167]
Diffstat (limited to 'PhysX_3.4/Samples/SampleVehicle/SampleVehicle_VehicleManager.cpp')
| -rw-r--r-- | PhysX_3.4/Samples/SampleVehicle/SampleVehicle_VehicleManager.cpp | 1171 |
1 files changed, 1171 insertions, 0 deletions
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;i<MAX_NUM_4W_VEHICLES+MAX_NUM_6W_VEHICLES;i++) + { + mVehicles[i]=NULL; + } + + //Allocate simulation data so we can switch from 3-wheeled to 4-wheeled cars by switching simulation data. + mWheelsSimData4W = PxVehicleWheelsSimData::allocate(4); + + //Scene query data for to allow raycasts for all suspensions of all vehicles. + mSqData = SampleVehicleSceneQueryData::allocate(MAX_NUM_4W_VEHICLES*4 + MAX_NUM_6W_VEHICLES*6); + + //Data to store reports for each wheel. + mWheelQueryResults = SampleVehicleWheelQueryResults::allocate(MAX_NUM_4W_VEHICLES*4 + MAX_NUM_6W_VEHICLES*6); + + //Set up the friction values arising from combinations of tire type and surface type. + mSurfaceTirePairs=PxVehicleDrivableSurfaceToTireFrictionPairs::allocate(MAX_NUM_TIRE_TYPES,MAX_NUM_SURFACE_TYPES); + mSurfaceTirePairs->setup(MAX_NUM_TIRE_TYPES,MAX_NUM_SURFACE_TYPES,drivableSurfaceMaterials,drivableSurfaceTypes); + for(PxU32 i=0;i<MAX_NUM_SURFACE_TYPES;i++) + { + for(PxU32 j=0;j<MAX_NUM_TIRE_TYPES;j++) + { + mSurfaceTirePairs->setTypePairFriction(i,j,TireFrictionMultipliers::getValue(i, j)); + } + } +} + +void SampleVehicle_VehicleManager::shutdown() +{ + //Remove the N-wheeled vehicles. + for(PxU32 i=0;i<mNumVehicles;i++) + { + switch(mVehicles[i]->getVehicleType()) + { + 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(vehicleId<mNumVehicles); + resetNWCar(transform,mVehicles[vehicleId]); +} + +void SampleVehicle_VehicleManager::suspensionRaycasts(PxScene* scene) +{ + //Create a scene query if we haven't already done so. + if(NULL==mSqWheelRaycastBatchQuery) + { + mSqWheelRaycastBatchQuery=mSqData->setUpBatchedSceneQuery(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;i<mNumVehicles;i++) + { + if(focusVehicle!=mVehicles[i]) + { + vehicles[numVehicles]=mVehicles[i]; + vehicleWheelQueryResults[numVehicles]=mVehicleWheelQueryResults[i]; + numVehicles++; + } + else + { + focusVehicleWheelQueryResults[0]=mVehicleWheelQueryResults[i]; + } + } + PxVehicleUpdates(timestep,gravity,*mSurfaceTirePairs,numVehicles,vehicles,vehicleWheelQueryResults); + + + //Update the vehicle for which we want to record debug data. + PxVehicleUpdateSingleVehicleAndStoreTelemetryData(timestep,gravity,*mSurfaceTirePairs,focusVehicle,focusVehicleWheelQueryResults,*telemetryData); +} + +#else + +void SampleVehicle_VehicleManager::update(const PxF32 timestep, const PxVec3& gravity) +{ + PxVehicleUpdates(timestep,gravity,*mSurfaceTirePairs,mNumVehicles,mVehicles,mVehicleWheelQueryResults); +} + +#endif //PX_DEBUG_VEHICLE_ON + +void SampleVehicle_VehicleManager::resetNWCar(const PxTransform& startTransform, PxVehicleWheels* vehWheels) +{ + switch(vehWheels->getVehicleType()) + { + 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;i<numWheelGeometries;i++) + { + PxShape* wheelShape=PxRigidActorExt::createExclusiveShape(*vehActor, *wheelGeometries[i],*wheelMaterial); + wheelShape->setQueryFilterData(vehQryFilterData); + wheelShape->setSimulationFilterData(wheelCollFilterData); + wheelShape->setLocalPose(wheelLocalPoses[i]); + } + + //Add the chassis shapes to the actor. + for(PxU32 i=0;i<numChassisGeometries;i++) + { + PxShape* chassisShape=PxRigidActorExt::createExclusiveShape(*vehActor, *chassisGeometries[i],*chassisMaterial); + chassisShape->setQueryFilterData(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;j<numWheelVerts;j++) + { + wheelMin.x=PxMin(wheelMin.x,wheelVerts[j].x); + wheelMin.y=PxMin(wheelMin.y,wheelVerts[j].y); + wheelMin.z=PxMin(wheelMin.z,wheelVerts[j].z); + wheelMax.x=PxMax(wheelMax.x,wheelVerts[j].x); + wheelMax.y=PxMax(wheelMax.y,wheelVerts[j].y); + wheelMax.z=PxMax(wheelMax.z,wheelVerts[j].z); + } + wheelWidths[i]=wheelMax.x-wheelMin.x; + wheelRadii[i]=PxMax(wheelMax.y,wheelMax.z)*0.975f; + } +} + +PxVec3 computeChassisAABBDimensions(const PxConvexMesh* chassisConvexMesh) +{ + const PxU32 numChassisVerts=chassisConvexMesh->getNbVertices(); + 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;i<numChassisVerts;i++) + { + chassisMin.x=PxMin(chassisMin.x,chassisVerts[i].x); + chassisMin.y=PxMin(chassisMin.y,chassisVerts[i].y); + chassisMin.z=PxMin(chassisMin.z,chassisVerts[i].z); + chassisMax.x=PxMax(chassisMax.x,chassisVerts[i].x); + chassisMax.y=PxMax(chassisMax.y,chassisVerts[i].y); + chassisMax.z=PxMax(chassisMax.z,chassisVerts[i].z); + } + const PxVec3 chassisDims=chassisMax-chassisMin; + return chassisDims; +} + +void createVehicle4WSimulationData +(const PxF32 chassisMass, PxConvexMesh* chassisConvexMesh, + const PxF32 wheelMass, PxConvexMesh** wheelConvexMeshes, const PxVec3* wheelCentreOffsets, + PxVehicleWheelsSimData& wheelsData, PxVehicleDriveSimData4W& driveData, PxVehicleChassisData& chassisData) +{ + //Extract the chassis AABB dimensions from the chassis convex mesh. + const PxVec3 chassisDims=computeChassisAABBDimensions(chassisConvexMesh); + + //The origin is at the center of the chassis mesh. + //Set the center of mass to be below this point and a little towards the front. + const PxVec3 chassisCMOffset=PxVec3(0.0f,-chassisDims.y*0.5f+0.65f,0.25f); + + //Now compute the chassis mass and moment of inertia. + //Use the moment of inertia of a cuboid as an approximate value for the chassis moi. + PxVec3 chassisMOI + ((chassisDims.y*chassisDims.y + chassisDims.z*chassisDims.z)*chassisMass/12.0f, + (chassisDims.x*chassisDims.x + chassisDims.z*chassisDims.z)*chassisMass/12.0f, + (chassisDims.x*chassisDims.x + chassisDims.y*chassisDims.y)*chassisMass/12.0f); + //A bit of tweaking here. The car will have more responsive turning if we reduce the + //y-component of the chassis moment of inertia. + chassisMOI.y*=0.8f; + + //Let's set up the chassis data structure now. + chassisData.mMass=chassisMass; + chassisData.mMOI=chassisMOI; + chassisData.mCMOffset=chassisCMOffset; + + //Compute the sprung masses of each suspension spring using a helper function. + PxF32 suspSprungMasses[4]; + PxVehicleComputeSprungMasses(4,wheelCentreOffsets,chassisCMOffset,chassisMass,1,suspSprungMasses); + + //Extract the wheel radius and width from the wheel convex meshes. + PxF32 wheelWidths[4]; + PxF32 wheelRadii[4]; + computeWheelWidthsAndRadii(wheelConvexMeshes,wheelWidths,wheelRadii); + + //Now compute the wheel masses and inertias components around the axle's axis. + //http://en.wikipedia.org/wiki/List_of_moments_of_inertia + PxF32 wheelMOIs[4]; + for(PxU32 i=0;i<4;i++) + { + wheelMOIs[i]=0.5f*wheelMass*wheelRadii[i]*wheelRadii[i]; + } + //Let's set up the wheel data structures now with radius, mass, and moi. + PxVehicleWheelData wheels[4]; + for(PxU32 i=0;i<4;i++) + { + wheels[i].mRadius=wheelRadii[i]; + wheels[i].mMass=wheelMass; + wheels[i].mMOI=wheelMOIs[i]; + wheels[i].mWidth=wheelWidths[i]; + } + //Disable the handbrake from the front wheels and enable for the rear wheels + wheels[PxVehicleDrive4WWheelOrder::eFRONT_LEFT].mMaxHandBrakeTorque=0.0f; + wheels[PxVehicleDrive4WWheelOrder::eFRONT_RIGHT].mMaxHandBrakeTorque=0.0f; + wheels[PxVehicleDrive4WWheelOrder::eREAR_LEFT].mMaxHandBrakeTorque=4000.0f; + wheels[PxVehicleDrive4WWheelOrder::eREAR_RIGHT].mMaxHandBrakeTorque=4000.0f; + //Enable steering for the front wheels and disable for the front wheels. + wheels[PxVehicleDrive4WWheelOrder::eFRONT_LEFT].mMaxSteer=PxPi*0.3333f; + wheels[PxVehicleDrive4WWheelOrder::eFRONT_RIGHT].mMaxSteer=PxPi*0.3333f; + wheels[PxVehicleDrive4WWheelOrder::eREAR_LEFT].mMaxSteer=0.0f; + wheels[PxVehicleDrive4WWheelOrder::eREAR_RIGHT].mMaxSteer=0.0f; + + //Let's set up the tire data structures now. + //Put slicks on the front tires and wets on the rear tires. + PxVehicleTireData tires[4]; + tires[PxVehicleDrive4WWheelOrder::eFRONT_LEFT].mType=TIRE_TYPE_SLICKS; + tires[PxVehicleDrive4WWheelOrder::eFRONT_RIGHT].mType=TIRE_TYPE_SLICKS; + tires[PxVehicleDrive4WWheelOrder::eREAR_LEFT].mType=TIRE_TYPE_WETS; + tires[PxVehicleDrive4WWheelOrder::eREAR_RIGHT].mType=TIRE_TYPE_WETS; + + //Let's set up the suspension data structures now. + PxVehicleSuspensionData susps[4]; + for(PxU32 i=0;i<4;i++) + { + susps[i].mMaxCompression=0.3f; + susps[i].mMaxDroop=0.1f; + susps[i].mSpringStrength=35000.0f; + susps[i].mSpringDamperRate=4500.0f; + } + susps[PxVehicleDrive4WWheelOrder::eFRONT_LEFT].mSprungMass=suspSprungMasses[PxVehicleDrive4WWheelOrder::eFRONT_LEFT]; + susps[PxVehicleDrive4WWheelOrder::eFRONT_RIGHT].mSprungMass=suspSprungMasses[PxVehicleDrive4WWheelOrder::eFRONT_RIGHT]; + susps[PxVehicleDrive4WWheelOrder::eREAR_LEFT].mSprungMass=suspSprungMasses[PxVehicleDrive4WWheelOrder::eREAR_LEFT]; + susps[PxVehicleDrive4WWheelOrder::eREAR_RIGHT].mSprungMass=suspSprungMasses[PxVehicleDrive4WWheelOrder::eREAR_RIGHT]; + + //Set up the camber. + //Remember that the left and right wheels need opposite camber so that the car preserves symmetry about the forward direction. + //Set the camber to 0.0f when the spring is neither compressed or elongated. + const PxF32 camberAngleAtRest=0.0; + susps[PxVehicleDrive4WWheelOrder::eFRONT_LEFT].mCamberAtRest=camberAngleAtRest; + susps[PxVehicleDrive4WWheelOrder::eFRONT_RIGHT].mCamberAtRest=-camberAngleAtRest; + susps[PxVehicleDrive4WWheelOrder::eREAR_LEFT].mCamberAtRest=camberAngleAtRest; + susps[PxVehicleDrive4WWheelOrder::eREAR_RIGHT].mCamberAtRest=-camberAngleAtRest; + //Set the wheels to camber inwards at maximum droop (the left and right wheels almost form a V shape) + const PxF32 camberAngleAtMaxDroop=0.001f; + susps[PxVehicleDrive4WWheelOrder::eFRONT_LEFT].mCamberAtMaxDroop=camberAngleAtMaxDroop; + susps[PxVehicleDrive4WWheelOrder::eFRONT_RIGHT].mCamberAtMaxDroop=-camberAngleAtMaxDroop; + susps[PxVehicleDrive4WWheelOrder::eREAR_LEFT].mCamberAtMaxDroop=camberAngleAtMaxDroop; + susps[PxVehicleDrive4WWheelOrder::eREAR_RIGHT].mCamberAtMaxDroop=-camberAngleAtMaxDroop; + //Set the wheels to camber outwards at maximum compression (the left and right wheels almost form a A shape). + const PxF32 camberAngleAtMaxCompression=-0.001f; + susps[PxVehicleDrive4WWheelOrder::eFRONT_LEFT].mCamberAtMaxCompression=camberAngleAtMaxCompression; + susps[PxVehicleDrive4WWheelOrder::eFRONT_RIGHT].mCamberAtMaxCompression=-camberAngleAtMaxCompression; + susps[PxVehicleDrive4WWheelOrder::eREAR_LEFT].mCamberAtMaxCompression=camberAngleAtMaxCompression; + susps[PxVehicleDrive4WWheelOrder::eREAR_RIGHT].mCamberAtMaxCompression=-camberAngleAtMaxCompression; + + //We need to set up geometry data for the suspension, wheels, and tires. + //We already know the wheel centers described as offsets from the actor center and the center of mass offset from actor center. + //From here we can approximate application points for the tire and suspension forces. + //Lets assume that the suspension travel directions are absolutely vertical. + //Also assume that we apply the tire and suspension forces 30cm below the center of mass. + PxVec3 suspTravelDirections[4]={PxVec3(0,-1,0),PxVec3(0,-1,0),PxVec3(0,-1,0),PxVec3(0,-1,0)}; + PxVec3 wheelCentreCMOffsets[4]; + PxVec3 suspForceAppCMOffsets[4]; + PxVec3 tireForceAppCMOffsets[4]; + for(PxU32 i=0;i<4;i++) + { + wheelCentreCMOffsets[i]=wheelCentreOffsets[i]-chassisCMOffset; + suspForceAppCMOffsets[i]=PxVec3(wheelCentreCMOffsets[i].x,-0.3f,wheelCentreCMOffsets[i].z); + tireForceAppCMOffsets[i]=PxVec3(wheelCentreCMOffsets[i].x,-0.3f,wheelCentreCMOffsets[i].z); + } + + //Now add the wheel, tire and suspension data. + for(PxU32 i=0;i<4;i++) + { + wheelsData.setWheelData(i,wheels[i]); + wheelsData.setTireData(i,tires[i]); + wheelsData.setSuspensionData(i,susps[i]); + wheelsData.setSuspTravelDirection(i,suspTravelDirections[i]); + wheelsData.setWheelCentreOffset(i,wheelCentreCMOffsets[i]); + wheelsData.setSuspForceAppPointOffset(i,suspForceAppCMOffsets[i]); + wheelsData.setTireForceAppPointOffset(i,tireForceAppCMOffsets[i]); + } + + //Set the car to perform 3 sub-steps when it moves with a forwards speed of less than 5.0 + //and with a single step when it moves at speed greater than or equal to 5.0. + wheelsData.setSubStepCount(5.0f, 3, 1); + + + //Now set up the differential, engine, gears, clutch, and ackermann steering. + + //Diff + PxVehicleDifferential4WData diff; + diff.mType=PxVehicleDifferential4WData::eDIFF_TYPE_LS_4WD; + driveData.setDiffData(diff); + + //Engine + PxVehicleEngineData engine; + engine.mPeakTorque=500.0f; + engine.mMaxOmega=600.0f;//approx 6000 rpm + driveData.setEngineData(engine); + + //Gears + PxVehicleGearsData gears; + gears.mSwitchTime=0.5f; + driveData.setGearsData(gears); + + //Clutch + PxVehicleClutchData clutch; + clutch.mStrength=10.0f; + driveData.setClutchData(clutch); + + //Ackermann steer accuracy + PxVehicleAckermannGeometryData ackermann; + ackermann.mAccuracy=1.0f; + ackermann.mAxleSeparation=wheelCentreOffsets[PxVehicleDrive4WWheelOrder::eFRONT_LEFT].z-wheelCentreOffsets[PxVehicleDrive4WWheelOrder::eREAR_LEFT].z; + ackermann.mFrontWidth=wheelCentreOffsets[PxVehicleDrive4WWheelOrder::eFRONT_RIGHT].x-wheelCentreOffsets[PxVehicleDrive4WWheelOrder::eFRONT_LEFT].x; + ackermann.mRearWidth=wheelCentreOffsets[PxVehicleDrive4WWheelOrder::eREAR_RIGHT].x-wheelCentreOffsets[PxVehicleDrive4WWheelOrder::eREAR_LEFT].x; + driveData.setAckermannGeometryData(ackermann); +} + +void SampleVehicle_VehicleManager::create4WVehicle +(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(mNumVehicles<MAX_NUM_4W_VEHICLES); + + PxVehicleWheelsSimData* wheelsSimData=PxVehicleWheelsSimData::allocate(4); + PxVehicleDriveSimData4W driveSimData; + PxVehicleChassisData chassisData; + createVehicle4WSimulationData + (chassisMass,chassisConvexMesh, + 20.0f,wheelConvexMeshes4,wheelCentreOffsets4, + *wheelsSimData,driveSimData,chassisData); + + //Instantiate and finalize the vehicle using physx. + PxRigidDynamic* vehActor=createVehicleActor4W(chassisData,wheelConvexMeshes4,chassisConvexMesh,scene,physics,material); + + //Create a car. + PxVehicleDrive4W* car = PxVehicleDrive4W::allocate(4); + car->setup(&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(mNumVehicles<MAX_NUM_4W_VEHICLES+MAX_NUM_6W_VEHICLES); + + //We're going to create an 4-wheeled vehicle then quickly copy components to make an 6-wheeled vehicle. + PxVehicleWheelsSimData* wheelsSimData=PxVehicleWheelsSimData::allocate(6); + PxVehicleDriveSimDataNW driveSimData; + PxVehicleChassisData chassisData; + createVehicle6WSimulationData(chassisMass,wheelCentreOffsets4,chassisConvexMesh,wheelConvexMeshes4,*wheelsSimData,driveSimData,chassisData); + + //Instantiate and finalize the vehicle using physx. + PxRigidDynamic* vehActor=createVehicleActor6W(chassisData,wheelConvexMeshes4,chassisConvexMesh,scene,physics,material); + + //Create a car. + PxVehicleDriveNW* car = PxVehicleDriveNW::allocate(6); + car->setup(&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; +} + + + |