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,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