This commit is contained in:
2025-11-28 23:13:44 +05:30
commit a3a8e79709
7360 changed files with 1156074 additions and 0 deletions

View File

@ -0,0 +1,321 @@
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2021 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 "SnippetVehicleCreate.h"
#include "SnippetVehicleTireFriction.h"
#include "SnippetVehicleSceneQuery.h"
namespace snippetvehicle
{
using namespace physx;
namespace fourwheel
{
void computeWheelCenterActorOffsets4W(const PxF32 wheelFrontZ, const PxF32 wheelRearZ, const PxVec3& chassisDims, const PxF32 wheelWidth, const PxF32 wheelRadius, const PxU32 numWheels, PxVec3* wheelCentreOffsets)
{
//chassisDims.z is the distance from the rear of the chassis to the front of the chassis.
//The front has z = 0.5*chassisDims.z and the rear has z = -0.5*chassisDims.z.
//Compute a position for the front wheel and the rear wheel along the z-axis.
//Compute the separation between each wheel along the z-axis.
const PxF32 numLeftWheels = numWheels/2.0f;
const PxF32 deltaZ = (wheelFrontZ - wheelRearZ)/(numLeftWheels-1.0f);
//Set the outside of the left and right wheels to be flush with the chassis.
//Set the top of the wheel to be just touching the underside of the chassis.
//Begin by setting the rear-left/rear-right/front-left,front-right wheels.
wheelCentreOffsets[PxVehicleDrive4WWheelOrder::eREAR_LEFT] = PxVec3((-chassisDims.x + wheelWidth)*0.5f, -(chassisDims.y/2 + wheelRadius), wheelRearZ + 0*deltaZ*0.5f);
wheelCentreOffsets[PxVehicleDrive4WWheelOrder::eREAR_RIGHT] = PxVec3((+chassisDims.x - wheelWidth)*0.5f, -(chassisDims.y/2 + wheelRadius), wheelRearZ + 0*deltaZ*0.5f);
wheelCentreOffsets[PxVehicleDrive4WWheelOrder::eFRONT_LEFT] = PxVec3((-chassisDims.x + wheelWidth)*0.5f, -(chassisDims.y/2 + wheelRadius), wheelRearZ + (numLeftWheels-1)*deltaZ);
wheelCentreOffsets[PxVehicleDrive4WWheelOrder::eFRONT_RIGHT] = PxVec3((+chassisDims.x - wheelWidth)*0.5f, -(chassisDims.y/2 + wheelRadius), wheelRearZ + (numLeftWheels-1)*deltaZ);
//Set the remaining wheels.
for(PxU32 i = 2, wheelCount = 4; i < numWheels-2; i+=2, wheelCount+=2)
{
wheelCentreOffsets[wheelCount + 0] = PxVec3((-chassisDims.x + wheelWidth)*0.5f, -(chassisDims.y/2 + wheelRadius), wheelRearZ + i*deltaZ*0.5f);
wheelCentreOffsets[wheelCount + 1] = PxVec3((+chassisDims.x - wheelWidth)*0.5f, -(chassisDims.y/2 + wheelRadius), wheelRearZ + i*deltaZ*0.5f);
}
}
void 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.3333f;
wheels[PxVehicleDrive4WWheelOrder::eFRONT_RIGHT].mMaxSteer=PxPi*0.3333f;
}
//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, PxI32(i));
}
//Add a front and rear anti-roll bar
PxVehicleAntiRollBarData barFront;
barFront.mWheel0 = PxVehicleDrive4WWheelOrder::eFRONT_LEFT;
barFront.mWheel1 = PxVehicleDrive4WWheelOrder::eFRONT_RIGHT;
barFront.mStiffness = 10000.0f;
wheelsSimData->addAntiRollBarData(barFront);
PxVehicleAntiRollBarData barRear;
barRear.mWheel0 = PxVehicleDrive4WWheelOrder::eREAR_LEFT;
barRear.mWheel1 = PxVehicleDrive4WWheelOrder::eREAR_RIGHT;
barRear.mStiffness = 10000.0f;
wheelsSimData->addAntiRollBarData(barRear);
}
} //namespace fourwheel
PxVehicleDrive4W* createVehicle4W(const VehicleDesc& vehicle4WDesc, PxPhysics* physics, PxCooking* cooking)
{
const PxVec3 chassisDims = vehicle4WDesc.chassisDims;
const PxF32 wheelWidth = vehicle4WDesc.wheelWidth;
const PxF32 wheelRadius = vehicle4WDesc.wheelRadius;
const PxU32 numWheels = vehicle4WDesc.numWheels;
const PxFilterData& chassisSimFilterData = vehicle4WDesc.chassisSimFilterData;
const PxFilterData& wheelSimFilterData = vehicle4WDesc.wheelSimFilterData;
//Construct a physx actor with shapes for the chassis and wheels.
//Set the rigid body mass, moment of inertia, and center of mass offset.
PxRigidDynamic* veh4WActor = NULL;
{
//Construct a convex mesh for a cylindrical wheel.
PxConvexMesh* wheelMesh = createWheelMesh(wheelWidth, wheelRadius, *physics, *cooking);
//Assume all wheels are identical for simplicity.
PxConvexMesh* wheelConvexMeshes[PX_MAX_NB_WHEELS];
PxMaterial* wheelMaterials[PX_MAX_NB_WHEELS];
//Set the meshes and materials for the driven wheels.
for(PxU32 i = PxVehicleDrive4WWheelOrder::eFRONT_LEFT; i <= PxVehicleDrive4WWheelOrder::eREAR_RIGHT; i++)
{
wheelConvexMeshes[i] = wheelMesh;
wheelMaterials[i] = vehicle4WDesc.wheelMaterial;
}
//Set the meshes and materials for the non-driven wheels
for(PxU32 i = PxVehicleDrive4WWheelOrder::eREAR_RIGHT + 1; i < numWheels; i++)
{
wheelConvexMeshes[i] = wheelMesh;
wheelMaterials[i] = vehicle4WDesc.wheelMaterial;
}
//Chassis just has a single convex shape for simplicity.
PxConvexMesh* chassisConvexMesh = createChassisMesh(chassisDims, *physics, *cooking);
PxConvexMesh* chassisConvexMeshes[1] = {chassisConvexMesh};
PxMaterial* chassisMaterials[1] = {vehicle4WDesc.chassisMaterial};
//Rigid body data.
PxVehicleChassisData rigidBodyData;
rigidBodyData.mMOI = vehicle4WDesc.chassisMOI;
rigidBodyData.mMass = vehicle4WDesc.chassisMass;
rigidBodyData.mCMOffset = vehicle4WDesc.chassisCMOffset;
veh4WActor = createVehicleActor
(rigidBodyData,
wheelMaterials, wheelConvexMeshes, numWheels, wheelSimFilterData,
chassisMaterials, chassisConvexMeshes, 1, chassisSimFilterData,
*physics);
}
//Set up the sim data for the wheels.
PxVehicleWheelsSimData* wheelsSimData = PxVehicleWheelsSimData::allocate(numWheels);
{
//Compute the wheel center offsets from the origin.
PxVec3 wheelCenterActorOffsets[PX_MAX_NB_WHEELS];
const PxF32 frontZ = chassisDims.z*0.3f;
const PxF32 rearZ = -chassisDims.z*0.3f;
fourwheel::computeWheelCenterActorOffsets4W(frontZ, rearZ, chassisDims, wheelWidth, wheelRadius, numWheels, wheelCenterActorOffsets);
//Set up the simulation data for all wheels.
fourwheel::setupWheelsSimulationData
(vehicle4WDesc.wheelMass, vehicle4WDesc.wheelMOI, wheelRadius, wheelWidth,
numWheels, wheelCenterActorOffsets,
vehicle4WDesc.chassisCMOffset, vehicle4WDesc.chassisMass,
wheelsSimData);
}
//Set up the sim data for the vehicle drive model.
PxVehicleDriveSimData4W driveSimData;
{
//Diff
PxVehicleDifferential4WData diff;
diff.mType=PxVehicleDifferential4WData::eDIFF_TYPE_LS_4WD;
driveSimData.setDiffData(diff);
//Engine
PxVehicleEngineData engine;
engine.mPeakTorque=500.0f;
engine.mMaxOmega=600.0f;//approx 6000 rpm
driveSimData.setEngineData(engine);
//Gears
PxVehicleGearsData gears;
gears.mSwitchTime=0.5f;
driveSimData.setGearsData(gears);
//Clutch
PxVehicleClutchData clutch;
clutch.mStrength=10.0f;
driveSimData.setClutchData(clutch);
//Ackermann steer accuracy
PxVehicleAckermannGeometryData ackermann;
ackermann.mAccuracy=1.0f;
ackermann.mAxleSeparation=
wheelsSimData->getWheelCentreOffset(PxVehicleDrive4WWheelOrder::eFRONT_LEFT).z-
wheelsSimData->getWheelCentreOffset(PxVehicleDrive4WWheelOrder::eREAR_LEFT).z;
ackermann.mFrontWidth=
wheelsSimData->getWheelCentreOffset(PxVehicleDrive4WWheelOrder::eFRONT_RIGHT).x-
wheelsSimData->getWheelCentreOffset(PxVehicleDrive4WWheelOrder::eFRONT_LEFT).x;
ackermann.mRearWidth=
wheelsSimData->getWheelCentreOffset(PxVehicleDrive4WWheelOrder::eREAR_RIGHT).x -
wheelsSimData->getWheelCentreOffset(PxVehicleDrive4WWheelOrder::eREAR_LEFT).x;
driveSimData.setAckermannGeometryData(ackermann);
}
//Create a vehicle from the wheels and drive sim data.
PxVehicleDrive4W* vehDrive4W = PxVehicleDrive4W::allocate(numWheels);
vehDrive4W->setup(physics, veh4WActor, *wheelsSimData, driveSimData, numWheels - 4);
//Configure the userdata
configureUserData(vehDrive4W, vehicle4WDesc.actorUserData, vehicle4WDesc.shapeUserDatas);
//Free the sim data because we don't need that any more.
wheelsSimData->free();
return vehDrive4W;
}
} //namespace snippetvehicle

View File

@ -0,0 +1,122 @@
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
#ifndef SNIPPET_VEHICLE_CONCURRENCY_H
#define SNIPPET_VEHICLE_CONCURRENCY_H
#include "PxPhysicsAPI.h"
#include <new>
namespace snippetvehicle
{
using namespace physx;
//Data structure for quick setup of wheel query data structures.
class VehicleConcurrency
{
public:
VehicleConcurrency()
: mMaxNumVehicles(0),
mMaxNumWheelsPerVehicle(0),
mVehicleConcurrentUpdates(NULL)
{
}
~VehicleConcurrency()
{
}
static VehicleConcurrency* allocate(const PxU32 maxNumVehicles, const PxU32 maxNumWheelsPerVehicle, PxAllocatorCallback& allocator)
{
const PxU32 byteSize =
sizeof(VehicleConcurrency) +
sizeof(PxVehicleConcurrentUpdateData)*maxNumVehicles +
sizeof(PxVehicleWheelConcurrentUpdateData)*maxNumWheelsPerVehicle*maxNumVehicles;
PxU8* buffer = static_cast<PxU8*>(allocator.allocate(byteSize, NULL, NULL, 0));
VehicleConcurrency* vc = reinterpret_cast<VehicleConcurrency*>(buffer);
new(vc) VehicleConcurrency();
buffer += sizeof(VehicleConcurrency);
vc->mMaxNumVehicles = maxNumVehicles;
vc->mMaxNumWheelsPerVehicle = maxNumWheelsPerVehicle;
vc->mVehicleConcurrentUpdates = reinterpret_cast<PxVehicleConcurrentUpdateData*>(buffer);
buffer += sizeof(PxVehicleConcurrentUpdateData)*maxNumVehicles;
for(PxU32 i=0;i<maxNumVehicles;i++)
{
new(vc->mVehicleConcurrentUpdates + i) PxVehicleConcurrentUpdateData();
vc->mVehicleConcurrentUpdates[i].nbConcurrentWheelUpdates = maxNumWheelsPerVehicle;
vc->mVehicleConcurrentUpdates[i].concurrentWheelUpdates = reinterpret_cast<PxVehicleWheelConcurrentUpdateData*>(buffer);
buffer += sizeof(PxVehicleWheelConcurrentUpdateData)*maxNumWheelsPerVehicle;
for(PxU32 j = 0; j < maxNumWheelsPerVehicle; j++)
{
new(vc->mVehicleConcurrentUpdates[i].concurrentWheelUpdates + j) PxVehicleWheelConcurrentUpdateData();
}
}
return vc;
}
//Free allocated buffer for scene queries of suspension raycasts.
void free(PxAllocatorCallback& allocator)
{
allocator.deallocate(this);
}
//Return the PxVehicleConcurrentUpdate for a vehicle specified by an index.
PxVehicleConcurrentUpdateData* getVehicleConcurrentUpdate(const PxU32 id)
{
return (mVehicleConcurrentUpdates + id);
}
//Return the entire array of PxVehicleConcurrentUpdates
PxVehicleConcurrentUpdateData* getVehicleConcurrentUpdateBuffer()
{
return mVehicleConcurrentUpdates;
}
private:
PxU32 mMaxNumVehicles;
PxU32 mMaxNumWheelsPerVehicle;
PxVehicleConcurrentUpdateData* mVehicleConcurrentUpdates;
};
} // namespace snippetvehicle
#endif //SNIPPET_VEHICLE_CONCURRENCY_H

View File

@ -0,0 +1,339 @@
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2021 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 <new>
#include "SnippetVehicleCreate.h"
#include "SnippetVehicleSceneQuery.h"
#include "SnippetVehicleFilterShader.h"
#include "SnippetVehicleTireFriction.h"
#include "PxPhysicsAPI.h"
namespace snippetvehicle
{
using namespace physx;
PxRigidStatic* createDrivablePlane(const PxFilterData& simFilterData, PxMaterial* material, PxPhysics* physics)
{
//Add a plane to the scene.
PxRigidStatic* groundPlane = PxCreatePlane(*physics, PxPlane(0,1,0,0), *material);
//Get the plane shape so we can set query and simulation filter data.
PxShape* shapes[1];
groundPlane->getShapes(shapes, 1);
//Set the query filter data of the ground plane so that the vehicle raycasts can hit the ground.
PxFilterData qryFilterData;
setupDrivableSurface(qryFilterData);
shapes[0]->setQueryFilterData(qryFilterData);
//Set the simulation filter data of the ground plane so that it collides with the chassis of a vehicle but not the wheels.
shapes[0]->setSimulationFilterData(simFilterData);
return groundPlane;
}
static PxConvexMesh* createConvexMesh(const PxVec3* verts, const PxU32 numVerts, PxPhysics& physics, PxCooking& cooking)
{
// Create descriptor for convex mesh
PxConvexMeshDesc convexDesc;
convexDesc.points.count = numVerts;
convexDesc.points.stride = sizeof(PxVec3);
convexDesc.points.data = verts;
convexDesc.flags = PxConvexFlag::eCOMPUTE_CONVEX;
PxConvexMesh* convexMesh = NULL;
PxDefaultMemoryOutputStream buf;
if(cooking.cookConvexMesh(convexDesc, buf))
{
PxDefaultMemoryInputData id(buf.getData(), buf.getSize());
convexMesh = physics.createConvexMesh(id);
}
return convexMesh;
}
PxConvexMesh* createChassisMesh(const PxVec3 dims, PxPhysics& physics, PxCooking& cooking)
{
const PxF32 x = dims.x*0.5f;
const PxF32 y = dims.y*0.5f;
const PxF32 z = dims.z*0.5f;
PxVec3 verts[8] =
{
PxVec3(x,y,-z),
PxVec3(x,y,z),
PxVec3(x,-y,z),
PxVec3(x,-y,-z),
PxVec3(-x,y,-z),
PxVec3(-x,y,z),
PxVec3(-x,-y,z),
PxVec3(-x,-y,-z)
};
return createConvexMesh(verts,8,physics,cooking);
}
PxConvexMesh* createWheelMesh(const PxF32 width, const PxF32 radius, PxPhysics& physics, PxCooking& cooking)
{
PxVec3 points[2*16];
for(PxU32 i = 0; i < 16; i++)
{
const PxF32 cosTheta = PxCos(i*PxPi*2.0f/16.0f);
const PxF32 sinTheta = PxSin(i*PxPi*2.0f/16.0f);
const PxF32 y = radius*cosTheta;
const PxF32 z = radius*sinTheta;
points[2*i+0] = PxVec3(-width/2.0f, y, z);
points[2*i+1] = PxVec3(+width/2.0f, y, z);
}
return createConvexMesh(points,32,physics,cooking);
}
PxRigidDynamic* createVehicleActor
(const PxVehicleChassisData& chassisData,
PxMaterial** wheelMaterials, PxConvexMesh** wheelConvexMeshes, const PxU32 numWheels, const PxFilterData& wheelSimFilterData,
PxMaterial** chassisMaterials, PxConvexMesh** chassisConvexMeshes, const PxU32 numChassisMeshes, const PxFilterData& chassisSimFilterData,
PxPhysics& physics)
{
//We need a rigid body actor for the vehicle.
//Don't forget to add the actor to the scene after setting up the associated vehicle.
PxRigidDynamic* vehActor = physics.createRigidDynamic(PxTransform(PxIdentity));
//Wheel and chassis query filter data.
//Optional: cars don't drive on other cars.
PxFilterData wheelQryFilterData;
setupNonDrivableSurface(wheelQryFilterData);
PxFilterData chassisQryFilterData;
setupNonDrivableSurface(chassisQryFilterData);
//Add all the wheel shapes to the actor.
for(PxU32 i = 0; i < numWheels; i++)
{
PxConvexMeshGeometry geom(wheelConvexMeshes[i]);
PxShape* wheelShape=PxRigidActorExt::createExclusiveShape(*vehActor, geom, *wheelMaterials[i]);
wheelShape->setQueryFilterData(wheelQryFilterData);
wheelShape->setSimulationFilterData(wheelSimFilterData);
wheelShape->setLocalPose(PxTransform(PxIdentity));
}
//Add the chassis shapes to the actor.
for(PxU32 i = 0; i < numChassisMeshes; i++)
{
PxShape* chassisShape=PxRigidActorExt::createExclusiveShape(*vehActor, PxConvexMeshGeometry(chassisConvexMeshes[i]), *chassisMaterials[i]);
chassisShape->setQueryFilterData(chassisQryFilterData);
chassisShape->setSimulationFilterData(chassisSimFilterData);
chassisShape->setLocalPose(PxTransform(PxIdentity));
}
vehActor->setMass(chassisData.mMass);
vehActor->setMassSpaceInertiaTensor(chassisData.mMOI);
vehActor->setCMassLocalPose(PxTransform(chassisData.mCMOffset,PxQuat(PxIdentity)));
return vehActor;
}
void configureUserData(PxVehicleWheels* vehicle, ActorUserData* actorUserData, ShapeUserData* shapeUserDatas)
{
if(actorUserData)
{
vehicle->getRigidDynamicActor()->userData = actorUserData;
actorUserData->vehicle = vehicle;
}
if(shapeUserDatas)
{
PxShape* shapes[PX_MAX_NB_WHEELS + 1];
vehicle->getRigidDynamicActor()->getShapes(shapes, PX_MAX_NB_WHEELS + 1);
for(PxU32 i = 0; i < vehicle->mWheelsSimData.getNbWheels(); i++)
{
const PxI32 shapeId = vehicle->mWheelsSimData.getWheelShapeMapping(i);
shapes[shapeId]->userData = &shapeUserDatas[i];
shapeUserDatas[i].isWheel = true;
shapeUserDatas[i].wheelId = i;
}
}
}
void customizeVehicleToLengthScale(const PxReal lengthScale, PxRigidDynamic* rigidDynamic, PxVehicleWheelsSimData* wheelsSimData, PxVehicleDriveSimData* driveSimData)
{
//Rigid body center of mass and moment of inertia.
{
PxTransform t = rigidDynamic->getCMassLocalPose();
t.p *= lengthScale;
rigidDynamic->setCMassLocalPose(t);
PxVec3 moi = rigidDynamic->getMassSpaceInertiaTensor();
moi *= (lengthScale*lengthScale);
rigidDynamic->setMassSpaceInertiaTensor(moi);
}
//Wheels, suspensions, wheel centers, tire/susp force application points.
{
for(PxU32 i = 0; i < wheelsSimData->getNbWheels(); i++)
{
PxVehicleWheelData wheelData = wheelsSimData->getWheelData(i);
wheelData.mRadius *= lengthScale;
wheelData.mWidth *= lengthScale;
wheelData.mDampingRate *= lengthScale*lengthScale;
wheelData.mMaxBrakeTorque *= lengthScale*lengthScale;
wheelData.mMaxHandBrakeTorque *= lengthScale*lengthScale;
wheelData.mMOI *= lengthScale*lengthScale;
wheelsSimData->setWheelData(i, wheelData);
PxVehicleSuspensionData suspData = wheelsSimData->getSuspensionData(i);
suspData.mMaxCompression *= lengthScale;
suspData.mMaxDroop *= lengthScale;
wheelsSimData->setSuspensionData(i, suspData);
PxVec3 v = wheelsSimData->getWheelCentreOffset(i);
v *= lengthScale;
wheelsSimData->setWheelCentreOffset(i,v);
v = wheelsSimData->getSuspForceAppPointOffset(i);
v *= lengthScale;
wheelsSimData->setSuspForceAppPointOffset(i,v);
v = wheelsSimData->getTireForceAppPointOffset(i);
v *= lengthScale;
wheelsSimData->setTireForceAppPointOffset(i,v);
}
}
//Slow forward speed correction.
{
wheelsSimData->setSubStepCount(5.0f*lengthScale, 3, 1);
wheelsSimData->setMinLongSlipDenominator(4.0f*lengthScale);
}
//Engine
if(driveSimData)
{
PxVehicleEngineData engineData = driveSimData->getEngineData();
engineData.mMOI *= lengthScale*lengthScale;
engineData.mPeakTorque *= lengthScale*lengthScale;
engineData.mDampingRateFullThrottle *= lengthScale*lengthScale;
engineData.mDampingRateZeroThrottleClutchEngaged *= lengthScale*lengthScale;
engineData.mDampingRateZeroThrottleClutchDisengaged *= lengthScale*lengthScale;
driveSimData->setEngineData(engineData);
}
//Clutch.
if(driveSimData)
{
PxVehicleClutchData clutchData = driveSimData->getClutchData();
clutchData.mStrength *= lengthScale*lengthScale;
driveSimData->setClutchData(clutchData);
}
//Scale the collision meshes too.
{
PxShape* shapes[16];
const PxU32 nbShapes = rigidDynamic->getShapes(shapes, 16);
for(PxU32 i = 0; i < nbShapes; i++)
{
switch(shapes[i]->getGeometryType())
{
case PxGeometryType::eSPHERE:
{
PxSphereGeometry sphere;
shapes[i]->getSphereGeometry(sphere);
sphere.radius *= lengthScale;
shapes[i]->setGeometry(sphere);
}
break;
case PxGeometryType::ePLANE:
PX_ASSERT(false);
break;
case PxGeometryType::eCAPSULE:
{
PxCapsuleGeometry capsule;
shapes[i]->getCapsuleGeometry(capsule);
capsule.radius *= lengthScale;
capsule.halfHeight*= lengthScale;
shapes[i]->setGeometry(capsule);
}
break;
case PxGeometryType::eBOX:
{
PxBoxGeometry box;
shapes[i]->getBoxGeometry(box);
box.halfExtents *= lengthScale;
shapes[i]->setGeometry(box);
}
break;
case PxGeometryType::eCONVEXMESH:
{
PxConvexMeshGeometry convexMesh;
shapes[i]->getConvexMeshGeometry(convexMesh);
convexMesh.scale.scale *= lengthScale;
shapes[i]->setGeometry(convexMesh);
}
break;
case PxGeometryType::eTRIANGLEMESH:
{
PxTriangleMeshGeometry triMesh;
shapes[i]->getTriangleMeshGeometry(triMesh);
triMesh.scale.scale *= lengthScale;
shapes[i]->setGeometry(triMesh);
}
break;
case PxGeometryType::eHEIGHTFIELD:
{
PxHeightFieldGeometry hf;
shapes[i]->getHeightFieldGeometry(hf);
hf.columnScale *= lengthScale;
hf.heightScale *= lengthScale;
hf.rowScale *= lengthScale;
shapes[i]->setGeometry(hf);
}
break;
case PxGeometryType::eINVALID:
case PxGeometryType::eGEOMETRY_COUNT:
break;
}
}
}
}
void customizeVehicleToLengthScale(const PxReal lengthScale, PxRigidDynamic* rigidDynamic, PxVehicleWheelsSimData* wheelsSimData, PxVehicleDriveSimData4W* driveSimData)
{
customizeVehicleToLengthScale(lengthScale, rigidDynamic, wheelsSimData, static_cast<PxVehicleDriveSimData*>(driveSimData));
//Ackermann geometry.
if(driveSimData)
{
PxVehicleAckermannGeometryData ackermannData = driveSimData->getAckermannGeometryData();
ackermannData.mAxleSeparation *= lengthScale;
ackermannData.mFrontWidth *= lengthScale;
ackermannData.mRearWidth *= lengthScale;
driveSimData->setAckermannGeometryData(ackermannData);
}
}
} // namespace snippetvehicle

View File

@ -0,0 +1,142 @@
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
#ifndef SNIPPET_VEHICLE_COMMON_H
#define SNIPPET_VEHICLE_COMMON_H
#include "PxPhysicsAPI.h"
#include "vehicle/PxVehicleDriveTank.h"
#include "vehicle/PxVehicleNoDrive.h"
namespace snippetvehicle
{
using namespace physx;
////////////////////////////////////////////////
PxRigidStatic* createDrivablePlane(const PxFilterData& simFilterData, PxMaterial* material, PxPhysics* physics);
////////////////////////////////////////////////
struct ActorUserData
{
ActorUserData()
: vehicle(NULL),
actor(NULL)
{
}
const PxVehicleWheels* vehicle;
const PxActor* actor;
};
struct ShapeUserData
{
ShapeUserData()
: isWheel(false),
wheelId(0xffffffff)
{
}
bool isWheel;
PxU32 wheelId;
};
struct VehicleDesc
{
VehicleDesc()
: chassisMass(0.0f),
chassisDims(PxVec3(0.0f, 0.0f, 0.0f)),
chassisMOI(PxVec3(0.0f, 0.0f, 0.0f)),
chassisCMOffset(PxVec3(0.0f, 0.0f, 0.0f)),
chassisMaterial(NULL),
wheelMass(0.0f),
wheelWidth(0.0f),
wheelRadius(0.0f),
wheelMOI(0.0f),
wheelMaterial(NULL),
actorUserData(NULL),
shapeUserDatas(NULL)
{
}
PxF32 chassisMass;
PxVec3 chassisDims;
PxVec3 chassisMOI;
PxVec3 chassisCMOffset;
PxMaterial* chassisMaterial;
PxFilterData chassisSimFilterData; //word0 = collide type, word1 = collide against types, word2 = PxPairFlags
PxF32 wheelMass;
PxF32 wheelWidth;
PxF32 wheelRadius;
PxF32 wheelMOI;
PxMaterial* wheelMaterial;
PxU32 numWheels;
PxFilterData wheelSimFilterData; //word0 = collide type, word1 = collide against types, word2 = PxPairFlags
ActorUserData* actorUserData;
ShapeUserData* shapeUserDatas;
};
PxVehicleDrive4W* createVehicle4W(const VehicleDesc& vehDesc, PxPhysics* physics, PxCooking* cooking);
PxVehicleDriveTank* createVehicleTank(const VehicleDesc& vehDesc, PxPhysics* physics, PxCooking* cooking);
PxVehicleNoDrive* createVehicleNoDrive(const VehicleDesc& vehDesc, PxPhysics* physics, PxCooking* cooking);
////////////////////////////////////////////////
PxConvexMesh* createChassisMesh(const PxVec3 dims, PxPhysics& physics, PxCooking& cooking);
PxConvexMesh* createWheelMesh(const PxF32 width, const PxF32 radius, PxPhysics& physics, PxCooking& cooking);
////////////////////////////////////////////////
void customizeVehicleToLengthScale(const PxReal lengthScale, PxRigidDynamic* rigidDynamic, PxVehicleWheelsSimData* wheelsSimData, PxVehicleDriveSimData* driveSimData);
void customizeVehicleToLengthScale(const PxReal lengthScale, PxRigidDynamic* rigidDynamic, PxVehicleWheelsSimData* wheelsSimData, PxVehicleDriveSimData4W* driveSimData);
////////////////////////////////////////////////
PxRigidDynamic* createVehicleActor
(const PxVehicleChassisData& chassisData,
PxMaterial** wheelMaterials, PxConvexMesh** wheelConvexMeshes, const PxU32 numWheels, const PxFilterData& wheelSimFilterData,
PxMaterial** chassisMaterials, PxConvexMesh** chassisConvexMeshes, const PxU32 numChassisMeshes, const PxFilterData& chassisSimFilterData,
PxPhysics& physics);
void configureUserData(PxVehicleWheels* vehicle, ActorUserData* actorUserData, ShapeUserData* shapeUserDatas);
////////////////////////////////////////////////
} // namespace snippetvehicle
#endif //SNIPPET_VEHICLE_COMMON_H

View File

@ -0,0 +1,58 @@
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2021 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 <new>
#include "SnippetVehicleFilterShader.h"
#include "PxPhysicsAPI.h"
namespace snippetvehicle
{
using namespace physx;
PxFilterFlags VehicleFilterShader
(PxFilterObjectAttributes attributes0, PxFilterData filterData0,
PxFilterObjectAttributes attributes1, PxFilterData filterData1,
PxPairFlags& pairFlags, const void* constantBlock, PxU32 constantBlockSize)
{
PX_UNUSED(attributes0);
PX_UNUSED(attributes1);
PX_UNUSED(constantBlock);
PX_UNUSED(constantBlockSize);
if( (0 == (filterData0.word0 & filterData1.word1)) && (0 == (filterData1.word0 & filterData0.word1)) )
return PxFilterFlag::eSUPPRESS;
pairFlags = PxPairFlag::eCONTACT_DEFAULT;
pairFlags |= PxPairFlags(PxU16(filterData0.word2 | filterData1.word2));
return PxFilterFlags();
}
} // namespace snippetvehicle

View File

@ -0,0 +1,62 @@
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
#ifndef SNIPPET_VEHICLE_FILTERSHADER_H
#define SNIPPET_VEHICLE_FILTERSHADER_H
#include "PxPhysicsAPI.h"
namespace snippetvehicle
{
using namespace physx;
enum
{
COLLISION_FLAG_GROUND = 1 << 0,
COLLISION_FLAG_WHEEL = 1 << 1,
COLLISION_FLAG_CHASSIS = 1 << 2,
COLLISION_FLAG_OBSTACLE = 1 << 3,
COLLISION_FLAG_DRIVABLE_OBSTACLE= 1 << 4,
COLLISION_FLAG_GROUND_AGAINST = COLLISION_FLAG_CHASSIS | COLLISION_FLAG_OBSTACLE | COLLISION_FLAG_DRIVABLE_OBSTACLE,
COLLISION_FLAG_WHEEL_AGAINST = COLLISION_FLAG_WHEEL | COLLISION_FLAG_CHASSIS | COLLISION_FLAG_OBSTACLE,
COLLISION_FLAG_CHASSIS_AGAINST = COLLISION_FLAG_GROUND | COLLISION_FLAG_WHEEL | COLLISION_FLAG_CHASSIS | COLLISION_FLAG_OBSTACLE | COLLISION_FLAG_DRIVABLE_OBSTACLE,
COLLISION_FLAG_OBSTACLE_AGAINST = COLLISION_FLAG_GROUND | COLLISION_FLAG_WHEEL | COLLISION_FLAG_CHASSIS | COLLISION_FLAG_OBSTACLE | COLLISION_FLAG_DRIVABLE_OBSTACLE,
COLLISION_FLAG_DRIVABLE_OBSTACLE_AGAINST= COLLISION_FLAG_GROUND | COLLISION_FLAG_CHASSIS | COLLISION_FLAG_OBSTACLE | COLLISION_FLAG_DRIVABLE_OBSTACLE
};
PxFilterFlags VehicleFilterShader
(PxFilterObjectAttributes attributes0, PxFilterData filterData0,
PxFilterObjectAttributes attributes1, PxFilterData filterData1,
PxPairFlags& pairFlags, const void* constantBlock, PxU32 constantBlockSize);
} // namespace snippetvehicle
#endif //SNIPPET_VEHICLE_FILTERSHADER_H

View File

@ -0,0 +1,246 @@
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2021 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 "SnippetVehicleCreate.h"
#include "SnippetVehicleTireFriction.h"
#include "SnippetVehicleSceneQuery.h"
namespace snippetvehicle
{
using namespace physx;
namespace nodrive
{
void computeWheelCenterActorOffsets
(const PxF32 wheelFrontZ, const PxF32 wheelRearZ, const PxVec3& chassisDims, const PxF32 wheelWidth, const PxF32 wheelRadius, const PxU32 numWheels, PxVec3* wheelCentreOffsets)
{
//chassisDims.z is the distance from the rear of the chassis to the front of the chassis.
//The front has z = 0.5*chassisDims.z and the rear has z = -0.5*chassisDims.z.
//Compute a position for the front wheel and the rear wheel along the z-axis.
//Compute the separation between each wheel along the z-axis.
const PxF32 numLeftWheels = numWheels/2.0f;
const PxF32 deltaZ = (wheelFrontZ - wheelRearZ)/(numLeftWheels-1.0f);
//Set the outside of the left and right wheels to be flush with the chassis.
//Set the top of the wheel to be just touching the underside of the chassis.
for(PxU32 i = 0; i < numWheels; i+=2)
{
//Left wheel offset from origin.
wheelCentreOffsets[i + 0] = PxVec3((-chassisDims.x + wheelWidth)*0.5f, -(chassisDims.y/2 + wheelRadius), wheelRearZ + i*deltaZ*0.5f);
//Right wheel offsets from origin.
wheelCentreOffsets[i + 1] = PxVec3((+chassisDims.x - wheelWidth)*0.5f, -(chassisDims.y/2 + wheelRadius), wheelRearZ + i*deltaZ*0.5f);
}
}
void 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;
}
}
//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, PxI32(i));
}
}
}// namespace nodrive
PxVehicleNoDrive* createVehicleNoDrive(const VehicleDesc& vehicleDesc, PxPhysics* physics, PxCooking* cooking)
{
const PxVec3 chassisDims = vehicleDesc.chassisDims;
const PxF32 wheelWidth = vehicleDesc.wheelWidth;
const PxF32 wheelRadius = vehicleDesc.wheelRadius;
const PxU32 numWheels = vehicleDesc.numWheels;
const PxFilterData& chassisSimFilterData = vehicleDesc.chassisSimFilterData;
const PxFilterData& wheelSimFilterData = vehicleDesc.wheelSimFilterData;
//Construct a physx actor with shapes for the chassis and wheels.
//Set the rigid body mass, moment of inertia, and center of mass offset.
PxRigidDynamic* vehActor = NULL;
{
//Construct a convex mesh for a cylindrical wheel.
PxConvexMesh* wheelMesh = createWheelMesh(wheelWidth, wheelRadius, *physics, *cooking);
//Assume all wheels are identical for simplicity.
PxConvexMesh* wheelConvexMeshes[PX_MAX_NB_WHEELS];
PxMaterial* wheelMaterials[PX_MAX_NB_WHEELS];
//Set the meshes and materials for the driven wheels.
for(PxU32 i = 0; i < numWheels; i++)
{
wheelConvexMeshes[i] = wheelMesh;
wheelMaterials[i] = vehicleDesc.wheelMaterial;
}
//Chassis just has a single convex shape for simplicity.
PxConvexMesh* chassisConvexMesh = createChassisMesh(chassisDims, *physics, *cooking);
PxConvexMesh* chassisConvexMeshes[1] = {chassisConvexMesh};
PxMaterial* chassisMaterials[1] = {vehicleDesc.chassisMaterial};
//Rigid body data.
PxVehicleChassisData rigidBodyData;
rigidBodyData.mMOI = vehicleDesc.chassisMOI;
rigidBodyData.mMass = vehicleDesc.chassisMass;
rigidBodyData.mCMOffset = vehicleDesc.chassisCMOffset;
vehActor = createVehicleActor
(rigidBodyData,
wheelMaterials, wheelConvexMeshes, numWheels, wheelSimFilterData,
chassisMaterials, chassisConvexMeshes, 1, chassisSimFilterData,
*physics);
}
//Set up the sim data for the wheels.
PxVehicleWheelsSimData* wheelsSimData = PxVehicleWheelsSimData::allocate(numWheels);
{
//Compute the wheel center offsets from the origin.
PxVec3 wheelCentreActorOffsets[PX_MAX_NB_WHEELS];
const PxF32 frontZ = chassisDims.z*0.3f;
const PxF32 rearZ = -chassisDims.z*0.3f;
nodrive::computeWheelCenterActorOffsets(frontZ, rearZ, chassisDims, wheelWidth, wheelRadius, numWheels, wheelCentreActorOffsets);
nodrive::setupWheelsSimulationData
(vehicleDesc.wheelMass, vehicleDesc.wheelMOI, wheelRadius, wheelWidth,
numWheels, wheelCentreActorOffsets,
vehicleDesc.chassisCMOffset, vehicleDesc.chassisMass,
wheelsSimData);
}
//Create a vehicle from the wheels and drive sim data.
PxVehicleNoDrive* vehDriveNoDrive = PxVehicleNoDrive::allocate(numWheels);
vehDriveNoDrive->setup(physics, vehActor, *wheelsSimData);
//Configure the userdata
configureUserData(vehDriveNoDrive, vehicleDesc.actorUserData, vehicleDesc.shapeUserDatas);
//Free the sim data because we don't need that any more.
wheelsSimData->free();
return vehDriveNoDrive;
}
} // namespace snippetvehicle

View File

@ -0,0 +1,215 @@
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2021 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 <new>
#include "SnippetVehicleSceneQuery.h"
#include "PxPhysicsAPI.h"
namespace snippetvehicle
{
using namespace physx;
void setupDrivableSurface(PxFilterData& filterData)
{
filterData.word3 = static_cast<PxU32>(DRIVABLE_SURFACE);
}
void setupNonDrivableSurface(PxFilterData& filterData)
{
filterData.word3 = UNDRIVABLE_SURFACE;
}
PxQueryHitType::Enum WheelSceneQueryPreFilterBlocking
(PxFilterData filterData0, PxFilterData filterData1,
const void* constantBlock, PxU32 constantBlockSize,
PxHitFlags& queryFlags)
{
//filterData0 is the vehicle suspension query.
//filterData1 is the shape potentially hit by the query.
PX_UNUSED(filterData0);
PX_UNUSED(constantBlock);
PX_UNUSED(constantBlockSize);
PX_UNUSED(queryFlags);
return ((0 == (filterData1.word3 & DRIVABLE_SURFACE)) ? PxQueryHitType::eNONE : PxQueryHitType::eBLOCK);
}
PxQueryHitType::Enum WheelSceneQueryPostFilterBlocking
(PxFilterData filterData0, PxFilterData filterData1,
const void* constantBlock, PxU32 constantBlockSize,
const PxQueryHit& hit)
{
PX_UNUSED(filterData0);
PX_UNUSED(filterData1);
PX_UNUSED(constantBlock);
PX_UNUSED(constantBlockSize);
if((static_cast<const PxSweepHit&>(hit)).hadInitialOverlap())
return PxQueryHitType::eNONE;
return PxQueryHitType::eBLOCK;
}
PxQueryHitType::Enum WheelSceneQueryPreFilterNonBlocking
(PxFilterData filterData0, PxFilterData filterData1,
const void* constantBlock, PxU32 constantBlockSize,
PxHitFlags& queryFlags)
{
//filterData0 is the vehicle suspension query.
//filterData1 is the shape potentially hit by the query.
PX_UNUSED(filterData0);
PX_UNUSED(constantBlock);
PX_UNUSED(constantBlockSize);
PX_UNUSED(queryFlags);
return ((0 == (filterData1.word3 & DRIVABLE_SURFACE)) ? PxQueryHitType::eNONE : PxQueryHitType::eTOUCH);
}
PxQueryHitType::Enum WheelSceneQueryPostFilterNonBlocking
(PxFilterData filterData0, PxFilterData filterData1,
const void* constantBlock, PxU32 constantBlockSize,
const PxQueryHit& hit)
{
PX_UNUSED(filterData0);
PX_UNUSED(filterData1);
PX_UNUSED(constantBlock);
PX_UNUSED(constantBlockSize);
if ((static_cast<const PxSweepHit&>(hit)).hadInitialOverlap())
return PxQueryHitType::eNONE;
return PxQueryHitType::eTOUCH;
}
VehicleSceneQueryData::VehicleSceneQueryData()
: mNumQueriesPerBatch(0),
mNumHitResultsPerQuery(0),
mRaycastResults(NULL),
mRaycastHitBuffer(NULL),
mPreFilterShader(NULL),
mPostFilterShader(NULL)
{
}
VehicleSceneQueryData::~VehicleSceneQueryData()
{
}
VehicleSceneQueryData* VehicleSceneQueryData::allocate
(const PxU32 maxNumVehicles, const PxU32 maxNumWheelsPerVehicle, const PxU32 maxNumHitPointsPerWheel, const PxU32 numVehiclesInBatch,
PxBatchQueryPreFilterShader preFilterShader, PxBatchQueryPostFilterShader postFilterShader,
PxAllocatorCallback& allocator)
{
const PxU32 sqDataSize = ((sizeof(VehicleSceneQueryData) + 15) & ~15);
const PxU32 maxNumWheels = maxNumVehicles*maxNumWheelsPerVehicle;
const PxU32 raycastResultSize = ((sizeof(PxRaycastQueryResult)*maxNumWheels + 15) & ~15);
const PxU32 sweepResultSize = ((sizeof(PxSweepQueryResult)*maxNumWheels + 15) & ~15);
const PxU32 maxNumHitPoints = maxNumWheels*maxNumHitPointsPerWheel;
const PxU32 raycastHitSize = ((sizeof(PxRaycastHit)*maxNumHitPoints + 15) & ~15);
const PxU32 sweepHitSize = ((sizeof(PxSweepHit)*maxNumHitPoints + 15) & ~15);
const PxU32 size = sqDataSize + raycastResultSize + raycastHitSize + sweepResultSize + sweepHitSize;
PxU8* buffer = static_cast<PxU8*>(allocator.allocate(size, NULL, NULL, 0));
VehicleSceneQueryData* sqData = new(buffer) VehicleSceneQueryData();
sqData->mNumQueriesPerBatch = numVehiclesInBatch*maxNumWheelsPerVehicle;
sqData->mNumHitResultsPerQuery = maxNumHitPointsPerWheel;
buffer += sqDataSize;
sqData->mRaycastResults = reinterpret_cast<PxRaycastQueryResult*>(buffer);
buffer += raycastResultSize;
sqData->mRaycastHitBuffer = reinterpret_cast<PxRaycastHit*>(buffer);
buffer += raycastHitSize;
sqData->mSweepResults = reinterpret_cast<PxSweepQueryResult*>(buffer);
buffer += sweepResultSize;
sqData->mSweepHitBuffer = reinterpret_cast<PxSweepHit*>(buffer);
buffer += sweepHitSize;
for (PxU32 i = 0; i < maxNumWheels; i++)
{
new(sqData->mRaycastResults + i) PxRaycastQueryResult();
new(sqData->mSweepResults + i) PxSweepQueryResult();
}
for (PxU32 i = 0; i < maxNumHitPoints; i++)
{
new(sqData->mRaycastHitBuffer + i) PxRaycastHit();
new(sqData->mSweepHitBuffer + i) PxSweepHit();
}
sqData->mPreFilterShader = preFilterShader;
sqData->mPostFilterShader = postFilterShader;
return sqData;
}
void VehicleSceneQueryData::free(PxAllocatorCallback& allocator)
{
allocator.deallocate(this);
}
PxBatchQuery* VehicleSceneQueryData::setUpBatchedSceneQuery(const PxU32 batchId, const VehicleSceneQueryData& vehicleSceneQueryData, PxScene* scene)
{
const PxU32 maxNumQueriesInBatch = vehicleSceneQueryData.mNumQueriesPerBatch;
const PxU32 maxNumHitResultsInBatch = vehicleSceneQueryData.mNumQueriesPerBatch*vehicleSceneQueryData.mNumHitResultsPerQuery;
PxBatchQueryDesc sqDesc(maxNumQueriesInBatch, maxNumQueriesInBatch, 0);
sqDesc.queryMemory.userRaycastResultBuffer = vehicleSceneQueryData.mRaycastResults + batchId*maxNumQueriesInBatch;
sqDesc.queryMemory.userRaycastTouchBuffer = vehicleSceneQueryData.mRaycastHitBuffer + batchId*maxNumHitResultsInBatch;
sqDesc.queryMemory.raycastTouchBufferSize = maxNumHitResultsInBatch;
sqDesc.queryMemory.userSweepResultBuffer = vehicleSceneQueryData.mSweepResults + batchId*maxNumQueriesInBatch;
sqDesc.queryMemory.userSweepTouchBuffer = vehicleSceneQueryData.mSweepHitBuffer + batchId*maxNumHitResultsInBatch;
sqDesc.queryMemory.sweepTouchBufferSize = maxNumHitResultsInBatch;
sqDesc.preFilterShader = vehicleSceneQueryData.mPreFilterShader;
sqDesc.postFilterShader = vehicleSceneQueryData.mPostFilterShader;
return scene->createBatchQuery(sqDesc);
}
PxRaycastQueryResult* VehicleSceneQueryData::getRaycastQueryResultBuffer(const PxU32 batchId)
{
return (mRaycastResults + batchId*mNumQueriesPerBatch);
}
PxSweepQueryResult* VehicleSceneQueryData::getSweepQueryResultBuffer(const PxU32 batchId)
{
return (mSweepResults + batchId*mNumQueriesPerBatch);
}
PxU32 VehicleSceneQueryData::getQueryResultBufferSize() const
{
return mNumQueriesPerBatch;
}
} // namespace snippetvehicle

View File

@ -0,0 +1,126 @@
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
#ifndef SNIPPET_VEHICLE_SCENEQUERY_H
#define SNIPPET_VEHICLE_SCENEQUERY_H
#include "PxPhysicsAPI.h"
namespace snippetvehicle
{
using namespace physx;
enum
{
DRIVABLE_SURFACE = 0xffff0000,
UNDRIVABLE_SURFACE = 0x0000ffff
};
void setupDrivableSurface(PxFilterData& filterData);
void setupNonDrivableSurface(PxFilterData& filterData);
PxQueryHitType::Enum WheelSceneQueryPreFilterBlocking
(PxFilterData filterData0, PxFilterData filterData1,
const void* constantBlock, PxU32 constantBlockSize,
PxHitFlags& queryFlags);
PxQueryHitType::Enum WheelSceneQueryPostFilterBlocking
(PxFilterData queryFilterData, PxFilterData objectFilterData,
const void* constantBlock, PxU32 constantBlockSize,
const PxQueryHit& hit);
PxQueryHitType::Enum WheelSceneQueryPreFilterNonBlocking
(PxFilterData filterData0, PxFilterData filterData1,
const void* constantBlock, PxU32 constantBlockSize,
PxHitFlags& queryFlags);
PxQueryHitType::Enum WheelSceneQueryPostFilterNonBlocking
(PxFilterData queryFilterData, PxFilterData objectFilterData,
const void* constantBlock, PxU32 constantBlockSize,
const PxQueryHit& hit);
//Data structure for quick setup of scene queries for suspension queries.
class VehicleSceneQueryData
{
public:
VehicleSceneQueryData();
~VehicleSceneQueryData();
//Allocate scene query data for up to maxNumVehicles and up to maxNumWheelsPerVehicle with numVehiclesInBatch per batch query.
static VehicleSceneQueryData* allocate
(const PxU32 maxNumVehicles, const PxU32 maxNumWheelsPerVehicle, const PxU32 maxNumHitPointsPerWheel, const PxU32 numVehiclesInBatch,
PxBatchQueryPreFilterShader preFilterShader, PxBatchQueryPostFilterShader postFilterShader,
PxAllocatorCallback& allocator);
//Free allocated buffers.
void free(PxAllocatorCallback& allocator);
//Create a PxBatchQuery instance that will be used for a single specified batch.
static PxBatchQuery* setUpBatchedSceneQuery(const PxU32 batchId, const VehicleSceneQueryData& vehicleSceneQueryData, PxScene* scene);
//Return an array of scene query results for a single specified batch.
PxRaycastQueryResult* getRaycastQueryResultBuffer(const PxU32 batchId);
//Return an array of scene query results for a single specified batch.
PxSweepQueryResult* getSweepQueryResultBuffer(const PxU32 batchId);
//Get the number of scene query results that have been allocated for a single batch.
PxU32 getQueryResultBufferSize() const;
private:
//Number of queries per batch
PxU32 mNumQueriesPerBatch;
//Number of hit results per query
PxU32 mNumHitResultsPerQuery;
//One result for each wheel.
PxRaycastQueryResult* mRaycastResults;
PxSweepQueryResult* mSweepResults;
//One hit for each wheel.
PxRaycastHit* mRaycastHitBuffer;
PxSweepHit* mSweepHitBuffer;
//Filter shader used to filter drivable and non-drivable surfaces
PxBatchQueryPreFilterShader mPreFilterShader;
//Filter shader used to reject hit shapes that initially overlap sweeps.
PxBatchQueryPostFilterShader mPostFilterShader;
};
} // namespace snippetvehicle
#endif //SNIPPET_VEHICLE_SCENEQUERY_H

View File

@ -0,0 +1,238 @@
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2021 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 "SnippetVehicleCreate.h"
#include "SnippetVehicleTireFriction.h"
#include "SnippetVehicleSceneQuery.h"
namespace snippetvehicle
{
namespace tank
{
void computeWheelCenterActorOffsets
(const PxF32 wheelFrontZ, const PxF32 wheelRearZ, const PxVec3& chassisDims, const PxF32 wheelWidth, const PxF32 wheelRadius, const PxU32 numWheels, PxVec3* wheelCentreOffsets)
{
//chassisDims.z is the distance from the rear of the chassis to the front of the chassis.
//The front has z = 0.5*chassisDims.z and the rear has z = -0.5*chassisDims.z.
//Compute a position for the front wheel and the rear wheel along the z-axis.
//Compute the separation between each wheel along the z-axis.
const PxF32 numLeftWheels = numWheels/2.0f;
const PxF32 deltaZ = (wheelFrontZ - wheelRearZ)/(numLeftWheels-1.0f);
//Set the outside of the left and right wheels to be flush with the chassis.
//Set the top of the wheel to be just touching the underside of the chassis.
for(PxU32 i = 0; i < numWheels; i+=2)
{
//Left wheel offset from origin.
wheelCentreOffsets[i + 0] = PxVec3((-chassisDims.x + wheelWidth)*0.5f, -(chassisDims.y/2 + wheelRadius), wheelRearZ + i*deltaZ*0.5f);
//Right wheel offsets from origin.
wheelCentreOffsets[i + 1] = PxVec3((+chassisDims.x - wheelWidth)*0.5f, -(chassisDims.y/2 + wheelRadius), wheelRearZ + i*deltaZ*0.5f);
}
}
void 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.
//Increase the damping on the wheel.
for(PxU32 i = 0; i < numWheels; i++)
{
wheels[i].mMass = wheelMass;
wheels[i].mMOI = wheelMOI;
wheels[i].mRadius = wheelRadius;
wheels[i].mWidth = wheelWidth;
wheels[i].mDampingRate = 2.0f;
}
}
//Set up the tires.
PxVehicleTireData tires[PX_MAX_NB_WHEELS];
{
//Set all tire types to "normal" type.
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 = 10000.0f;
suspensions[i].mSpringDamperRate = 1500.0f;
suspensions[i].mSprungMass = suspSprungMasses[i];
}
}
//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];
{
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, PxI32(i));
}
}
}// namespace tank
PxVehicleDriveTank* createVehicleTank(const VehicleDesc& tankDesc, PxPhysics* physics, PxCooking* cooking)
{
const PxVec3 chassisDims = tankDesc.chassisDims;
const PxF32 wheelWidth = tankDesc.wheelWidth;
const PxF32 wheelRadius = tankDesc.wheelRadius;
const PxU32 numWheels = tankDesc.numWheels;
const PxFilterData& chassisSimFilterData = tankDesc.chassisSimFilterData;
const PxFilterData& wheelSimFilterData = tankDesc.wheelSimFilterData;
//Construct a physx actor with shapes for the chassis and wheels.
//Set the rigid body mass, moment of inertia, and center of mass offset.
PxRigidDynamic* tankActor = NULL;
{
//Construct a convex mesh for a cylindrical wheel.
PxConvexMesh* wheelMesh = createWheelMesh(wheelWidth, wheelRadius, *physics, *cooking);
//Assume all wheels are identical for simplicity.
PxConvexMesh* wheelConvexMeshes[PX_MAX_NB_WHEELS];
PxMaterial* wheelMaterials[PX_MAX_NB_WHEELS];
for(PxU32 i = 0; i < numWheels; i++)
{
wheelConvexMeshes[i] = wheelMesh;
wheelMaterials[i] = tankDesc.wheelMaterial;
}
//Chassis just has a single convex shape for simplicity.
PxConvexMesh* chassisConvexMesh = createChassisMesh(chassisDims, *physics, *cooking);
PxConvexMesh* chassisConvexMeshes[1] = {chassisConvexMesh};
PxMaterial* chassisMaterials[1] = {tankDesc.chassisMaterial};
//Rigid body data.
PxVehicleChassisData rigidBodyData;
rigidBodyData.mMOI = tankDesc.chassisMOI;
rigidBodyData.mMass = tankDesc.chassisMass;
rigidBodyData.mCMOffset = tankDesc.chassisCMOffset;
tankActor = createVehicleActor
(rigidBodyData,
wheelMaterials, wheelConvexMeshes, numWheels, wheelSimFilterData,
chassisMaterials, chassisConvexMeshes, 1, chassisSimFilterData,
*physics);
}
//Set up the sim data for the wheels.
PxVehicleWheelsSimData* wheelsSimData = PxVehicleWheelsSimData::allocate(numWheels);
{
//Compute the wheel center offsets from the origin.
PxVec3 wheelCentreActorOffsets[PX_MAX_NB_WHEELS];
const PxF32 frontZ = chassisDims.z*0.35f;
const PxF32 rearZ = -chassisDims.z*0.35f;
tank::computeWheelCenterActorOffsets(frontZ, rearZ, chassisDims, wheelWidth, wheelRadius, numWheels, wheelCentreActorOffsets);
tank::setupWheelsSimulationData
(tankDesc.wheelMass, tankDesc.wheelMOI, wheelRadius, wheelWidth,
numWheels, wheelCentreActorOffsets,
tankDesc.chassisCMOffset, tankDesc.chassisMass,
wheelsSimData);
}
//Set up the sim data for the tank drive model.
PxVehicleDriveSimData driveSimData;
{
//Set up the engine to be more powerful but also more damped than the default engine.
PxVehicleEngineData engineData = driveSimData.getEngineData();
engineData.mPeakTorque *= 2.0f;
engineData.mDampingRateZeroThrottleClutchEngaged = 2.0f;
engineData.mDampingRateZeroThrottleClutchDisengaged = 0.5f;
engineData.mDampingRateFullThrottle = 0.5f;
driveSimData.setEngineData(engineData);
}
//Create a tank from the wheels and drive sim data.
PxVehicleDriveTank* vehDriveTank = PxVehicleDriveTank::allocate(numWheels);
vehDriveTank->setup(physics, tankActor, *wheelsSimData, driveSimData, numWheels);
//Configure the userdata
configureUserData(vehDriveTank, tankDesc.actorUserData, tankDesc.shapeUserDatas);
//Free the sim data because we don't need that any more.
wheelsSimData->free();
return vehDriveTank;
}
} // namespace snippetvehicle

View File

@ -0,0 +1,69 @@
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2021 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 <new>
#include "SnippetVehicleTireFriction.h"
#include "PxPhysicsAPI.h"
namespace snippetvehicle
{
using namespace physx;
//Tire model friction for each combination of drivable surface type and tire type.
static PxF32 gTireFrictionMultipliers[MAX_NUM_SURFACE_TYPES][MAX_NUM_TIRE_TYPES]=
{
//NORMAL, WORN
{1.00f, 0.1f}//TARMAC
};
PxVehicleDrivableSurfaceToTireFrictionPairs* createFrictionPairs(const PxMaterial* defaultMaterial)
{
PxVehicleDrivableSurfaceType surfaceTypes[1];
surfaceTypes[0].mType = SURFACE_TYPE_TARMAC;
const PxMaterial* surfaceMaterials[1];
surfaceMaterials[0] = defaultMaterial;
PxVehicleDrivableSurfaceToTireFrictionPairs* surfaceTirePairs =
PxVehicleDrivableSurfaceToTireFrictionPairs::allocate(MAX_NUM_TIRE_TYPES,MAX_NUM_SURFACE_TYPES);
surfaceTirePairs->setup(MAX_NUM_TIRE_TYPES, MAX_NUM_SURFACE_TYPES, surfaceMaterials, surfaceTypes);
for(PxU32 i = 0; i < MAX_NUM_SURFACE_TYPES; i++)
{
for(PxU32 j = 0; j < MAX_NUM_TIRE_TYPES; j++)
{
surfaceTirePairs->setTypePairFriction(i,j,gTireFrictionMultipliers[i][j]);
}
}
return surfaceTirePairs;
}
} // namespace snippetvehicle

View File

@ -0,0 +1,59 @@
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
#ifndef SNIPPET_VEHICLE_TIREFRICTION_H
#define SNIPPET_VEHICLE_TIREFRICTION_H
#include "PxPhysicsAPI.h"
namespace snippetvehicle
{
using namespace physx;
//Drivable surface types.
enum
{
SURFACE_TYPE_TARMAC,
MAX_NUM_SURFACE_TYPES
};
//Tire types.
enum
{
TIRE_TYPE_NORMAL=0,
TIRE_TYPE_WORN,
MAX_NUM_TIRE_TYPES
};
PxVehicleDrivableSurfaceToTireFrictionPairs* createFrictionPairs(const PxMaterial* defaultMaterial);
} // namespace snippetvehicle
#endif //SNIPPET_VEHICLE_TIREFRICTION_H

View File

@ -0,0 +1,97 @@
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
#ifndef SNIPPET_VEHICLE_WHEELQUERYRESULT_H
#define SNIPPET_VEHICLE_WHEELQUERYRESULT_H
#include "PxPhysicsAPI.h"
#include <new>
namespace snippetvehicle
{
using namespace physx;
//Data structure for quick setup of wheel query data structures.
class VehicleWheelQueryResults
{
public:
VehicleWheelQueryResults()
: mVehicleWheelQueryResults(NULL)
{
}
~VehicleWheelQueryResults()
{
}
//Allocate wheel results for up to maxNumVehicles with up to maxNumWheelsPerVehicle.
static VehicleWheelQueryResults* allocate(const PxU32 maxNumVehicles, const PxU32 maxNumWheelsPerVehicle, PxAllocatorCallback& allocator)
{
const PxU32 byteSize = sizeof(VehicleWheelQueryResults) + sizeof(PxVehicleWheelQueryResult)*maxNumVehicles + sizeof(PxWheelQueryResult)*maxNumWheelsPerVehicle*maxNumVehicles;
PxU8* buffer = static_cast<PxU8*>(allocator.allocate(byteSize, NULL, NULL, 0));
VehicleWheelQueryResults* vwqr = reinterpret_cast<VehicleWheelQueryResults*>(buffer);
buffer += sizeof(VehicleWheelQueryResults);
vwqr->mVehicleWheelQueryResults = reinterpret_cast<PxVehicleWheelQueryResult*>(buffer);
buffer+=sizeof(PxVehicleWheelQueryResult)*maxNumVehicles;
for(PxU32 i=0;i<maxNumVehicles;i++)
{
new(buffer) PxWheelQueryResult();
vwqr->mVehicleWheelQueryResults[i].wheelQueryResults = reinterpret_cast<PxWheelQueryResult*>(buffer);
vwqr->mVehicleWheelQueryResults[i].nbWheelQueryResults = maxNumWheelsPerVehicle;
buffer += sizeof(PxWheelQueryResult)*maxNumWheelsPerVehicle;
}
return vwqr;
}
//Free allocated buffer for scene queries of suspension raycasts.
void free(PxAllocatorCallback& allocator)
{
allocator.deallocate(this);
}
//Return the PxVehicleWheelQueryResult for a vehicle specified by an index.
PxVehicleWheelQueryResult* getVehicleWheelQueryResults(const PxU32 id)
{
return (mVehicleWheelQueryResults + id);
}
private:
PxVehicleWheelQueryResult* mVehicleWheelQueryResults;
};
} // namespace snippetvehicle
#endif //SNIPPET_VEHICLE_WHEELQUERYRESULT_H