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

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,198 @@
//
// 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 SAMPLE_VEHICLE_H
#define SAMPLE_VEHICLE_H
#include "PhysXSample.h"
#include "SampleVehicle_ControlInputs.h"
#include "SampleVehicle_CameraController.h"
#include "SampleVehicle_VehicleController.h"
#include "SampleVehicle_VehicleManager.h"
#include "SampleVehicle_GameLogic.h"
#include "vehicle/PxVehicleTireFriction.h"
class SampleVehicle : public PhysXSample
{
public:
SampleVehicle(PhysXSampleApplication& app);
virtual ~SampleVehicle();
///////////////////////////////////////////////////////////////////////////////
// Implements RAWImportCallback
virtual void newMesh(const RAWMesh&);
///////////////////////////////////////////////////////////////////////////////
// Implements SampleApplication
virtual void onInit();
virtual void onInit(bool restart) { onInit(); }
virtual void onShutdown();
virtual void onTickPreRender(PxF32 dtime);
virtual void onTickPostRender(PxF32 dtime);
virtual void onDigitalInputEvent(const SampleFramework::InputEvent& , bool val);
virtual void onAnalogInputEvent(const SampleFramework::InputEvent& , float val);
///////////////////////////////////////////////////////////////////////////////
// Implements PhysXSampleApplication
virtual void helpRender(PxU32 x, PxU32 y, PxU8 textAlpha);
virtual void descriptionRender(PxU32 x, PxU32 y, PxU8 textAlpha);
virtual void customizeSample(SampleSetup&);
virtual void customizeSceneDesc(PxSceneDesc&);
virtual void customizeRender();
virtual void onSubstep(PxF32 dtime);
virtual void collectInputEvents(std::vector<const SampleFramework::InputEvent*>& inputEvents);
private:
SampleVehicle_ControlInputs mControlInputs;
SampleVehicle_CameraController mCameraController;
SampleVehicle_VehicleController mVehicleController;
//Terrain
PxF32* mTerrainVB;
PxU32 mNbTerrainVerts;
enum
{
MAX_NUM_INDEX_BUFFERS = 16
};
PxU32 mNbIB;
PxU32* mIB[MAX_NUM_INDEX_BUFFERS];
PxU32 mNbTriangles[MAX_NUM_INDEX_BUFFERS];
PxU32 mRenderMaterial[MAX_NUM_INDEX_BUFFERS];
//Materials
PxVehicleDrivableSurfaceType mVehicleDrivableSurfaceTypes[MAX_NUM_INDEX_BUFFERS];
PxMaterial* mStandardMaterials[MAX_NUM_INDEX_BUFFERS];
PxMaterial* mChassisMaterialDrivable;
PxMaterial* mChassisMaterialNonDrivable;
RenderMaterial* mTerrainMaterial;
RenderMaterial* mRoadMaterial;
RenderMaterial* mRoadIceMaterial;
RenderMaterial* mRoadGravelMaterial;
void createStandardMaterials();
enum eFocusVehicleType
{
ePLAYER_VEHICLE_TYPE_VEHICLE4W=0,
ePLAYER_VEHICLE_TYPE_VEHICLE6W,
ePLAYER_VEHICLE_TYPE_TANK4W,
ePLAYER_VEHICLE_TYPE_TANK6W,
eMAX_NUM_FOCUS_VEHICLE_TYPES
};
// Vehicles
SampleVehicle_VehicleManager mVehicleManager;
std::vector<RenderMeshActor*> mVehicleGraphics;
PxU32 mPlayerVehicle;
eFocusVehicleType mPlayerVehicleType;
PxVehicleDriveTankControlModel::Enum mTankDriveModel;
const char* getFocusVehicleName();
void createVehicles();
PxU32 mTerrainSize;
PxF32 mTerrainWidth;
PxRigidActor* mHFActor;
void createTrack(PxU32 size, PxF32 width, PxF32 chaos);
void createTerrain(PxU32 size, PxF32 width, PxF32 chaos);
void addRenderMesh(PxF32* verts, PxU32 nVerts, PxU32* indices, PxU32 mIndices, PxU32 matID);
void addMesh(PxRigidActor* actor, PxF32* verts, PxU32 nVerts, PxU32* indices, PxU32 mIndices, PxU32 materialIndex, const char* filename);
void createLandscapeMesh();
//Obstacles
void createObstacles();
PxRigidStatic* addStaticObstacle(const PxTransform& transform, const PxU32 numShapes, PxTransform* shapeTransforms, PxGeometry** shapeGeometries, PxMaterial** shapeMaterials);
PxRigidDynamic* addDynamicObstacle(const PxTransform& transform, const PxF32 mass, const PxU32 numShapes, PxTransform* transforms, PxGeometry** geometries, PxMaterial** materials);
PxRigidDynamic* addDynamicDrivableObstacle(const PxTransform& transform, const PxF32 mass, const PxU32 numShapes, PxTransform* transforms, PxGeometry** geometries, PxMaterial** materials);
void createStack(PxU32 size, PxF32 boxSize, const PxVec3& pos, const PxQuat& quat);
void createWall(const PxU32 numHorizontalBoxes, const PxU32 numVerticalBoxes, const PxF32 boxSize, const PxVec3& pos, const PxQuat& quat);
//Debug render
bool mHideScreenText;
bool mDebugRenderFlag;
#if PX_DEBUG_VEHICLE_ON
PxU32 mDebugRenderActiveGraphChannelWheel;
PxU32 mDebugRenderActiveGraphChannelEngine;
PxVehicleTelemetryData* mTelemetryData4W;
PxVehicleTelemetryData* mTelemetryData6W;
#endif
void setupTelemetryData();
void clearTelemetryData();
void drawWheels();
void drawVehicleDebug();
void drawHud();
void drawGraphsAndPrintTireSurfaceTypes(const PxVehicleWheels& focusVehicle, const PxVehicleWheelQueryResult& focusVehicleWheelQueryResults);
void drawFocusVehicleGraphsAndPrintTireSurfaces();
//Waypoints
SampleVehicleWayPoints mWayPoints;
bool mFixCar;
bool mBackToStart;
//3W and 4W modes
bool m3WModeIncremented;
PxU32 m3WMode;
PxF32 mForwardSpeedHud;
#if defined(SERIALIZE_VEHICLE_BINARY)
void* mMemory;
#endif
void updateCameraController(const PxF32 dtime, PxScene& scene);
void updateVehicleController(const PxF32 dtime);
void updateVehicleManager(const PxF32 dtime, const PxVec3& gravity);
void resetFocusVehicleAtWaypoint();
PxRigidDynamic* getFocusVehicleRigidDynamicActor();
bool getFocusVehicleUsesAutoGears();
char mVehicleFilePath[256];
};
#endif

View File

@ -0,0 +1,367 @@
//
// 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 "SampleVehicle.h"
#include "RenderPhysX3Debug.h"
#include "PxRigidDynamic.h"
#include "SampleVehicle_VehicleManager.h"
using namespace SampleRenderer;
// PT: this file contains the part of SampleVehicle dealing with cars' debug rendering
void SampleVehicle::drawWheels()
{
PxSceneReadLock scopedLock(*mScene);
const RendererColor colorPurple(255, 0, 255);
for(PxU32 i=0;i<mVehicleManager.getNbVehicles();i++)
{
//Draw a rotating arrow to get an idea of the wheel rotation speed.
PxVehicleWheels* veh=mVehicleManager.getVehicle(i);
const PxRigidDynamic* actor=veh->getRigidDynamicActor();
PxShape* shapeBuffer[PX_MAX_NB_WHEELS];
actor->getShapes(shapeBuffer,veh->mWheelsSimData.getNbWheels());
const PxTransform vehGlobalPose=actor->getGlobalPose();
const PxU32 numWheels=veh->mWheelsSimData.getNbWheels();
for(PxU32 j=0;j<numWheels;j++)
{
const PxTransform wheelTransform=vehGlobalPose.transform(shapeBuffer[j]->getLocalPose());
const PxF32 wheelRadius=veh->mWheelsSimData.getWheelData(j).mRadius;
const PxF32 wheelHalfWidth=veh->mWheelsSimData.getWheelData(j).mWidth*0.5f;
PxVec3 offset=wheelTransform.q.getBasisVector0()*wheelHalfWidth;
offset*= (veh->mWheelsSimData.getWheelCentreOffset(j).x > 0) ? 1.0f : -1.0f;
const PxVec3 arrow=wheelTransform.rotate(PxVec3(0,0,1));
getDebugRenderer()->addLine(wheelTransform.p+offset, wheelTransform.p+offset+arrow*wheelRadius, colorPurple);
}
}
}
void SampleVehicle::drawVehicleDebug()
{
PxSceneReadLock scopedLock(*mScene);
const RendererColor colorColl(255, 0, 0);
const RendererColor colorCol2(0, 255, 0);
const RendererColor colorCol3(0, 0, 255);
#if PX_DEBUG_VEHICLE_ON
const PxVec3* tireForceAppPoints=NULL;
const PxVec3* suspForceAppPoints=NULL;
switch(mPlayerVehicleType)
{
case ePLAYER_VEHICLE_TYPE_VEHICLE4W:
case ePLAYER_VEHICLE_TYPE_TANK4W:
tireForceAppPoints=mTelemetryData4W->getTireforceAppPoints();
suspForceAppPoints=mTelemetryData4W->getSuspforceAppPoints();
break;
case ePLAYER_VEHICLE_TYPE_VEHICLE6W:
case ePLAYER_VEHICLE_TYPE_TANK6W:
tireForceAppPoints=mTelemetryData6W->getTireforceAppPoints();
suspForceAppPoints=mTelemetryData6W->getSuspforceAppPoints();
break;
default:
PX_ASSERT(false);
break;
}
#endif
const PxVehicleWheels& vehicle4W=*mVehicleManager.getVehicle(mPlayerVehicle);
const PxVehicleWheelQueryResult& vehicleWheelQueryResults=mVehicleManager.getVehicleWheelQueryResults(mPlayerVehicle);
const PxRigidDynamic* actor=vehicle4W.getRigidDynamicActor();
const PxU32 numWheels=vehicle4W.mWheelsSimData.getNbWheels();
PxVec3 v[8];
PxVec3 w[8];
PxF32 l[8];
for(PxU32 i=0;i<numWheels;i++)
{
v[i] = vehicleWheelQueryResults.wheelQueryResults[i].suspLineStart;
w[i] = vehicleWheelQueryResults.wheelQueryResults[i].suspLineDir;
l[i] = vehicleWheelQueryResults.wheelQueryResults[i].suspLineLength;
}
const PxTransform t=actor->getGlobalPose().transform(actor->getCMassLocalPose());
const PxVec3 dirs[3]={t.rotate(PxVec3(1,0,0)),t.rotate(PxVec3(0,1,0)),t.rotate(PxVec3(0,0,1))};
getDebugRenderer()->addLine(t.p, t.p + dirs[0]*4.0f, colorColl);
getDebugRenderer()->addLine(t.p, t.p + dirs[1]*4.0f, colorColl);
getDebugRenderer()->addLine(t.p, t.p + dirs[2]*4.0f, colorColl);
for(PxU32 j=0;j<numWheels;j++)
{
getDebugRenderer()->addLine(v[j], v[j]+w[j]*l[j], colorColl);
#if PX_DEBUG_VEHICLE_ON
//Draw all tire force app points.
const PxVec3& appPoint = tireForceAppPoints[j];
getDebugRenderer()->addLine(appPoint - dirs[0], appPoint + dirs[0], colorCol2);
getDebugRenderer()->addLine(appPoint - dirs[2], appPoint + dirs[2], colorCol2);
//Draw all susp force app points.
const PxVec3& appPoint2 = suspForceAppPoints[j];
getDebugRenderer()->addLine(appPoint2 - dirs[0], appPoint2 + dirs[0], colorCol3);
getDebugRenderer()->addLine(appPoint2 - dirs[2], appPoint2 + dirs[2], colorCol3);
#endif
}
}
static void drawBox2D(Renderer* renderer, PxF32 minX, PxF32 maxX, PxF32 minY, PxF32 maxY, const RendererColor& color, PxF32 alpha)
{
ScreenQuad sq;
sq.mX0 = minX;
sq.mY0 = 1.0f - minY;
sq.mX1 = maxX;
sq.mY1 = 1.0f - maxY;
sq.mLeftUpColor = color;
sq.mRightUpColor = color;
sq.mLeftDownColor = color;
sq.mRightDownColor = color;
sq.mAlpha = alpha;
renderer->drawScreenQuad(sq);
}
static void print(Renderer* renderer, PxF32 x, PxF32 y, PxF32 scale_, const char* text)
{
PxU32 width, height;
renderer->getWindowSize(width, height);
y = 1.0f - y;
const PxReal scale = scale_*20.0f;
const PxReal shadowOffset = 6.0f;
const RendererColor textColor(255, 255, 255, 255);
renderer->print(PxU32(x*PxF32(width)), PxU32(y*PxF32(height)), text, scale, shadowOffset, textColor);
}
void SampleVehicle::drawHud()
{
const PxVehicleWheels& focusVehicle = *mVehicleManager.getVehicle(mPlayerVehicle);
PxVehicleDriveDynData* driveDynData=NULL;
PxVehicleDriveSimData* driveSimData=NULL;
switch(focusVehicle.getVehicleType())
{
case PxVehicleTypes::eDRIVE4W:
{
PxVehicleDrive4W& vehDrive4W=(PxVehicleDrive4W&)focusVehicle;
driveDynData=&vehDrive4W.mDriveDynData;
driveSimData=&vehDrive4W.mDriveSimData;
}
break;
case PxVehicleTypes::eDRIVENW:
{
PxVehicleDriveNW& vehDriveNW=(PxVehicleDriveNW&)focusVehicle;
driveDynData=&vehDriveNW.mDriveDynData;
driveSimData=&vehDriveNW.mDriveSimData;
}
break;
case PxVehicleTypes::eDRIVETANK:
{
PxVehicleDriveTank& vehDriveTank=(PxVehicleDriveTank&)focusVehicle;
driveDynData=&vehDriveTank.mDriveDynData;
driveSimData=&vehDriveTank.mDriveSimData;
}
break;
default:
PX_ASSERT(false);
break;
}
const PxU32 currentGear=driveDynData->getCurrentGear();
const PxF32 vz=mForwardSpeedHud*3.6f;
const PxF32 revs=driveDynData->getEngineRotationSpeed();
const PxF32 maxRevs=driveSimData->getEngineData().mMaxOmega*60*0.5f/PxPi;//Convert from radians per second to rpm
const PxF32 invMaxRevs=driveSimData->getEngineData().getRecipMaxOmega();
//Draw gears and speed.
const PxF32 x=0.5f;
const PxF32 y=0.18f;
const PxF32 length=0.1f;
const PxF32 textheight=0.02f;
Renderer* renderer = getRenderer();
drawBox2D(renderer, x-length-textheight, x+length+textheight, y, y+length+textheight, RendererColor(255, 255, 255), 0.5f);
//Gear
char gear[PxVehicleGearsData::eGEARSRATIO_COUNT][64]=
{
"R","N","1","2","3","4","5"
};
print(renderer, x-0.25f*textheight, y+0.02f, 0.02f, gear[currentGear]);
//Speed
char speed[64];
sprintf(speed, "%1.0f %s", PxAbs(vz), "kmph");
print(renderer, x-textheight, y+length-textheight, textheight, speed);
//Revs
{
const PxF32 xy[4]={x, 1.0f-y, x-length, 1.0f-(y+length)};
renderer->drawLines2D(2, xy, RendererColor(0, 0, 255));
char buffer[64];
sprintf(buffer, "%d \n", 0);
print(renderer, x-length, y+length, textheight, buffer);
}
{
const PxF32 xy[4]={x, 1.0f-y, x+length, 1.0f-(y+length)};
renderer->drawLines2D(2, xy, RendererColor(0, 0, 255));
char buffer[64];
sprintf(buffer, "%1.0f \n", maxRevs);
print(renderer, x+length-2*textheight, y+length, textheight, buffer);
}
{
const PxF32 alpha=revs*invMaxRevs;
const PxF32 dx=-(1.0f-alpha)*length + alpha*length;
const PxF32 xy[4]={x, 1.0f-y, x+dx, 1.0f-(y+length)};
renderer->drawLines2D(2, xy, RendererColor(255, 0, 0));
}
}
#if PX_DEBUG_VEHICLE_ON
static PX_FORCE_INLINE RendererColor getColor(const PxVec3& c)
{
return RendererColor(PxU8(c.x), PxU8(c.y), PxU8(c.z));
}
static PX_FORCE_INLINE void convertColors(const PxVec3* src, RendererColor* dst)
{
for(PxU32 i=0;i<PxVehicleGraph::eMAX_NB_SAMPLES;i++)
*dst++ = getColor(src[i]);
}
static void convertY(PxF32* xy)
{
for(PxU32 i=0;i<PxVehicleGraph::eMAX_NB_SAMPLES;i++)
xy[2*i+1]=1.0f-xy[2*i+1];
}
#endif //PX_DEBUG_VEHICLE_ON
#if PX_DEBUG_VEHICLE_ON
void drawGraphsAndPrintTireSurfaceTypesN
(const PxVehicleTelemetryData& telemetryData, const PxU32* tireTypes, const PxU32* surfaceTypes,
const PxU32 activeEngineGraphChannel, const PxU32 activeWheelGraphChannel,
SampleRenderer::Renderer* renderer)
{
PxF32 xy[2*PxVehicleGraph::eMAX_NB_SAMPLES];
PxVec3 color[PxVehicleGraph::eMAX_NB_SAMPLES];
RendererColor rendererColor[PxVehicleGraph::eMAX_NB_SAMPLES];
char title[PxVehicleGraph::eMAX_NB_TITLE_CHARS];
const PxU32 numWheelGraphs=telemetryData.getNbWheelGraphs();
for(PxU32 i=0;i<numWheelGraphs;i++)
{
PxF32 xMin,xMax,yMin,yMax;
telemetryData.getWheelGraph(i).getBackgroundCoords(xMin,yMin,xMax,yMax);
const PxVec3& backgroundColor=telemetryData.getWheelGraph(i).getBackgroundColor();
const PxF32 alpha=telemetryData.getWheelGraph(i).getBackgroundAlpha();
drawBox2D(renderer, xMin,xMax,yMin,yMax, getColor(backgroundColor),alpha);
telemetryData.getWheelGraph(i).computeGraphChannel(activeWheelGraphChannel,xy,color,title);
convertY(xy);
convertColors(color, rendererColor);
renderer->drawLines2D(PxVehicleGraph::eMAX_NB_SAMPLES, xy, rendererColor);
print(renderer, xMin,yMax-0.02f, 0.02f, title);
const PxU32 tireType=tireTypes[i];
const PxU32 tireSurfaceType=surfaceTypes[i];
if (PxVehicleDrivableSurfaceType::eSURFACE_TYPE_UNKNOWN!=tireSurfaceType)
{
const char* surfaceType= SurfaceTypeNames::getName(tireSurfaceType);
const PxF32 friction=TireFrictionMultipliers::getValue(tireSurfaceType, tireType);
char surfaceDetails[64];
sprintf(surfaceDetails, "%s %1.2f \n", surfaceType, friction);
print(renderer, xMin+0.1f, yMax-0.12f, 0.02f, surfaceDetails);
}
}
PxF32 xMin,xMax,yMin,yMax;
telemetryData.getEngineGraph().getBackgroundCoords(xMin,yMin,xMax,yMax);
const PxVec3& backgroundColor=telemetryData.getEngineGraph().getBackgroundColor();
const PxF32 alpha=telemetryData.getEngineGraph().getBackgroundAlpha();
drawBox2D(renderer, xMin,xMax,yMin,yMax, getColor(backgroundColor),alpha);
telemetryData.getEngineGraph().computeGraphChannel(activeEngineGraphChannel,xy,color,title);
convertY(xy);
convertColors(color, rendererColor);
renderer->drawLines2D(PxVehicleGraph::eMAX_NB_SAMPLES, xy, rendererColor);
print(renderer, xMin,yMax-0.02f,0.02f,title);
}
#endif //PX_DEBUG_VEHICLE_GRAPH_ON
void SampleVehicle::drawGraphsAndPrintTireSurfaceTypes(const PxVehicleWheels& focusVehicle, const PxVehicleWheelQueryResult& focusVehicleWheelQueryResults)
{
#if PX_DEBUG_VEHICLE_ON
PxU32 tireTypes[8];
PxU32 surfaceTypes[8];
const PxU32 numWheels=focusVehicle.mWheelsSimData.getNbWheels();
PX_ASSERT(numWheels<=8);
for(PxU32 i=0;i<numWheels;i++)
{
tireTypes[i]=focusVehicle.mWheelsSimData.getTireData(i).mType;
surfaceTypes[i]=focusVehicleWheelQueryResults.wheelQueryResults[i].tireSurfaceType;
}
PxVehicleTelemetryData* vehTelData=NULL;
switch(mPlayerVehicleType)
{
case ePLAYER_VEHICLE_TYPE_VEHICLE4W:
case ePLAYER_VEHICLE_TYPE_TANK4W:
vehTelData=mTelemetryData4W;
break;
case ePLAYER_VEHICLE_TYPE_VEHICLE6W:
case ePLAYER_VEHICLE_TYPE_TANK6W:
vehTelData=mTelemetryData6W;
break;
default:
PX_ASSERT(false);
break;
}
drawGraphsAndPrintTireSurfaceTypesN(
*vehTelData,tireTypes,surfaceTypes,
mDebugRenderActiveGraphChannelEngine,mDebugRenderActiveGraphChannelWheel,
getRenderer());
#endif
}

View File

@ -0,0 +1,98 @@
//
// 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.
#ifndef _SAMPLE_VEHICLE_INPUT_EVENT_IDS_H
#define _SAMPLE_VEHICLE_INPUT_EVENT_IDS_H
#include <SampleBaseInputEventIds.h>
// InputEvents used by SampleVehicle
enum SampleVehicleInputEventIds
{
SAMPLE_VEHICLE_FIRST_ID = NUM_SAMPLE_BASE_INPUT_EVENT_IDS,
CAR_ACCELERATE_BRAKE,
//KEYBOARD (car+tank)
VEH_ACCELERATE_KBD,
VEH_GEAR_UP_KBD,
VEH_GEAR_DOWN_KBD,
VEH_SAVE_KBD,
//KEYBOARD (car)
CAR_BRAKE_KBD,
CAR_HANDBRAKE_KBD,
CAR_STEER_LEFT_KBD,
CAR_STEER_RIGHT_KBD,
//KEYBOARD (tank)
TANK_THRUST_LEFT_KBD,
TANK_THRUST_RIGHT_KBD,
TANK_BRAKE_LEFT_KBD,
TANK_BRAKE_RIGHT_KBD,
//KEYBOARD (camera)
CAMERA_ROTATE_LEFT_KBD,
CAMERA_ROTATE_RIGHT_KBD,
CAMERA_ROTATE_UP_KBD,
CAMERA_ROTATE_DOWN_KBD,
//GAMEPAD (car+tank)
VEH_ACCELERATE_PAD,
VEH_GEAR_UP_PAD,
VEH_GEAR_DOWN_PAD,
//GAMEPAD (car)
CAR_BRAKE_PAD,
CAR_HANDBRAKE_PAD,
CAR_STEER_PAD,
//GAMEPAD (tank)
TANK_THRUST_LEFT_PAD,
TANK_THRUST_RIGHT_PAD,
TANK_BRAKE_LEFT_PAD,
TANK_BRAKE_RIGHT_PAD,
//GAMEPAD (camera)
CAMERA_ROTATE_LEFT_RIGHT_PAD,
CAMERA_ROTATE_UP_DOWN_PAD,
//
AUTOMATIC_GEAR,
DEBUG_RENDER_FLAG,
DEBUG_RENDER_WHEEL ,
DEBUG_RENDER_ENGINE,
RETRY,
FIX_CAR,
CAMERA_LOCK,
W3MODE,
NUM_SAMPLE_VEHICLE_INPUT_EVENT_IDS,
};
#endif

View File

@ -0,0 +1,547 @@
//
// 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 "SampleVehicle.h"
#include "SampleVehicle_SceneQuery.h"
#include "SampleRandomPrecomputed.h"
#include "SampleAllocatorSDKClasses.h"
#include "RendererMemoryMacros.h"
#include "RenderMaterial.h"
#include "RenderMeshActor.h"
#include "cooking/PxTriangleMeshDesc.h"
#include "geometry/PxHeightFieldGeometry.h"
#include "geometry/PxHeightFieldSample.h"
#include "geometry/PxHeightFieldDesc.h"
#include "cooking/PxCooking.h"
#include "PxScene.h"
#include "PxRigidStatic.h"
#include "PxTkStream.h"
#include "PxTkFile.h"
//using namespace physx;
using namespace PxToolkit;
//Use a mesh (instead of a height field)
static bool gRecook = false;
enum MaterialID
{
MATERIAL_TERRAIN_MUD = 1000,
MATERIAL_ROAD_TARMAC = 1001,
MATERIAL_ROAD_SNOW = 1002,
MATERIAL_ROAD_GRASS = 1003,
};
static void computeTerrain(bool* done, float* pVB, PxU32 x0, PxU32 y0, PxU32 currentSize, float value, PxU32 initSize, SampleRandomPrecomputed& randomPrecomputed)
{
// Compute new size
currentSize>>=1;
if(currentSize > 0)
{
const PxU32 x1 = (x0+currentSize) % initSize;
const PxU32 x2 = (x0+currentSize+currentSize) % initSize;
const PxU32 y1 = (y0+currentSize) % initSize;
const PxU32 y2 = (y0+currentSize+currentSize) % initSize;
if(!done[x1 + y0*initSize]) pVB[(x1 + y0*initSize)*9+1] = randomPrecomputed.getRandomInRange(-0.5f*value, 0.5f*value) + 0.5f * (pVB[(x0 + y0*initSize)*9+1] + pVB[(x2 + y0*initSize)*9+1]);
if(!done[x0 + y1*initSize]) pVB[(x0 + y1*initSize)*9+1] = randomPrecomputed.getRandomInRange(-0.5f*value, 0.5f*value) + 0.5f * (pVB[(x0 + y0*initSize)*9+1] + pVB[(x0 + y2*initSize)*9+1]);
if(!done[x2 + y1*initSize]) pVB[(x2 + y1*initSize)*9+1] = randomPrecomputed.getRandomInRange(-0.5f*value, 0.5f*value) + 0.5f * (pVB[(x2 + y0*initSize)*9+1] + pVB[(x2 + y2*initSize)*9+1]);
if(!done[x1 + y2*initSize]) pVB[(x1 + y2*initSize)*9+1] = randomPrecomputed.getRandomInRange(-0.5f*value, 0.5f*value) + 0.5f * (pVB[(x0 + y2*initSize)*9+1] + pVB[(x2 + y2*initSize)*9+1]);
if(!done[x1 + y1*initSize]) pVB[(x1 + y1*initSize)*9+1] = randomPrecomputed.getRandomInRange(-0.5f*value, 0.5f*value) + 0.5f * (pVB[(x0 + y1*initSize)*9+1] + pVB[(x2 + y1*initSize)*9+1]);
done[x1 + y0*initSize] = true;
done[x0 + y1*initSize] = true;
done[x2 + y1*initSize] = true;
done[x1 + y2*initSize] = true;
done[x1 + y1*initSize] = true;
// Recurse through 4 corners
value *= 0.5f;
computeTerrain(done, pVB, x0, y0, currentSize, value, initSize, randomPrecomputed);
computeTerrain(done, pVB, x0, y1, currentSize, value, initSize, randomPrecomputed);
computeTerrain(done, pVB, x1, y0, currentSize, value, initSize, randomPrecomputed);
computeTerrain(done, pVB, x1, y1, currentSize, value, initSize, randomPrecomputed);
}
}
void SampleVehicle::createTerrain(PxU32 size, float width, float chaos)
{
mNbTerrainVerts = size*size;
// Vertex buffer
mTerrainVB = (float*)SAMPLE_ALLOC(sizeof(float)*mNbTerrainVerts*3*3);
for(PxU32 y=0;y<size;y++)
{
for(PxU32 x=0;x<size;x++)
{
mTerrainVB[(x+y*size)*9+0] = (float(x)-(float(size-1)*0.5f))* width;
mTerrainVB[(x+y*size)*9+1] = 0.0f;
mTerrainVB[(x+y*size)*9+2] = (float(y)-(float(size-1)*0.5f))* width;
mTerrainVB[(x+y*size)*9+3] = 0.0f; mTerrainVB[(x+y*size)*9+4] = 1.0f; mTerrainVB[(x+y*size)*9+5] = 0.0f;
mTerrainVB[(x+y*size)*9+6] = 0.5f; mTerrainVB[(x+y*size)*9+7] = 0.4f; mTerrainVB[(x+y*size)*9+8] = 0.2f;
}
}
// Fractalize
bool* doneBuffer = (bool*)SAMPLE_ALLOC(sizeof(bool)*mNbTerrainVerts);
PxU32* tagBuffer = (PxU32*)SAMPLE_ALLOC(sizeof(PxU32)*mNbTerrainVerts);
for(PxU32 i=0;i<mNbTerrainVerts;i++)
{
doneBuffer[i] = false;
tagBuffer[i] = 0;
}
mTerrainVB[1] = 10.0f;
mTerrainVB[(size-1)*9+1] = 10.0f;
mTerrainVB[(size*(size-1))*9+1] = 10.0f;
mTerrainVB[(mNbTerrainVerts-1)*9+1] = 10.0f;
SampleRandomPrecomputed randomPrecomputed(*this);
computeTerrain(doneBuffer, mTerrainVB, 0, 0, size, chaos/16.0f, size, randomPrecomputed);
const PxU32 street0 = (PxU32)(size/3.0f);
const PxU32 streetSize = (PxU32)(size/30.0f);
float ay = 0.0f;
for(PxU32 y=0;y<size;y++)
{
for(PxU32 x=street0;x<street0+streetSize;x++)
{
ay+=mTerrainVB[(x+y*size)*9+1];
ay+=mTerrainVB[(y+x*size)*9+1];
}
}
const float cx = size/2.0f;
const float cy = size/2.0f;
const float r = size/3.0f;
const float g = streetSize/2.0f;
for(PxU32 i=0;i<mNbTerrainVerts;i++)
tagBuffer[i] = false;
ay/=streetSize*size;
ay-=streetSize;
for(PxU32 y=15;y<size-15;y++)
{
bool smoothBorder = true;
for(PxU32 x=street0;x<street0+streetSize;x++)
{
if(y > size*0.5f && y < size*0.7f)
{
mTerrainVB[(x+y*size)*9+1]=ay+sinf(((float)y)*12.0f+4.0f)*2.0f;
smoothBorder = false;
}
else
{
mTerrainVB[(x+y*size)*9+1]=ay;
}
if(y > size*0.55f && y < size*0.75f)
{
mTerrainVB[(y+x*size)*9+1]=ay+sinf(y*12.0f)*0.75f;
//mTerrainVB[(y+x*size)*9+1]=ay;
tagBuffer[y+x*size] = 3;
tagBuffer[x+y*size] = 3;
smoothBorder = false;
}
else if(y < size*0.15f)
{
const float s = size*0.15f-(float)y;
mTerrainVB[(y+x*size)*9+1]=ay+s*0.25f;
smoothBorder = false;
}
else if(y > size*0.85f)
{
const float s = (float)y-size*0.85f;
mTerrainVB[(y+x*size)*9+1]=ay+s*0.7f;
smoothBorder = false;
}
else
{
mTerrainVB[(y+x*size)*9+1]=ay;
tagBuffer[y+x*size] = 1;
tagBuffer[x+y*size] = 1;
}
}
if(smoothBorder)
{
mTerrainVB[((street0-1)+y*size)*9+1]=ay*0.5f+mTerrainVB[((street0-1)+y*size)*9+1]*0.5f;
mTerrainVB[(y+(street0-1)*size)*9+1]=ay*0.5f+mTerrainVB[(y+(street0-1)*size)*9+1]*0.5f;
mTerrainVB[((street0+1)+y*size)*9+1]=ay*0.5f+mTerrainVB[((street0+1)+y*size)*9+1]*0.5f;
mTerrainVB[(y+(street0+1)*size)*9+1]=ay*0.5f+mTerrainVB[(y+(street0+1)*size)*9+1]*0.5f;
}
}
// Circle street
for(PxU32 y=0;y<size;y++)
{
for(PxU32 x=0;x<size;x++)
{
const float x0 = x-cx;
const float y0 = y-cy;
const float d = sqrtf(x0*x0+y0*y0);
if(d >= r && d < r+streetSize)
{
mTerrainVB[(y+x*size)*9+1]=ay;
if(y > size*0.55f && y < size*0.75f)
tagBuffer[y+x*size] = 2;
else
tagBuffer[y+x*size] = 1;
}
else if(d >= r+streetSize && d < r+streetSize+g)
{
const float a = (d-(r+streetSize))/g;
mTerrainVB[(y+x*size)*9+1]=ay*(1.0f-a) + mTerrainVB[(y+x*size)*9+1]*a;
}
else if(d >= r-g && d < r)
{
const float a = (d-(r-g))/g;
mTerrainVB[(y+x*size)*9+1]=ay*a+mTerrainVB[(y+x*size)*9+1]*(1.0f-a);
}
}
}
// Borders
const float b = size/25.0f;
const float bd = size/2.0f-b;
for(PxU32 y=0;y<size;y++)
{
for(PxU32 x=0;x<size;x++)
{
const float x0 = fabsf(x-cx);
const float y0 = fabsf(y-cy);
if(x0 > bd || y0 > bd)
{
float a0 = (x0-bd)/b;
float a1 = (y0-bd)/b;
if(a1 > a0)
a0 = a1;
mTerrainVB[(y+x*size)*9+1]=20.0f*a0 + mTerrainVB[(y+x*size)*9+1]*(1-a0);
}
}
}
// Sobel filter
for(PxU32 y=1;y<size-1;y++)
{
for(PxU32 x=1;x<size-1;x++)
{
// 1 0 -1
// 2 0 -2
// 1 0 -1
float dx;
dx = mTerrainVB[((x-1)+(y-1)*size)*9+1];
dx -= mTerrainVB[((x+1)+(y-1)*size)*9+1];
dx += 2.0f*mTerrainVB[((x-1)+(y+0)*size)*9+1];
dx -= 2.0f*mTerrainVB[((x+1)+(y+0)*size)*9+1];
dx += mTerrainVB[((x-1)+(y+1)*size)*9+1];
dx -= mTerrainVB[((x+1)+(y+1)*size)*9+1];
// 1 2 1
// 0 0 0
// -1 -2 -1
float dy;
dy = mTerrainVB[((x-1)+(y-1)*size)*9+1];
dy += 2.0f*mTerrainVB[((x+0)+(y-1)*size)*9+1];
dy += mTerrainVB[((x+1)+(y-1)*size)*9+1];
dy -= mTerrainVB[((x-1)+(y+1)*size)*9+1];
dy -= 2.0f*mTerrainVB[((x+0)+(y+1)*size)*9+1];
dy -= mTerrainVB[((x+1)+(y+1)*size)*9+1];
const float nx = dx/width*0.15f;
const float ny = 1.0f;
const float nz = dy/width*0.15f;
const float len = sqrtf(nx*nx+ny*ny+nz*nz);
mTerrainVB[(x+y*size)*9+3] = nx/len;
mTerrainVB[(x+y*size)*9+4] = ny/len;
mTerrainVB[(x+y*size)*9+5] = nz/len;
}
}
// Static lighting (two directional lights)
const float l0[3] = {0.25f/0.8292f, 0.75f/0.8292f, 0.25f/0.8292f};
const float l1[3] = {0.65f/0.963f, 0.55f/0.963f, 0.45f/0.963f};
//const float len = sqrtf(l1[0]*l1[0]+l1[1]*l1[1]+l1[2]*l1[2]);
for(PxU32 y=0;y<size;y++)
{
for(PxU32 x=0;x<size;x++)
{
const float nx = mTerrainVB[(x+y*size)*9+3], ny = mTerrainVB[(x+y*size)*9+4], nz = mTerrainVB[(x+y*size)*9+5];
const float a = 0.3f;
float dot0 = l0[0]*nx + l0[1]*ny + l0[2]*nz;
float dot1 = l1[0]*nx + l1[1]*ny + l1[2]*nz;
if(dot0 < 0.0f) { dot0 = 0.0f; }
if(dot1 < 0.0f) { dot1 = 0.0f; }
const float l = dot0*0.7f + dot1*0.3f;
mTerrainVB[(x+y*size)*9+6] = mTerrainVB[(x+y*size)*9+6]*(l + a);
mTerrainVB[(x+y*size)*9+7] = mTerrainVB[(x+y*size)*9+7]*(l + a);
mTerrainVB[(x+y*size)*9+8] = mTerrainVB[(x+y*size)*9+8]*(l + a);
/*mTerrainVB[(x+y*size)*9+3] = 0.0f;
mTerrainVB[(x+y*size)*9+4] = -1.0f;
mTerrainVB[(x+y*size)*9+5] = 0.0f;*/
}
}
// Index buffers
const PxU32 maxNbTerrainTriangles = (size-1)*(size-1)*2;
mNbIB = 4;
mRenderMaterial[0] = MATERIAL_TERRAIN_MUD;
mRenderMaterial[1] = MATERIAL_ROAD_TARMAC;
mRenderMaterial[2] = MATERIAL_ROAD_SNOW;
mRenderMaterial[3] = MATERIAL_ROAD_GRASS;
for(PxU32 i=0;i<mNbIB;i++)
{
mIB[i] = (PxU32*)SAMPLE_ALLOC(sizeof(PxU32)*maxNbTerrainTriangles*3);
mNbTriangles[i] = 0;
}
for(PxU32 j=0;j<size-1;j++)
{
for(PxU32 i=0;i<size-1;i++)
{
PxU32 tris[6];
tris[0] = i + j*size; tris[1] = i + (j+1)*size; tris[2] = i+1 + (j+1)*size;
tris[3] = i + j*size; tris[4] = i+1 + (j+1)*size; tris[5] = i+1 + j*size;
for(PxU32 t=0;t<2;t++)
{
const PxU32 vt0 = tagBuffer[tris[t*3+0]];
const PxU32 vt1 = tagBuffer[tris[t*3+1]];
const PxU32 vt2 = tagBuffer[tris[t*3+2]];
PxU32 buffer = 0;
if(vt0 == vt1 && vt0 == vt2)
buffer = vt0;
mIB[buffer][mNbTriangles[buffer]*3+0] = tris[t*3+0];
mIB[buffer][mNbTriangles[buffer]*3+1] = tris[t*3+1];
mIB[buffer][mNbTriangles[buffer]*3+2] = tris[t*3+2];
mNbTriangles[buffer]++;
}
}
}
SAMPLE_FREE(tagBuffer);
SAMPLE_FREE(doneBuffer);
}
void SampleVehicle::addMesh(PxRigidActor* actor, float* verts, PxU32 nVerts, PxU32* indices, PxU32 mIndices, PxU32 materialIndex, const char* filename)
{
const char* filenameCooked = getSampleOutputFilePath(filename, "");
PX_ASSERT(NULL != filenameCooked);
bool ok = false;
if(!gRecook)
{
SampleFramework::File* fp = NULL;
PxToolkit::fopen_s(&fp, filenameCooked, "rb");
if(fp)
{
fseek(fp, 0, SEEK_END);
PxU32 filesize = (PxU32)ftell(fp);
fclose(fp);
ok = (filesize != 0);
}
}
if(!ok)
{
PxTriangleMeshDesc meshDesc;
meshDesc.points.count = nVerts;
meshDesc.triangles.count = mIndices;
meshDesc.points.stride = sizeof(float)*3*3;
meshDesc.triangles.stride = sizeof(PxU32)*3;
meshDesc.points.data = verts;
meshDesc.triangles.data = indices;
meshDesc.flags = PxMeshFlags(0);
//
shdfnd::printFormatted("Cooking object... %s", filenameCooked);
PxDefaultFileOutputStream stream(filenameCooked);
ok = getCooking().cookTriangleMesh(meshDesc, stream);
shdfnd::printFormatted(" - Done\n");
}
{
PxDefaultFileInputData stream(filenameCooked);
PxTriangleMesh* triangleMesh = getPhysics().createTriangleMesh(stream);
if(triangleMesh)
{
PxRigidActorExt::createExclusiveShape(*actor, PxTriangleMeshGeometry(triangleMesh), *mStandardMaterials[materialIndex] /**mStandardMaterial*/);
}
}
}
// PT: the renderer also expects 16bit indices so we still have to cut a big mesh to pieces
void SampleVehicle::addRenderMesh(float* verts, PxU32 nVerts, PxU32* indices, PxU32 mIndices, PxU32 matID)
{
float minX=1000000.0f;
float minZ=1000000.0f;
float maxX=-1000000.0f;
float maxZ=-1000000.0f;
// PT: the VB uses interleaved data so we need a temp buffer
PxVec3Alloc* v = SAMPLE_NEW(PxVec3Alloc)[nVerts];
float* curVerts = verts;
PxBounds3 meshBound = PxBounds3::empty();
for(PxU32 i=0;i<nVerts;i++)
{
v[i].x = curVerts[0];
v[i].y = curVerts[1];
v[i].z = curVerts[2];
if (v[i].x < minX) { minX = v[i].x; }
if (v[i].z < minZ) { minZ = v[i].z; }
if (v[i].x > maxX) { maxX = v[i].x; }
if (v[i].z > maxZ) { maxZ = v[i].z; }
curVerts += 3*3;
meshBound.include(v[i]);
}
PxReal* uv = (PxReal*)SAMPLE_ALLOC(sizeof(PxReal)*nVerts*2);
curVerts = verts;
const float scaleX = (maxX-minX)/64.0f;
const float scaleZ = (maxZ-minZ)/64.0f;
for(PxU32 i=0;i<nVerts;i++)
{
uv[i*2+0] = (curVerts[0]-minX)/scaleX;
uv[i*2+1] = (curVerts[2]-minZ)/scaleZ;
curVerts += 3*3;
}
RAWMesh data;
data.mMaterialID = matID;
data.mNbVerts = nVerts;
data.mNbFaces = mIndices;
data.mVerts = v;
data.mUVs = uv;
data.mIndices = indices;
RenderMeshActor* renderActor = createRenderMeshFromRawMesh(data);
if( renderActor != NULL )
{
renderActor->setWorldBounds(meshBound);
renderActor->setEnableCameraCull(true);
}
SAMPLE_FREE(uv);
DELETEARRAY(v);
}
void SampleVehicle::createTrack(PxU32 size, float width, float chaos)
{
createTerrain(size, width, chaos);
createLandscapeMesh();
}
void SampleVehicle::createLandscapeMesh()
{
RAWTexture data;
data.mName = "gravel_diffuse.dds";
RenderTexture* gravelTexture = createRenderTextureFromRawTexture(data);
mTerrainMaterial = SAMPLE_NEW(RenderMaterial)(*getRenderer(), PxVec3(0.5f, 0.25f, 0.125f), 1.0f, false, MATERIAL_TERRAIN_MUD, gravelTexture);
mRenderMaterials.push_back(mTerrainMaterial);
data.mName = "asphalt_diffuse.dds";
RenderTexture* asphaltTexture = createRenderTextureFromRawTexture(data);
mRoadMaterial = SAMPLE_NEW(RenderMaterial)(*getRenderer(), PxVec3(1.0f, 1.0f, 1.0f), 1.0f, false, MATERIAL_ROAD_TARMAC, asphaltTexture);
mRenderMaterials.push_back(mRoadMaterial);
data.mName = "ice_diffuse.dds";
RenderTexture* snowTexture = createRenderTextureFromRawTexture(data);
mRoadIceMaterial = SAMPLE_NEW(RenderMaterial)(*getRenderer(), PxVec3(0.05f, 0.05f, 0.75f), 1.0f, false, MATERIAL_ROAD_SNOW, snowTexture);
mRenderMaterials.push_back(mRoadIceMaterial);
data.mName = "grass_diffuse.dds";
RenderTexture* grassTexture = createRenderTextureFromRawTexture(data);
mRoadGravelMaterial = SAMPLE_NEW(RenderMaterial)(*getRenderer(), PxVec3(1.0f, 1.0f, 1.0f), 1.0f, false, MATERIAL_ROAD_GRASS, grassTexture);
mRenderMaterials.push_back(mRoadGravelMaterial);
PxTransform pose;
pose = PxTransform(PxIdentity);
// pose.p.y -= 10.0f;
mHFActor = getPhysics().createRigidStatic(pose);
for(PxU32 i=0;i<mNbIB;i++)
{
if(mNbTriangles[i] > 0)
{
char filename[512];
sprintf(filename, "SampleVehicleGroundMeshes_Part%d", i);
addMesh(mHFActor, mTerrainVB, mNbTerrainVerts, mIB[i], mNbTriangles[i], i, filename);
if (mNbTriangles[i] > (1<<16))
{
PxU32 firstBatch = mNbTriangles[i]/2;
addRenderMesh(mTerrainVB, mNbTerrainVerts, mIB[i], firstBatch, MATERIAL_TERRAIN_MUD);
addRenderMesh(mTerrainVB, mNbTerrainVerts, mIB[i]+(firstBatch*3), mNbTriangles[i]-firstBatch, mRenderMaterial[i]);
}
else
{
addRenderMesh(mTerrainVB, mNbTerrainVerts, mIB[i], mNbTriangles[i], mRenderMaterial[i]);
}
}
}
PxSceneWriteLock scopedLock(*mScene);
mScene->addActor(*mHFActor);
PxShape* shapeBuffer[MAX_NUM_INDEX_BUFFERS];
mHFActor->getShapes(shapeBuffer, MAX_NUM_INDEX_BUFFERS);
PxFilterData simulationFilterData;
simulationFilterData.word0=COLLISION_FLAG_GROUND;
simulationFilterData.word1=COLLISION_FLAG_GROUND_AGAINST;
PxFilterData queryFilterData;
SampleVehicleSetupDrivableShapeQueryFilterData(&queryFilterData);
for(PxU32 i=0;i<mNbIB;i++)
{
shapeBuffer[i]->setSimulationFilterData(simulationFilterData);
shapeBuffer[i]->setQueryFilterData(queryFilterData);
shapeBuffer[i]->setFlag(PxShapeFlag::eVISUALIZATION,false);
}
}

View File

@ -0,0 +1,164 @@
//
// 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 "SampleVehicle_CameraController.h"
#include "PhysXSampleApplication.h"
#include "PxRigidDynamic.h"
#include "PxQueryFiltering.h"
#include "PxScene.h"
#include "PxSceneLock.h"
#include "vehicle/PxVehicleWheels.h"
using namespace SampleRenderer;
using namespace SampleFramework;
///////////////////////////////////////////////////////////////////////////////
SampleVehicle_CameraController::SampleVehicle_CameraController()
: mRotateInputY (0.0f),
mRotateInputZ (0.0f),
mMaxCameraRotateSpeed (5.0f),
mCameraRotateAngleY (0.0f),
mCameraRotateAngleZ (0.33f),
mCameraPos (PxVec3(0,0,0)),
mCameraTargetPos (PxVec3(0,0,0)),
mLastCarPos (PxVec3(0,0,0)),
mLastCarVelocity (PxVec3(0,0,0)),
mCameraInit (false),
mLockOnFocusVehTransform (true),
mLastFocusVehTransform (PxTransform(PxIdentity))
{
}
SampleVehicle_CameraController::~SampleVehicle_CameraController()
{
}
static void dampVec3(const PxVec3& oldPosition, PxVec3& newPosition, PxF32 timestep)
{
PxF32 t = 0.7f * timestep * 8.0f;
t = PxMin(t, 1.0f);
newPosition = oldPosition * (1 - t) + newPosition * t;
}
void SampleVehicle_CameraController::update(const PxReal dtime, const PxRigidDynamic* actor, PxScene& scene)
{
PxSceneReadLock scopedLock(scene);
PxTransform carChassisTransfm;
if(mLockOnFocusVehTransform)
{
carChassisTransfm = actor->getGlobalPose();
mLastFocusVehTransform = carChassisTransfm;
}
else
{
carChassisTransfm = mLastFocusVehTransform;
}
PxF32 camDist = 15.0f;
PxF32 cameraYRotExtra = 0.0f;
PxVec3 velocity = mLastCarPos-carChassisTransfm.p;
if (mCameraInit)
{
//Work out the forward and sideways directions.
PxVec3 unitZ(0,0,1);
PxVec3 carDirection = carChassisTransfm.q.rotate(unitZ);
PxVec3 unitX(1,0,0);
PxVec3 carSideDirection = carChassisTransfm.q.rotate(unitX);
//Acceleration (note that is not scaled by time).
PxVec3 acclVec = mLastCarVelocity-velocity;
//Higher forward accelerations allow the car to speed away from the camera.
PxF32 acclZ = carDirection.dot(acclVec);
camDist = PxMax(camDist+acclZ*400.0f, 5.0f);
//Higher sideways accelerations allow the car's rotation to speed away from the camera's rotation.
PxF32 acclX = carSideDirection.dot(acclVec);
cameraYRotExtra = -acclX*10.0f;
//At very small sideways speeds the camera greatly amplifies any numeric error in the body and leads to a slight jitter.
//Scale cameraYRotExtra by a value in range (0,1) for side speeds in range (0.1,1.0) and by zero for side speeds less than 0.1.
PxFixedSizeLookupTable<4> table;
table.addPair(0.0f, 0.0f);
table.addPair(0.1f*dtime, 0);
table.addPair(1.0f*dtime, 1);
PxF32 velX = carSideDirection.dot(velocity);
cameraYRotExtra *= table.getYVal(PxAbs(velX));
}
mCameraRotateAngleY+=mRotateInputY*mMaxCameraRotateSpeed*dtime;
mCameraRotateAngleY=physx::intrinsics::fsel(mCameraRotateAngleY-10*PxPi, mCameraRotateAngleY-10*PxPi, physx::intrinsics::fsel(-mCameraRotateAngleY-10*PxPi, mCameraRotateAngleY + 10*PxPi, mCameraRotateAngleY));
mCameraRotateAngleZ+=mRotateInputZ*mMaxCameraRotateSpeed*dtime;
mCameraRotateAngleZ=PxClamp(mCameraRotateAngleZ,-PxPi*0.05f,PxPi*0.45f);
PxVec3 cameraDir=PxVec3(0,0,1)*PxCos(mCameraRotateAngleY+cameraYRotExtra) + PxVec3(1,0,0)*PxSin(mCameraRotateAngleY+cameraYRotExtra);
cameraDir=cameraDir*PxCos(mCameraRotateAngleZ)-PxVec3(0,1,0)*PxSin(mCameraRotateAngleZ);
const PxVec3 direction = carChassisTransfm.q.rotate(cameraDir);
PxVec3 target = carChassisTransfm.p;
target.y+=0.5f;
PxRaycastBuffer hit;
PxQueryFilterData filterData(PxQueryFlag::eSTATIC);
scene.raycast(target, -direction, camDist, hit, PxHitFlags(0), filterData);
if (hit.hasBlock && hit.block.shape != NULL)
{
camDist = hit.block.distance-0.25f;
}
camDist = PxMax(5.0f, PxMin(camDist, 50.0f));
PxVec3 position = target-direction*camDist;
if (mCameraInit)
{
dampVec3(mCameraPos, position, dtime);
dampVec3(mCameraTargetPos, target, dtime);
}
mCameraPos = position;
mCameraTargetPos = target;
mCameraInit = true;
mLastCarVelocity = velocity;
mLastCarPos = carChassisTransfm.p;
}
void SampleVehicle_CameraController::update(const PxReal dtime, const PxVehicleWheels& focusVehicle, PxScene& scene)
{
const PxRigidDynamic* actor=focusVehicle.getRigidDynamicActor();
update(dtime,actor,scene);
}

View File

@ -0,0 +1,92 @@
//
// 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 SAMPLE_VEHICLE_CAMERA_CONTROLLER_H
#define SAMPLE_VEHICLE_CAMERA_CONTROLLER_H
#include "common/PxPhysXCommonConfig.h"
#include "foundation/PxVec3.h"
#include "foundation/PxTransform.h"
using namespace physx;
namespace physx
{
class PxScene;
class PxVehicleWheels;
class PxRigidDynamic;
}
class Camera;
class SampleVehicle_CameraController
{
public:
SampleVehicle_CameraController();
~SampleVehicle_CameraController();
void setInputs(const PxF32 rotateInputY, const PxF32 rotateInputZ)
{
mRotateInputY=rotateInputY;
mRotateInputZ=rotateInputZ;
}
void update(const PxF32 dtime, const PxVehicleWheels& focusVehicle, PxScene& scene);
void restart() {}
bool getIsLockedOnVehicleTransform() const {return mLockOnFocusVehTransform;}
void toggleLockOnVehTransform() {mLockOnFocusVehTransform = !mLockOnFocusVehTransform;}
const PxVec3& getCameraPos() const {return mCameraPos;}
const PxVec3& getCameraTar() const {return mCameraTargetPos;}
private:
PxF32 mRotateInputY;
PxF32 mRotateInputZ;
PxF32 mMaxCameraRotateSpeed;
PxF32 mCameraRotateAngleY;
PxF32 mCameraRotateAngleZ;
PxVec3 mCameraPos;
PxVec3 mCameraTargetPos;
PxVec3 mLastCarPos;
PxVec3 mLastCarVelocity;
bool mCameraInit;
bool mLockOnFocusVehTransform;
PxTransform mLastFocusVehTransform;
void update(const PxReal dtime, const PxRigidDynamic* actor, PxScene& scene);
};
#endif //SAMPLE_VEHICLE_CAMERA_CONTROLLER_H

View File

@ -0,0 +1,68 @@
//
// 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 "SampleVehicle_ControlInputs.h"
#include "PhysXSampleApplication.h"
using namespace SampleRenderer;
using namespace SampleFramework;
///////////////////////////////////////////////////////////////////////////////
SampleVehicle_ControlInputs::SampleVehicle_ControlInputs()
: mCameraRotateInputY (0.0f),
mCameraRotateInputZ (0.0f),
mAccelKeyPressed (false),
mGearUpKeyPressed (false),
mGearDownKeyPressed (false),
mBrakeKeyPressed (false),
mHandbrakeKeyPressed (false),
mSteerLeftKeyPressed (false),
mSteerRightKeyPressed (false),
mBrakeLeftKeyPressed (false),
mBrakeRightKeyPressed (false),
mThrustLeftKeyPressed (false),
mThrustRightKeyPressed (false),
mAccel (0.0f),
mGearup (false),
mGeardown (false),
mBrake (0.0f),
mSteer (0.0f),
mHandbrake (false),
mThrustLeft (0.0f),
mThrustRight (0.0f),
mBrakeLeft (0.0f),
mBrakeRight (0.0f)
{
}
SampleVehicle_ControlInputs::~SampleVehicle_ControlInputs()
{
}

View File

@ -0,0 +1,145 @@
//
// 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 SAMPLE_VEHICLE_CONTROL_INPUTS_H
#define SAMPLE_VEHICLE_CONTROL_INPUTS_H
#include "common/PxPhysXCommonConfig.h"
using namespace physx;
class SampleVehicle_ControlInputs
{
public:
SampleVehicle_ControlInputs();
~SampleVehicle_ControlInputs();
//Camera inputs
void setRotateY(const PxF32 f) {mCameraRotateInputY=f;}
void setRotateZ(const PxF32 f) {mCameraRotateInputZ=f;}
PxF32 getRotateY() const {return mCameraRotateInputY;}
PxF32 getRotateZ() const {return mCameraRotateInputZ;}
//Keyboard driving inputs - (car + tank)
void setAccelKeyPressed(const bool b) {mAccelKeyPressed=b;}
void setGearUpKeyPressed(const bool b) {mGearUpKeyPressed=b;}
void setGearDownKeyPressed(const bool b) {mGearDownKeyPressed=b;}
bool getAccelKeyPressed() const {return mAccelKeyPressed;}
bool getGearUpKeyPressed() const {return mGearUpKeyPressed;}
bool getGearDownKeyPressed() const {return mGearDownKeyPressed;}
//Keyboard driving inputs - (car only)
void setBrakeKeyPressed(const bool b) {mBrakeKeyPressed=b;}
void setHandbrakeKeyPressed(const bool b) {mHandbrakeKeyPressed=b;}
void setSteerLeftKeyPressed(const bool b) {mSteerLeftKeyPressed=b;}
void setSteerRightKeyPressed(const bool b) {mSteerRightKeyPressed=b;}
bool getBrakeKeyPressed() const {return mBrakeKeyPressed;}
bool getHandbrakeKeyPressed() const {return mHandbrakeKeyPressed;}
bool getSteerLeftKeyPressed() const {return mSteerLeftKeyPressed;}
bool getSteerRightKeyPressed() const {return mSteerRightKeyPressed;}
//Keyboard driving inputs - (tank only)
void setBrakeLeftKeyPressed(const bool b) {mBrakeLeftKeyPressed=b;}
void setBrakeRightKeyPressed(const bool b) {mBrakeRightKeyPressed=b;}
void setThrustLeftKeyPressed(const bool b) {mThrustLeftKeyPressed=b;}
void setThrustRightKeyPressed(const bool b) {mThrustRightKeyPressed=b;}
bool getBrakeLeftKeyPressed() const {return mBrakeLeftKeyPressed;}
bool getBrakeRightKeyPressed() const {return mBrakeRightKeyPressed;}
bool getThrustLeftKeyPressed() const {return mThrustLeftKeyPressed;}
bool getThrustRightKeyPressed() const {return mThrustRightKeyPressed;}
//Gamepad driving inputs (car + tank)
void setAccel(const PxF32 f) {mAccel=f;}
void setGearUp(const bool b) {mGearup=b;}
void setGearDown(const bool b) {mGeardown=b;}
PxF32 getAccel() const {return mAccel;}
bool getGearUp() const {return mGearup;}
bool getGearDown() const {return mGeardown;}
//Gamepad driving inputs (car only)
void setBrake(const PxF32 f) {mBrake=f;}
void setSteer(const PxF32 f) {mSteer=f;}
void setHandbrake(const bool b) {mHandbrake=b;}
PxF32 getBrake() const {return mBrake;}
PxF32 getSteer() const {return mSteer;}
bool getHandbrake() const {return mHandbrake;}
//Gamepad driving inputs (tank only)
void setThrustLeft(const PxF32 f) {mThrustLeft=f;}
void setThrustRight(const PxF32 f) {mThrustRight=f;}
PxF32 getThrustLeft() const {return mThrustLeft;}
PxF32 getThrustRight() const {return mThrustRight;}
void setBrakeLeft(const PxF32 f) {mBrakeLeft=f;}
void setBrakeRight(const PxF32 f) {mBrakeRight=f;}
PxF32 getBrakeLeft() const {return mBrakeLeft;}
PxF32 getBrakeRight() const {return mBrakeRight;}
private:
//Camera inputs.
PxF32 mCameraRotateInputY;
PxF32 mCameraRotateInputZ;
//keyboard inputs (car and tank)
bool mAccelKeyPressed;
bool mGearUpKeyPressed;
bool mGearDownKeyPressed;
//keyboard inputs (car only)
bool mBrakeKeyPressed;
bool mHandbrakeKeyPressed;
bool mSteerLeftKeyPressed;
bool mSteerRightKeyPressed;
//keyboard inputs (tank only)
bool mBrakeLeftKeyPressed;
bool mBrakeRightKeyPressed;
bool mThrustLeftKeyPressed;
bool mThrustRightKeyPressed;
//gamepad inputs (car and tank)
PxF32 mAccel;
bool mGearup;
bool mGeardown;
//gamepad inputs (car only)
PxF32 mBrake;
PxF32 mSteer;
bool mHandbrake;
//gamepad inputs (tank only)
PxF32 mThrustLeft;
PxF32 mThrustRight;
PxF32 mBrakeLeft;
PxF32 mBrakeRight;
};
#endif //SAMPLE_VEHICLE_CONTROL_INPUTS_H

View File

@ -0,0 +1,91 @@
//
// 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 "SampleVehicle_GameLogic.h"
void SampleVehicleWayPoints::getNextWayPointsAndLineDirs(PxU32& numPoints, PxVec3& v0, PxVec3& v1, PxVec3& v2, PxVec3& w0, PxVec3& w1, PxVec3& w2) const
{
numPoints=0;
if((mProgress+1) < mNumWayPoints)
{
v0=mWayPoints[mProgress+1].p;
w0=mWayPoints[mProgress+1].q.getBasisVector0();
numPoints++;
if((mProgress+2) < mNumWayPoints)
{
v1=mWayPoints[mProgress+2].p;
w1=mWayPoints[mProgress+2].q.getBasisVector0();
numPoints++;
if((mProgress+3) < mNumWayPoints)
{
v2=mWayPoints[mProgress+3].p;
w2=mWayPoints[mProgress+3].q.getBasisVector0();
numPoints++;
}
}
}
}
#define LINEWIDTH 8
#define LINEDISTANCE2 3*3
void SampleVehicleWayPoints::update(const PxTransform& playerTransform, const PxF32 timestep)
{
//Increment the elapsed time
mTimeElapsed+=timestep;
//Work out the point on the crossing line of the next way-point that is closest to the player.
const PxTransform& nextWayPoint=mWayPoints[mProgress+1];
const PxVec3 v=nextWayPoint.p;
const PxVec3 w=nextWayPoint.q.getBasisVector0();
const PxVec3 p=playerTransform.p;
const PxVec3 pv=p-v;
const PxF32 t=pv.dot(w);
//Test if the player's position is inside the width of the line crossing the next way-point.
if(PxAbs(t) < LINEWIDTH)
{
//Now test if the shortest distance to the next crossing line is smaller than a threshold.
const PxVec3 linePos=v+w*t;
const PxVec3 diff=p-linePos;
const PxF32 dist2=diff.magnitudeSquared();
if(dist2<LINEDISTANCE2)
{
mProgress++;
}
}
if(mProgress == mNumWayPoints-1)
{
mMinTimeElapsed=PxMin(mTimeElapsed, mMinTimeElapsed);
mTimeElapsed=0;
mProgress=0;
}
}

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 SAMPLE_VEHICLE_GAME_LOGIC_H
#define SAMPLE_VEHICLE_GAME_LOGIC_H
#include "common/PxPhysXCommonConfig.h"
#include "foundation/PxTransform.h"
using namespace physx;
class SampleVehicleWayPoints
{
public:
SampleVehicleWayPoints()
: mWayPoints(NULL),
mNumWayPoints(0),
mProgress(0),
mTimeElapsed(0),
mMinTimeElapsed(100000)
{
}
~SampleVehicleWayPoints()
{
}
//Setup.
void setWayPoints(const PxTransform* wayPoints, const PxU32 numWayPoints)
{
mWayPoints=wayPoints;
mNumWayPoints=numWayPoints;
}
//Update.
void update(const PxTransform& playerTransform, const PxF32 timestep);
//Imagine we are starting the lap again.
PxTransform setBackAtStart()
{
mTimeElapsed=0;
mProgress=0;
return mWayPoints[0];
}
//Get the next three points and the crossing line of each way-point.
void getNextWayPointsAndLineDirs(PxU32& numPoints, PxVec3& v0, PxVec3& v1, PxVec3& v2, PxVec3& w0, PxVec3& w1, PxVec3& w2) const;
//Get lap time and best lap time.
PxF32 getTimeElapsed() const {return mTimeElapsed;}
PxF32 getMinTimeElapsed() const {return mMinTimeElapsed;}
//Get the transform to reset the car at the last passed way-point.
PxTransform getResetTransform() const {return mWayPoints[mProgress];}
private:
//Array of way points.
const PxTransform* mWayPoints;
PxU32 mNumWayPoints;
//Progress and time elapsed.
PxU32 mProgress;
PxF32 mTimeElapsed;
PxF32 mMinTimeElapsed;
};
#endif //SAMPLE_VEHICLE_GAME_LOGIC_H

View File

@ -0,0 +1,90 @@
//
// 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 "SampleVehicle_SceneQuery.h"
#include "vehicle/PxVehicleSDK.h"
#include "PxFiltering.h"
#include "PsFoundation.h"
#include "PsUtilities.h"
#define CHECK_MSG(exp, msg) (!!(exp) || (physx::shdfnd::getFoundation().error(physx::PxErrorCode::eINVALID_PARAMETER, __FILE__, __LINE__, msg), 0) )
#define SIZEALIGN16(size) (((unsigned)(size)+15)&((unsigned)(~15)));
void SampleVehicleSetupDrivableShapeQueryFilterData(PxFilterData* qryFilterData)
{
CHECK_MSG(0==qryFilterData->word3, "word3 is reserved for filter data for vehicle raycast queries");
qryFilterData->word3 = (PxU32)SAMPLEVEHICLE_DRIVABLE_SURFACE;
}
void SampleVehicleSetupNonDrivableShapeQueryFilterData(PxFilterData* qryFilterData)
{
CHECK_MSG(0==qryFilterData->word3, "word3 is reserved for filter data for vehicle raycast queries");
qryFilterData->word3 = (PxU32)SAMPLEVEHICLE_UNDRIVABLE_SURFACE;
}
void SampleVehicleSetupVehicleShapeQueryFilterData(PxFilterData* qryFilterData)
{
CHECK_MSG(0==qryFilterData->word3, "word3 is reserved for filter data for vehicle raycast queries");
qryFilterData->word3 = (PxU32)SAMPLEVEHICLE_UNDRIVABLE_SURFACE;
}
SampleVehicleSceneQueryData* SampleVehicleSceneQueryData::allocate(const PxU32 maxNumWheels)
{
const PxU32 size0 = SIZEALIGN16(sizeof(SampleVehicleSceneQueryData));
const PxU32 size1 = SIZEALIGN16(sizeof(PxRaycastQueryResult)*maxNumWheels);
const PxU32 size2 = SIZEALIGN16(sizeof(PxRaycastHit)*maxNumWheels);
const PxU32 size = size0 + size1 + size2;
SampleVehicleSceneQueryData* sqData = (SampleVehicleSceneQueryData*)PX_ALLOC(size, "PxVehicleNWSceneQueryData");
sqData->init();
PxU8* ptr = (PxU8*) sqData;
ptr += size0;
sqData->mSqResults = (PxRaycastQueryResult*)ptr;
sqData->mNbSqResults = maxNumWheels;
ptr += size1;
sqData->mSqHitBuffer = (PxRaycastHit*)ptr;
ptr += size2;
sqData->mNumQueries = maxNumWheels;
return sqData;
}
void SampleVehicleSceneQueryData::free()
{
PX_FREE(this);
}
PxBatchQuery* SampleVehicleSceneQueryData::setUpBatchedSceneQuery(PxScene* scene)
{
PxBatchQueryDesc sqDesc(mNbSqResults, 0, 0);
sqDesc.queryMemory.userRaycastResultBuffer = mSqResults;
sqDesc.queryMemory.userRaycastTouchBuffer = mSqHitBuffer;
sqDesc.queryMemory.raycastTouchBufferSize = mNumQueries;
sqDesc.preFilterShader = mPreFilterShader;
return scene->createBatchQuery(sqDesc);
}

View File

@ -0,0 +1,132 @@
//
// 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 SAMPLEVEHICLE_UTILSCENEQUERY_H
#define SAMPLEVEHICLE_UTILSCENEQUERY_H
#include "common/PxPhysXCommonConfig.h"
#include "vehicle/PxVehicleSDK.h"
#include "foundation/PxPreprocessor.h"
#include "PxScene.h"
#include "PxBatchQueryDesc.h"
using namespace physx;
//Make sure that suspension raycasts only consider shapes flagged as drivable that don't belong to the owner vehicle.
enum
{
SAMPLEVEHICLE_DRIVABLE_SURFACE = 0xffff0000,
SAMPLEVEHICLE_UNDRIVABLE_SURFACE = 0x0000ffff
};
static PxQueryHitType::Enum SampleVehicleWheelRaycastPreFilter(
PxFilterData filterData0,
PxFilterData filterData1,
const void* constantBlock, PxU32 constantBlockSize,
PxHitFlags& queryFlags)
{
//filterData0 is the vehicle suspension raycast.
//filterData1 is the shape potentially hit by the raycast.
PX_UNUSED(queryFlags);
PX_UNUSED(constantBlockSize);
PX_UNUSED(constantBlock);
PX_UNUSED(filterData0);
return ((0 == (filterData1.word3 & SAMPLEVEHICLE_DRIVABLE_SURFACE)) ? PxQueryHitType::eNONE : PxQueryHitType::eBLOCK);
}
//Set up query filter data so that vehicles can drive on shapes with this filter data.
//Note that we have reserved word3 of the PxFilterData for vehicle raycast query filtering.
void SampleVehicleSetupDrivableShapeQueryFilterData(PxFilterData* qryFilterData);
//Set up query filter data so that vehicles cannot drive on shapes with this filter data.
//Note that we have reserved word3 of the PxFilterData for vehicle raycast query filtering.
void SampleVehicleSetupNonDrivableShapeQueryFilterData(PxFilterData* qryFilterData);
//Set up query filter data for the shapes of a vehicle to ensure that vehicles cannot drive on themselves
//but can drive on the shapes of other vehicles.
//Note that we have reserved word3 of the PxFilterData for vehicle raycast query filtering.
void SampleVehicleSetupVehicleShapeQueryFilterData(PxFilterData* qryFilterData);
//Data structure for quick setup of scene queries for suspension raycasts.
class SampleVehicleSceneQueryData
{
public:
//Allocate scene query data for up to maxNumWheels suspension raycasts.
static SampleVehicleSceneQueryData* allocate(const PxU32 maxNumWheels);
//Free allocated buffer for scene queries of suspension raycasts.
void free();
//Create a PxBatchQuery instance that will be used as a single batched raycast of multiple suspension lines of multiple vehicles
PxBatchQuery* setUpBatchedSceneQuery(PxScene* scene);
//Get the buffer of scene query results that will be used by PxVehicleNWSuspensionRaycasts
PxRaycastQueryResult* getRaycastQueryResultBuffer() {return mSqResults;}
//Get the number of scene query results that have been allocated for use by PxVehicleNWSuspensionRaycasts
PxU32 getRaycastQueryResultBufferSize() const {return mNumQueries;}
//Set the pre-filter shader
void setPreFilterShader(PxBatchQueryPreFilterShader preFilterShader) {mPreFilterShader=preFilterShader;}
private:
//One result for each wheel.
PxRaycastQueryResult* mSqResults;
PxU32 mNbSqResults;
//One hit for each wheel.
PxRaycastHit* mSqHitBuffer;
//Filter shader used to filter drivable and non-drivable surfaces
PxBatchQueryPreFilterShader mPreFilterShader;
//Maximum number of suspension raycasts that can be supported by the allocated buffers
//assuming a single query and hit per suspension line.
PxU32 mNumQueries;
void init()
{
mPreFilterShader=SampleVehicleWheelRaycastPreFilter;
}
SampleVehicleSceneQueryData()
{
init();
}
~SampleVehicleSceneQueryData()
{
}
};
#endif //SAMPLEVEHICLE_UTILSCENEQUERY_H

View File

@ -0,0 +1,840 @@
//
// 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 "SampleVehicle_VehicleController.h"
#include "PhysXSample.h"
#include "vehicle/PxVehicleDrive4W.h"
#include "vehicle/PxVehicleDriveNW.h"
#include "vehicle/PxVehicleUtilControl.h"
#include "vehicle/PxVehicleUtil.h"
using namespace SampleRenderer;
using namespace SampleFramework;
PxVehicleKeySmoothingData gKeySmoothingData=
{
{
3.0f, //rise rate eANALOG_INPUT_ACCEL
3.0f, //rise rate eANALOG_INPUT_BRAKE
10.0f, //rise rate eANALOG_INPUT_HANDBRAKE
2.5f, //rise rate eANALOG_INPUT_STEER_LEFT
2.5f, //rise rate eANALOG_INPUT_STEER_RIGHT
},
{
5.0f, //fall rate eANALOG_INPUT__ACCEL
5.0f, //fall rate eANALOG_INPUT__BRAKE
10.0f, //fall rate eANALOG_INPUT__HANDBRAKE
5.0f, //fall rate eANALOG_INPUT_STEER_LEFT
5.0f //fall rate eANALOG_INPUT_STEER_RIGHT
}
};
PxVehiclePadSmoothingData gCarPadSmoothingData=
{
{
6.0f, //rise rate eANALOG_INPUT_ACCEL
6.0f, //rise rate eANALOG_INPUT_BRAKE
12.0f, //rise rate eANALOG_INPUT_HANDBRAKE
2.5f, //rise rate eANALOG_INPUT_STEER_LEFT
2.5f, //rise rate eANALOG_INPUT_STEER_RIGHT
},
{
10.0f, //fall rate eANALOG_INPUT_ACCEL
10.0f, //fall rate eANALOG_INPUT_BRAKE
12.0f, //fall rate eANALOG_INPUT_HANDBRAKE
5.0f, //fall rate eANALOG_INPUT_STEER_LEFT
5.0f //fall rate eANALOG_INPUT_STEER_RIGHT
}
};
PxF32 gSteerVsForwardSpeedData[2*8]=
{
0.0f, 0.75f,
5.0f, 0.75f,
30.0f, 0.125f,
120.0f, 0.1f,
PX_MAX_F32, PX_MAX_F32,
PX_MAX_F32, PX_MAX_F32,
PX_MAX_F32, PX_MAX_F32,
PX_MAX_F32, PX_MAX_F32
};
PxFixedSizeLookupTable<8> gSteerVsForwardSpeedTable(gSteerVsForwardSpeedData,4);
//Tank smoothing data.
PxVehiclePadSmoothingData gTankPadSmoothingData=
{
{
6.0f, //rise rate eTANK_ANALOG_INPUT_ACCEL
6.0f, //rise rate eTANK_ANALOG_INPUT_BRAKE_LEFT
6.0f, //rise rate eTANK_ANALOG_INPUT_BRAKE_RIGHT
2.5f, //rise rate eTANK_ANALOG_INPUT_THRUST_LEFT
2.5f, //rise rate eTANK_ANALOG_INPUT_THRUST_RIGHT
},
{
10.0f, //fall rate eTANK_ANALOG_INPUT_ACCEL
10.0f, //fall rate eTANK_ANALOG_INPUT_BRAKE_LEFT
10.0f, //fall rate eTANK_ANALOG_INPUT_BRAKE_RIGHT
5.0f, //fall rate eTANK_ANALOG_INPUT_THRUST_LEFT
5.0f //fall rate eTANK_ANALOG_INPUT_THRUST_RIGHT
}
};
///////////////////////////////////////////////////////////////////////////////
SampleVehicle_VehicleController::SampleVehicle_VehicleController()
{
clear();
}
SampleVehicle_VehicleController::~SampleVehicle_VehicleController()
{
}
void SampleVehicle_VehicleController::clear()
{
mKeyPressedAccel = false;
mKeyPressedGearUp = false;
mKeyPressedGearDown = false;
mKeyPressedBrake = false;
mKeyPressedHandbrake = false;
mKeyPressedSteerLeft = false;
mKeyPressedSteerRight = false;
mKeyPressedThrustLeft = false;
mKeyPressedThrustRight = false;
mKeyPressedBrakeLeft = false;
mKeyPressedBrakeRight = false;
mGamepadAccel = 0.0f;
mGamepadGearup = false;
mGamepadGeardown = false;
mGamepadCarBrake = 0.0f;
mGamepadCarSteer = 0.0f;
mGamepadCarHandbrake = false;
mTankThrustLeft = 0.0f;
mTankThrustRight = 0.0f;
mTankBrakeLeft = 0.0f;
mTankBrakeRight = 0.0f;
mRecord = false;
mReplay = false;
mNumSamples = 0;
mNumRecordedSamples = 0;
mUseKeyInputs = true;
mToggleAutoGears = false;
mIsMovingForwardSlowly = true;
mInReverseMode = false;
}
/*
bool SampleVehicle_VehicleController::processAutoReverse
(const PxF32 timestep, const bool isInAir, const PxF32 forwardSpeed, const PxF32 sidewaysSpeed, const PxVehicleDriveTankRawInputData& rawInputData)
{
//Keyboard controls for tank not implemented yet.
bool brakeLeft,brakeRight,accelLeft,accelRight;
if(mUseKeyInputs)
{
//Keyboard controls for tank not implemented yet.
brakeLeft=false;
brakeRight=false;
accelLeft=false;
accelRight=false;
}
else if(PxVehicleDriveTank::eDRIVE_MODEL_STANDARD==rawInputData.getDriveModel())
{
brakeLeft = mInReverseMode ? rawInputData.getAnalogLeftThrust() > 0 : rawInputData.getAnalogLeftBrake() > 0.0f;
brakeRight = mInReverseMode ? rawInputData.getAnalogRightThrust() > 0 : rawInputData.getAnalogRightBrake() > 0.0f;
accelLeft = mInReverseMode ? rawInputData.getAnalogLeftBrake() > 0 : rawInputData.getAnalogLeftThrust() > 0.0f;
accelRight = mInReverseMode ? rawInputData.getAnalogRightBrake() > 0 : rawInputData.getAnalogRightThrust() > 0.0f;
}
else
{
//Not much point in auto-reverse for tanks that can just spin both wheels backwards.
return false;
}
//If the car has been brought to rest by pressing the brake then raise a flag.
bool justRaisedFlag=false;
if(brakeLeft && brakeRight && !mAtRestUnderBraking)
{
if(!isInAir && forwardSpeed < THRESHOLD_FORWARD_SPEED && sidewaysSpeed < THRESHOLD_SIDEWAYS_SPEED)
{
justRaisedFlag=true;
mAtRestUnderBraking = true;
mTimeElapsedSinceAtRestUnderBraking = 0.0f;
}
}
//If the flag is raised and the player pressed accelerate then lower the flag.
if(mAtRestUnderBraking && (accelLeft || accelRight))
{
mAtRestUnderBraking = false;
mTimeElapsedSinceAtRestUnderBraking = 0.0f;
}
//If the flag is raised and the player doesn't press brake then increment the timer.
if(!brakeLeft && !brakeRight && mAtRestUnderBraking && !justRaisedFlag)
{
mTimeElapsedSinceAtRestUnderBraking += timestep;
}
//If the flag is raised and the player pressed brake again then switch auto-reverse.
if(brakeLeft && brakeRight && mAtRestUnderBraking && !justRaisedFlag && mTimeElapsedSinceAtRestUnderBraking > 0.0f)
{
mAtRestUnderBraking = false;
mTimeElapsedSinceAtRestUnderBraking = 0.0f;
return true;
}
return false;
}
*/
void SampleVehicle_VehicleController::processRawInputs
(const PxF32 dtime, const bool useAutoGears, PxVehicleDrive4WRawInputData& rawInputData)
{
// Keyboard
{
if(mRecord)
{
if(mNumSamples<MAX_NUM_RECORD_REPLAY_SAMPLES)
{
mKeyboardAccelValues[mNumSamples] = mKeyPressedAccel;
mKeyboardBrakeValues[mNumSamples] = mKeyPressedBrake;
mKeyboardHandbrakeValues[mNumSamples] = mKeyPressedHandbrake;
mKeyboardSteerLeftValues[mNumSamples] = mKeyPressedSteerLeft;
mKeyboardSteerRightValues[mNumSamples] = mKeyPressedSteerRight;
mKeyboardGearupValues[mNumSamples] = mKeyPressedGearUp;
mKeyboardGeardownValues[mNumSamples] = mKeyPressedGearDown;
}
}
else if(mReplay)
{
if(mNumSamples<mNumRecordedSamples)
{
mKeyPressedAccel = mKeyboardAccelValues[mNumSamples];
mKeyPressedBrake = mKeyboardBrakeValues[mNumSamples];
mKeyPressedHandbrake = mKeyboardHandbrakeValues[mNumSamples];
mKeyPressedSteerLeft = mKeyboardSteerLeftValues[mNumSamples];
mKeyPressedSteerRight = mKeyboardSteerRightValues[mNumSamples];
mKeyPressedGearUp = mKeyboardGearupValues[mNumSamples];
mKeyPressedGearDown = mKeyboardGeardownValues[mNumSamples];
}
}
rawInputData.setDigitalAccel(mKeyPressedAccel);
rawInputData.setDigitalBrake(mKeyPressedBrake);
rawInputData.setDigitalHandbrake(mKeyPressedHandbrake);
rawInputData.setDigitalSteerLeft(mKeyPressedSteerLeft);
rawInputData.setDigitalSteerRight(mKeyPressedSteerRight);
rawInputData.setGearUp(mKeyPressedGearUp);
rawInputData.setGearDown(mKeyPressedGearDown);
mUseKeyInputs=
(mKeyPressedAccel || mKeyPressedBrake || mKeyPressedHandbrake ||
mKeyPressedSteerLeft || mKeyPressedSteerRight ||
mKeyPressedGearUp || mKeyPressedGearDown);
}
// Gamepad
{
if(mRecord)
{
if(mNumSamples<MAX_NUM_RECORD_REPLAY_SAMPLES)
{
mGamepadAccelValues[mNumSamples] = mGamepadAccel;
mGamepadCarBrakeValues[mNumSamples] = mGamepadCarBrake;
mGamepadCarSteerValues[mNumSamples] = mGamepadCarSteer;
mGamepadGearupValues[mNumSamples] = mGamepadGearup;
mGamepadGeardownValues[mNumSamples] = mGamepadGeardown;
mGamepadCarHandbrakeValues[mNumSamples] = mGamepadCarHandbrake;
}
}
else if(mReplay)
{
if(mNumSamples<mNumRecordedSamples)
{
mGamepadAccel = mGamepadAccelValues[mNumSamples];
mGamepadCarBrake = mGamepadCarBrakeValues[mNumSamples];
mGamepadCarSteer = mGamepadCarSteerValues[mNumSamples];
mGamepadGearup = mGamepadGearupValues[mNumSamples];
mGamepadGeardown = mGamepadGeardownValues[mNumSamples];
mGamepadCarHandbrake = mGamepadCarHandbrakeValues[mNumSamples];
}
}
if(mGamepadAccel<0.0f || mGamepadAccel>1.01f)
getSampleErrorCallback().reportError(PxErrorCode::eINTERNAL_ERROR, "Illegal accel value from gamepad", __FILE__, __LINE__);
if(mGamepadCarBrake<0.0f || mGamepadCarBrake>1.01f)
getSampleErrorCallback().reportError(PxErrorCode::eINTERNAL_ERROR, "Illegal brake value from gamepad", __FILE__, __LINE__);
if(PxAbs(mGamepadCarSteer)>1.01f)
getSampleErrorCallback().reportError(PxErrorCode::eINTERNAL_ERROR, "Illegal steer value from gamepad", __FILE__, __LINE__);
if(mUseKeyInputs && ((mGamepadAccel+mGamepadCarBrake+mGamepadCarSteer)!=0.0f || mGamepadGearup || mGamepadGeardown || mGamepadCarHandbrake))
{
mUseKeyInputs=false;
}
if(!mUseKeyInputs)
{
rawInputData.setAnalogAccel(mGamepadAccel);
rawInputData.setAnalogBrake(mGamepadCarBrake);
rawInputData.setAnalogHandbrake(mGamepadCarHandbrake ? 1.0f : 0.0f);
rawInputData.setAnalogSteer(mGamepadCarSteer);
rawInputData.setGearUp(mGamepadGearup);
rawInputData.setGearDown(mGamepadGeardown);
}
}
if(useAutoGears && (rawInputData.getGearDown() || rawInputData.getGearUp()))
{
rawInputData.setGearDown(false);
rawInputData.setGearUp(false);
}
mNumSamples++;
}
void SampleVehicle_VehicleController::processRawInputs
(const PxF32 dtime, const bool useAutoGears, PxVehicleDriveTankRawInputData& rawInputData)
{
// Keyboard
//Keyboard controls for tank not implemented yet.
{
/*
if(mRecord)
{
if(mNumSamples<MAX_NUM_RECORD_REPLAY_SAMPLES)
{
mKeyboardAccelValues[mNumSamples] = mAccelKeyPressed;
mKeyboardBrakeValues[mNumSamples] = mBrakeKeyPressed;
mKeyboardHandbrakeValues[mNumSamples] = mHandbrakeKeyPressed;
mKeyboardSteerLeftValues[mNumSamples] = mSteerLeftKeyPressed;
mKeyboardSteerRightValues[mNumSamples] = mSteerRightKeyPressed;
mKeyboardGearupValues[mNumSamples] = mGearUpKeyPressed;
mKeyboardGeardownValues[mNumSamples] = mGearDownKeyPressed;
}
}
else if(mReplay)
{
if(mNumSamples<mNumRecordedSamples)
{
mAccelKeyPressed = mKeyboardAccelValues[mNumSamples];
mBrakeKeyPressed = mKeyboardBrakeValues[mNumSamples];
mHandbrakeKeyPressed = mKeyboardHandbrakeValues[mNumSamples];
mSteerLeftKeyPressed = mKeyboardSteerLeftValues[mNumSamples];
mSteerRightKeyPressed = mKeyboardSteerRightValues[mNumSamples];
mGearUpKeyPressed = mKeyboardGearupValues[mNumSamples];
mGearDownKeyPressed = mKeyboardGeardownValues[mNumSamples];
}
}
*/
rawInputData.setDigitalAccel(mKeyPressedAccel);
rawInputData.setDigitalLeftThrust(mKeyPressedThrustLeft);
rawInputData.setDigitalRightThrust(mKeyPressedThrustRight);
rawInputData.setDigitalLeftBrake(mKeyPressedBrakeLeft);
rawInputData.setDigitalRightBrake(mKeyPressedBrakeRight);
rawInputData.setGearUp(mKeyPressedGearUp);
rawInputData.setGearDown(mKeyPressedGearDown);
mUseKeyInputs=
(mKeyPressedAccel || mKeyPressedThrustLeft || mKeyPressedThrustRight ||
mKeyPressedBrakeLeft || mKeyPressedBrakeRight ||
mKeyPressedGearUp || mKeyPressedGearDown);
}
// Gamepad
{
if(mRecord)
{
if(mNumSamples<MAX_NUM_RECORD_REPLAY_SAMPLES)
{
mGamepadAccelValues[mNumSamples] = mGamepadAccel;
mGamepadTankThrustLeftValues[mNumSamples] = mTankThrustLeft;
mGamepadTankThrustRightValues[mNumSamples] = mTankThrustRight;
mGamepadGearupValues[mNumSamples] = mGamepadGearup;
mGamepadGeardownValues[mNumSamples] = mGamepadGeardown;
}
}
else if(mReplay)
{
if(mNumSamples<mNumRecordedSamples)
{
mGamepadAccel = mGamepadAccelValues[mNumSamples];
mTankThrustLeft = mGamepadTankThrustLeftValues[mNumSamples];
mTankThrustRight= mGamepadTankThrustRightValues[mNumSamples];
mGamepadGearup = mGamepadGearupValues[mNumSamples];
mGamepadGeardown = mGamepadGeardownValues[mNumSamples];
}
}
if(mGamepadAccel<0.0f || mGamepadAccel>1.01f)
getSampleErrorCallback().reportError(PxErrorCode::eINTERNAL_ERROR, "Illegal accel value from gamepad", __FILE__, __LINE__);
if(mTankThrustLeft<-1.01f || mTankThrustLeft>1.01f)
getSampleErrorCallback().reportError(PxErrorCode::eINTERNAL_ERROR, "Illegal brake value from gamepad", __FILE__, __LINE__);
if(mTankThrustRight<-1.01f || mTankThrustRight>1.01f)
getSampleErrorCallback().reportError(PxErrorCode::eINTERNAL_ERROR, "Illegal steer value from gamepad", __FILE__, __LINE__);
if(mUseKeyInputs && ((mGamepadAccel+mTankThrustLeft+mTankThrustRight)!=0.0f || mGamepadGearup || mGamepadGeardown))
{
mUseKeyInputs=false;
}
if(!mUseKeyInputs)
{
rawInputData.setAnalogAccel(mGamepadAccel);
rawInputData.setAnalogLeftThrust(mTankThrustLeft);
rawInputData.setAnalogRightThrust(mTankThrustRight);
rawInputData.setAnalogLeftBrake(mTankBrakeLeft);
rawInputData.setAnalogRightBrake(mTankBrakeRight);
rawInputData.setGearUp(mGamepadGearup);
rawInputData.setGearDown(mGamepadGeardown);
}
}
if(useAutoGears && (rawInputData.getGearDown() || rawInputData.getGearUp()))
{
rawInputData.setGearDown(false);
rawInputData.setGearUp(false);
}
mNumSamples++;
}
#define THRESHOLD_FORWARD_SPEED (0.1f)
#define THRESHOLD_SIDEWAYS_SPEED (0.2f)
#define THRESHOLD_ROLLING_BACKWARDS_SPEED (0.1f)
void SampleVehicle_VehicleController::processAutoReverse
(const PxVehicleWheels& focusVehicle, const PxVehicleDriveDynData& driveDynData, const PxVehicleWheelQueryResult& vehicleWheelQueryResults,
const PxVehicleDrive4WRawInputData& carRawInputs,
bool& toggleAutoReverse, bool& newIsMovingForwardSlowly) const
{
newIsMovingForwardSlowly = false;
toggleAutoReverse = false;
if(driveDynData.getUseAutoGears())
{
//If the car is travelling very slowly in forward gear without player input and the player subsequently presses the brake then we want the car to go into reverse gear
//If the car is travelling very slowly in reverse gear without player input and the player subsequently presses the accel then we want the car to go into forward gear
//If the car is in forward gear and is travelling backwards then we want to automatically put the car into reverse gear.
//If the car is in reverse gear and is travelling forwards then we want to automatically put the car into forward gear.
//(If the player brings the car to rest with the brake the player needs to release the brake then reapply it
//to indicate they want to toggle between forward and reverse.)
const bool prevIsMovingForwardSlowly=mIsMovingForwardSlowly;
bool isMovingForwardSlowly=false;
bool isMovingBackwards=false;
const bool isInAir = PxVehicleIsInAir(vehicleWheelQueryResults);
if(!isInAir)
{
bool accelRaw,brakeRaw,handbrakeRaw;
if(mUseKeyInputs)
{
accelRaw=carRawInputs.getDigitalAccel();
brakeRaw=carRawInputs.getDigitalBrake();
handbrakeRaw=carRawInputs.getDigitalHandbrake();
}
else
{
accelRaw=carRawInputs.getAnalogAccel() > 0 ? true : false;
brakeRaw=carRawInputs.getAnalogBrake() > 0 ? true : false;
handbrakeRaw=carRawInputs.getAnalogHandbrake() > 0 ? true : false;
}
const PxF32 forwardSpeed = focusVehicle.computeForwardSpeed();
const PxF32 forwardSpeedAbs = PxAbs(forwardSpeed);
const PxF32 sidewaysSpeedAbs = PxAbs(focusVehicle.computeSidewaysSpeed());
const PxU32 currentGear = driveDynData.getCurrentGear();
const PxU32 targetGear = driveDynData.getTargetGear();
//Check if the car is rolling against the gear (backwards in forward gear or forwards in reverse gear).
if(PxVehicleGearsData::eFIRST == currentGear && forwardSpeed < -THRESHOLD_ROLLING_BACKWARDS_SPEED)
{
isMovingBackwards = true;
}
else if(PxVehicleGearsData::eREVERSE == currentGear && forwardSpeed > THRESHOLD_ROLLING_BACKWARDS_SPEED)
{
isMovingBackwards = true;
}
//Check if the car is moving slowly.
if(forwardSpeedAbs < THRESHOLD_FORWARD_SPEED && sidewaysSpeedAbs < THRESHOLD_SIDEWAYS_SPEED)
{
isMovingForwardSlowly=true;
}
//Now work if we need to toggle from forwards gear to reverse gear or vice versa.
if(isMovingBackwards)
{
if(!accelRaw && !brakeRaw && !handbrakeRaw && (currentGear == targetGear))
{
//The car is rolling against the gear and the player is doing nothing to stop this.
toggleAutoReverse = true;
}
}
else if(prevIsMovingForwardSlowly && isMovingForwardSlowly)
{
if((currentGear > PxVehicleGearsData::eNEUTRAL) && brakeRaw && !accelRaw && (currentGear == targetGear))
{
//The car was moving slowly in forward gear without player input and is now moving slowly with player input that indicates the
//player wants to switch to reverse gear.
toggleAutoReverse = true;
}
else if(currentGear == PxVehicleGearsData::eREVERSE && accelRaw && !brakeRaw && (currentGear == targetGear))
{
//The car was moving slowly in reverse gear without player input and is now moving slowly with player input that indicates the
//player wants to switch to forward gear.
toggleAutoReverse = true;
}
}
//If the car was brought to rest through braking then the player needs to release the brake then reapply
//to indicate that the gears should toggle between reverse and forward.
if(isMovingForwardSlowly && !brakeRaw && !accelRaw && !handbrakeRaw)
{
newIsMovingForwardSlowly = true;
}
}
}
}
void SampleVehicle_VehicleController::processAutoReverse
(const PxVehicleWheels& focusVehicle, const PxVehicleDriveDynData& driveDynData, const PxVehicleWheelQueryResult& vehicleWheelQueryResults,
const PxVehicleDriveTankRawInputData& tankRawInputs,
bool& toggleAutoReverse, bool& newIsMovingForwardSlowly) const
{
newIsMovingForwardSlowly = false;
toggleAutoReverse = false;
if(driveDynData.getUseAutoGears())
{
//If the car is travelling very slowly in forward gear without player input and the player subsequently presses the brake then we want the car to go into reverse gear
//If the car is travelling very slowly in reverse gear without player input and the player subsequently presses the accel then we want the car to go into forward gear
//If the car is in forward gear and is travelling backwards then we want to automatically put the car into reverse gear.
//If the car is in reverse gear and is travelling forwards then we want to automatically put the car into forward gear.
//(If the player brings the car to rest with the brake the player needs to release the brake then reapply it
//to indicate they want to toggle between forward and reverse.)
const bool prevIsMovingForwardSlowly=mIsMovingForwardSlowly;
bool isMovingForwardSlowly=false;
bool isMovingBackwards=false;
const bool isInAir = PxVehicleIsInAir(vehicleWheelQueryResults);
if(!isInAir)
{
bool accelLeft,accelRight,brakeLeft,brakeRight;
if(mUseKeyInputs)
{
accelLeft=tankRawInputs.getDigitalLeftThrust();
accelRight=tankRawInputs.getDigitalRightThrust();
brakeLeft=tankRawInputs.getDigitalLeftBrake();
brakeRight=tankRawInputs.getDigitalRightBrake();
}
else
{
accelLeft = tankRawInputs.getAnalogLeftThrust() > 0 ? true : false;
accelRight = tankRawInputs.getAnalogRightThrust() > 0 ? true : false;
brakeLeft = tankRawInputs.getAnalogLeftBrake() > 0 ? true : false;
brakeRight = tankRawInputs.getAnalogRightBrake() > 0 ? true : false;
/*
if(accelLeft && accelLeft==accelRight && !brakeLeft && !brakeRight)
{
shdfnd::printFormatted("aligned accel\n");
}
if(brakeLeft && brakeLeft==brakeRight && !accelLeft && !accelRight)
{
shdfnd::printFormatted("aligned brake\n");
}
*/
}
const PxF32 forwardSpeed = focusVehicle.computeForwardSpeed();
const PxF32 forwardSpeedAbs = PxAbs(forwardSpeed);
const PxF32 sidewaysSpeedAbs = PxAbs(focusVehicle.computeSidewaysSpeed());
const PxU32 currentGear = driveDynData.getCurrentGear();
const PxU32 targetGear = driveDynData.getTargetGear();
//Check if the car is rolling against the gear (backwards in forward gear or forwards in reverse gear).
if(PxVehicleGearsData::eFIRST == currentGear && forwardSpeed < -THRESHOLD_ROLLING_BACKWARDS_SPEED)
{
isMovingBackwards = true;
}
else if(PxVehicleGearsData::eREVERSE == currentGear && forwardSpeed > THRESHOLD_ROLLING_BACKWARDS_SPEED)
{
isMovingBackwards = true;
}
//Check if the car is moving slowly.
if(forwardSpeedAbs < THRESHOLD_FORWARD_SPEED && sidewaysSpeedAbs < THRESHOLD_SIDEWAYS_SPEED)
{
isMovingForwardSlowly=true;
}
//Now work if we need to toggle from forwards gear to reverse gear or vice versa.
if(isMovingBackwards)
{
if(!accelLeft && !accelRight && !brakeLeft && !brakeRight && (currentGear == targetGear))
{
//The car is rolling against the gear and the player is doing nothing to stop this.
toggleAutoReverse = true;
}
}
else if(prevIsMovingForwardSlowly && isMovingForwardSlowly)
{
if((currentGear > PxVehicleGearsData::eNEUTRAL) && brakeLeft && brakeRight && !accelLeft && !accelRight && (currentGear == targetGear))
{
//The car was moving slowly in forward gear without player input and is now moving slowly with player input that indicates the
//player wants to switch to reverse gear.
toggleAutoReverse = true;
}
else if(currentGear == PxVehicleGearsData::eREVERSE && accelLeft && accelRight && !brakeLeft && !brakeRight && (currentGear == targetGear))
{
//The car was moving slowly in reverse gear without player input and is now moving slowly with player input that indicates the
//player wants to switch to forward gear.
toggleAutoReverse = true;
}
}
//If the car was brought to rest through braking then the player needs to release the brake then reapply
//to indicate that the gears should toggle between reverse and forward.
if(isMovingForwardSlowly && (!brakeLeft || !brakeRight) && (!accelLeft || !accelRight))
{
newIsMovingForwardSlowly = true;
}
}
}
}
void SampleVehicle_VehicleController::update(const PxF32 timestep, const PxVehicleWheelQueryResult& vehicleWheelQueryResults, PxVehicleWheels& focusVehicle)
{
PxVehicleDriveDynData* driveDynData=NULL;
bool isTank=false;
PxVehicleDriveTankControlModel::Enum tankDriveModel=PxVehicleDriveTankControlModel::eSTANDARD;
switch(focusVehicle.getVehicleType())
{
case PxVehicleTypes::eDRIVE4W:
{
PxVehicleDrive4W& vehDrive4W=(PxVehicleDrive4W&)focusVehicle;
driveDynData=&vehDrive4W.mDriveDynData;
isTank=false;
}
break;
case PxVehicleTypes::eDRIVENW:
{
PxVehicleDriveNW& vehDriveNW=(PxVehicleDriveNW&)focusVehicle;
driveDynData=&vehDriveNW.mDriveDynData;
isTank=false;
}
break;
case PxVehicleTypes::eDRIVETANK:
{
PxVehicleDriveTank& vehDriveTank=(PxVehicleDriveTank&)focusVehicle;
driveDynData=&vehDriveTank.mDriveDynData;
isTank=true;
tankDriveModel=vehDriveTank.getDriveModel();
}
break;
default:
PX_ASSERT(false);
break;
}
//Toggle autogear flag
if(mToggleAutoGears)
{
driveDynData->toggleAutoGears();
mToggleAutoGears = false;
}
//Store raw inputs in replay stream if in recording mode.
//Set raw inputs from replay stream if in replay mode.
//Store raw inputs from active stream in handy arrays so we don't need to worry
//about which stream (live input or replay) is active.
//Work out if we are using keys or gamepad controls depending on which is being used
//(gamepad selected if both are being used).
PxVehicleDrive4WRawInputData carRawInputs;
PxVehicleDriveTankRawInputData tankRawInputs(tankDriveModel);
if(!isTank)
{
processRawInputs(timestep,driveDynData->getUseAutoGears(),carRawInputs);
}
else
{
processRawInputs(timestep,driveDynData->getUseAutoGears(),tankRawInputs);
}
//Work out if the car is to flip from reverse to forward gear or from forward gear to reverse.
bool toggleAutoReverse = false;
bool newIsMovingForwardSlowly = false;
if(!isTank)
{
processAutoReverse(focusVehicle, *driveDynData, vehicleWheelQueryResults, carRawInputs, toggleAutoReverse, newIsMovingForwardSlowly);
}
else
{
processAutoReverse(focusVehicle, *driveDynData, vehicleWheelQueryResults, tankRawInputs, toggleAutoReverse, newIsMovingForwardSlowly);
}
mIsMovingForwardSlowly = newIsMovingForwardSlowly;
//If the car is to flip gear direction then switch gear as appropriate.
if(toggleAutoReverse)
{
mInReverseMode = !mInReverseMode;
if(mInReverseMode)
{
driveDynData->forceGearChange(PxVehicleGearsData::eREVERSE);
}
else
{
driveDynData->forceGearChange(PxVehicleGearsData::eFIRST);
}
}
//If in reverse mode then swap the accel and brake.
if(mInReverseMode)
{
if(mUseKeyInputs)
{
if(!isTank)
{
const bool accel=carRawInputs.getDigitalAccel();
const bool brake=carRawInputs.getDigitalBrake();
carRawInputs.setDigitalAccel(brake);
carRawInputs.setDigitalBrake(accel);
}
else
{
//Keyboard controls for tank not implemented yet.
const bool accelLeft=tankRawInputs.getDigitalLeftThrust();
const bool accelRight=tankRawInputs.getDigitalRightThrust();
const bool brakeLeft=tankRawInputs.getDigitalLeftBrake();
const bool brakeRight=tankRawInputs.getDigitalRightBrake();
tankRawInputs.setDigitalLeftThrust(brakeLeft);
tankRawInputs.setDigitalRightThrust(brakeRight);
tankRawInputs.setDigitalLeftBrake(accelLeft);
tankRawInputs.setDigitalRightBrake(accelRight);
}
}
else
{
if(!isTank)
{
const PxF32 accel=carRawInputs.getAnalogAccel();
const PxF32 brake=carRawInputs.getAnalogBrake();
carRawInputs.setAnalogAccel(brake);
carRawInputs.setAnalogBrake(accel);
}
else if(PxVehicleDriveTankControlModel::eSPECIAL==tankDriveModel)
{
const PxF32 thrustLeft=tankRawInputs.getAnalogLeftThrust();
const PxF32 thrustRight=tankRawInputs.getAnalogRightThrust();
tankRawInputs.setAnalogLeftThrust(-thrustLeft);
tankRawInputs.setAnalogRightThrust(-thrustRight);
}
else
{
const PxF32 thrustLeft=tankRawInputs.getAnalogLeftThrust();
const PxF32 thrustRight=tankRawInputs.getAnalogRightThrust();
const PxF32 brakeLeft=tankRawInputs.getAnalogLeftBrake();
const PxF32 brakeRight=tankRawInputs.getAnalogRightBrake();
tankRawInputs.setAnalogLeftThrust(brakeLeft);
tankRawInputs.setAnalogLeftBrake(thrustLeft);
tankRawInputs.setAnalogRightThrust(brakeRight);
tankRawInputs.setAnalogRightBrake(thrustRight);
}
}
}
// Now filter the raw input values and apply them to focus vehicle
// as floats for brake,accel,handbrake,steer and bools for gearup,geardown.
if(mUseKeyInputs)
{
if(!isTank)
{
const bool isInAir = PxVehicleIsInAir(vehicleWheelQueryResults);
PxVehicleDrive4WSmoothDigitalRawInputsAndSetAnalogInputs
(gKeySmoothingData,gSteerVsForwardSpeedTable,carRawInputs,timestep,isInAir,(PxVehicleDrive4W&)focusVehicle);
}
else
{
PxVehicleDriveTankSmoothDigitalRawInputsAndSetAnalogInputs
(gKeySmoothingData,tankRawInputs,timestep,(PxVehicleDriveTank&)focusVehicle);
}
}
else
{
if(!isTank)
{
const bool isInAir = PxVehicleIsInAir(vehicleWheelQueryResults);
PxVehicleDrive4WSmoothAnalogRawInputsAndSetAnalogInputs
(gCarPadSmoothingData,gSteerVsForwardSpeedTable,carRawInputs,timestep,isInAir,(PxVehicleDrive4W&)focusVehicle);
}
else
{
PxVehicleDriveTankSmoothAnalogRawInputsAndSetAnalogInputs
(gTankPadSmoothingData,tankRawInputs,timestep,(PxVehicleDriveTank&)focusVehicle);
}
}
}
void SampleVehicle_VehicleController::restart()
{
const bool record=mRecord;
const bool replay=mReplay;
const PxU32 numSamples=mNumSamples;
const PxU32 numRecordedSamples=mNumRecordedSamples;
clear();
mRecord=record;
mReplay=replay;
mNumRecordedSamples=numRecordedSamples;
if(record)
{
PX_ASSERT(!replay);
mNumRecordedSamples = numSamples;
mRecord = false;
mReplay = true;
}
}

View File

@ -0,0 +1,226 @@
//
// 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 SAMPLE_VEHICLE_VEHICLE_CONTROLLER_H
#define SAMPLE_VEHICLE_VEHICLE_CONTROLLER_H
#include "common/PxPhysXCommonConfig.h"
#include "foundation/PxVec3.h"
#include "vehicle/PxVehicleSDK.h"
#include "vehicle/PxVehicleUpdate.h"
#include "vehicle/PxVehicleUtilControl.h"
using namespace physx;
class SampleVehicle_VehicleController
{
public:
SampleVehicle_VehicleController();
~SampleVehicle_VehicleController();
void setCarKeyboardInputs
(const bool accel, const bool brake, const bool handbrake,
const bool steerleft, const bool steerright,
const bool gearup, const bool geardown)
{
mKeyPressedAccel=accel;
mKeyPressedBrake=brake;
mKeyPressedHandbrake=handbrake;
mKeyPressedSteerLeft=steerleft;
mKeyPressedSteerRight=steerright;
mKeyPressedGearUp=gearup;
mKeyPressedGearDown=geardown;
}
void setCarGamepadInputs
(const PxF32 accel, const PxF32 brake,
const PxF32 steer,
const bool gearup, const bool geardown,
const bool handbrake)
{
mGamepadAccel=accel;
mGamepadCarBrake=brake;
mGamepadCarSteer=steer;
mGamepadGearup=gearup;
mGamepadGeardown=geardown;
mGamepadCarHandbrake=handbrake;
}
void setTankKeyboardInputs
(const bool accel, const bool thrustLeft, const bool thrustRight, const bool brakeLeft, const bool brakeRight, const bool gearUp, const bool gearDown)
{
mKeyPressedAccel=accel;
mKeyPressedThrustLeft=thrustLeft;
mKeyPressedThrustRight=thrustRight;
mKeyPressedBrakeLeft=brakeLeft;
mKeyPressedBrakeRight=brakeRight;
mKeyPressedGearUp=gearUp;
mKeyPressedGearDown=gearDown;
}
void setTankGamepadInputs
(const PxF32 accel, const PxF32 thrustLeft, const PxF32 thrustRight, const PxF32 brakeLeft, const PxF32 brakeRight, const bool gearUp, const bool gearDown)
{
mGamepadAccel=accel;
mTankThrustLeft=thrustLeft;
mTankThrustRight=thrustRight;
mTankBrakeLeft=brakeLeft;
mTankBrakeRight=brakeRight;
mGamepadGearup=gearUp;
mGamepadGeardown=gearDown;
}
void toggleAutoGearFlag()
{
mToggleAutoGears = true;
}
void update(const PxF32 dtime, const PxVehicleWheelQueryResult& vehicleWheelQueryResults, PxVehicleWheels& focusVehicle);
void clear();
private:
//Raw driving inputs - keys (car + tank)
bool mKeyPressedAccel;
bool mKeyPressedGearUp;
bool mKeyPressedGearDown;
//Raw driving inputs - keys (car only)
bool mKeyPressedBrake;
bool mKeyPressedHandbrake;
bool mKeyPressedSteerLeft;
bool mKeyPressedSteerRight;
//Raw driving inputs - keys (tank only)
bool mKeyPressedThrustLeft;
bool mKeyPressedThrustRight;
bool mKeyPressedBrakeLeft;
bool mKeyPressedBrakeRight;
//Raw driving inputs - gamepad (car + tank)
PxF32 mGamepadAccel;
bool mGamepadGearup;
bool mGamepadGeardown;
//Raw driving inputs - gamepad (car only)
PxF32 mGamepadCarBrake;
PxF32 mGamepadCarSteer;
bool mGamepadCarHandbrake;
//Raw driving inputs - (tank only)
PxF32 mTankThrustLeft;
PxF32 mTankThrustRight;
PxF32 mTankBrakeLeft;
PxF32 mTankBrakeRight;
//Record and replay using raw driving inputs.
bool mRecord;
bool mReplay;
enum
{
MAX_NUM_RECORD_REPLAY_SAMPLES=8192
};
// Keyboard
bool mKeyboardAccelValues[MAX_NUM_RECORD_REPLAY_SAMPLES];
bool mKeyboardBrakeValues[MAX_NUM_RECORD_REPLAY_SAMPLES];
bool mKeyboardHandbrakeValues[MAX_NUM_RECORD_REPLAY_SAMPLES];
bool mKeyboardSteerLeftValues[MAX_NUM_RECORD_REPLAY_SAMPLES];
bool mKeyboardSteerRightValues[MAX_NUM_RECORD_REPLAY_SAMPLES];
bool mKeyboardGearupValues[MAX_NUM_RECORD_REPLAY_SAMPLES];
bool mKeyboardGeardownValues[MAX_NUM_RECORD_REPLAY_SAMPLES];
// Gamepad - (tank + car)
PxF32 mGamepadAccelValues[MAX_NUM_RECORD_REPLAY_SAMPLES];
bool mGamepadGearupValues[MAX_NUM_RECORD_REPLAY_SAMPLES];
bool mGamepadGeardownValues[MAX_NUM_RECORD_REPLAY_SAMPLES];
// Gamepad - car only
PxF32 mGamepadCarBrakeValues[MAX_NUM_RECORD_REPLAY_SAMPLES];
PxF32 mGamepadCarSteerValues[MAX_NUM_RECORD_REPLAY_SAMPLES];
bool mGamepadCarHandbrakeValues[MAX_NUM_RECORD_REPLAY_SAMPLES];
//Gamepad - tank only.
PxF32 mGamepadTankThrustLeftValues[MAX_NUM_RECORD_REPLAY_SAMPLES];
PxF32 mGamepadTankThrustRightValues[MAX_NUM_RECORD_REPLAY_SAMPLES];
PxU32 mNumSamples;
PxU32 mNumRecordedSamples;
// Raw data taken from the correct stream (live input stream or replay stream)
bool mUseKeyInputs;
// Toggle autogears flag on focus vehicle
bool mToggleAutoGears;
//Auto-reverse mode.
bool mIsMovingForwardSlowly;
bool mInReverseMode;
//Update
void processRawInputs(const PxF32 timestep, const bool useAutoGears, PxVehicleDrive4WRawInputData& rawInputData);
void processRawInputs(const PxF32 timestep, const bool useAutoGears, PxVehicleDriveTankRawInputData& rawInputData);
void processAutoReverse(
const PxVehicleWheels& focusVehicle, const PxVehicleDriveDynData& driveDynData, const PxVehicleWheelQueryResult& vehicleWheelQueryResults,
const PxVehicleDrive4WRawInputData& rawInputData,
bool& toggleAutoReverse, bool& newIsMovingForwardSlowly) const;
void processAutoReverse(
const PxVehicleWheels& focusVehicle, const PxVehicleDriveDynData& driveDynData, const PxVehicleWheelQueryResult& vehicleWheelQueryResults,
const PxVehicleDriveTankRawInputData& rawInputData,
bool& toggleAutoReverse, bool& newIsMovingForwardSlowly) const;
////////////////////////////////
//Record and replay deprecated at the moment.
//Setting functions as private to avoid them being used.
///////////////////////////////
bool getIsInRecordReplayMode() const {return (mRecord || mReplay);}
bool getIsRecording() const {return mRecord;}
bool getIsReplaying() const {return mReplay;}
void enableRecordReplayMode()
{
PX_ASSERT(!getIsInRecordReplayMode());
mRecord=true;
mReplay=false;
mNumRecordedSamples=0;
}
void disableRecordReplayMode()
{
PX_ASSERT(getIsInRecordReplayMode());
mRecord=false;
mReplay=false;
mNumRecordedSamples=0;
}
void restart();
////////////////////////////
};
#endif //SAMPLE_VEHICLE_VEHICLE_CONTROLLER_H

View File

@ -0,0 +1,171 @@
//
// 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 "SampleVehicle_VehicleCooking.h"
#include "PxTkStream.h"
#include "extensions/PxDefaultStreams.h"
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* createCuboidConvexMesh(const PxVec3& halfExtents, PxPhysics& physics, PxCooking& cooking)
{
PxVec3 verts[8]=
{
PxVec3(-halfExtents.x, -halfExtents.y, -halfExtents.z),
PxVec3(-halfExtents.x, -halfExtents.y, +halfExtents.z),
PxVec3(-halfExtents.x, +halfExtents.y, -halfExtents.z),
PxVec3(-halfExtents.x, +halfExtents.y, +halfExtents.z),
PxVec3(+halfExtents.x, -halfExtents.y, -halfExtents.z),
PxVec3(+halfExtents.x, -halfExtents.y, +halfExtents.z),
PxVec3(+halfExtents.x, +halfExtents.y, -halfExtents.z),
PxVec3(+halfExtents.x, +halfExtents.y, +halfExtents.z)
};
PxU32 numVerts=8;
return createConvexMesh(verts,numVerts,physics,cooking);
}
PxConvexMesh* createWedgeConvexMesh(const PxVec3& halfExtents, PxPhysics& physics, PxCooking& cooking)
{
PxVec3 verts[6]=
{
PxVec3(-halfExtents.x, -halfExtents.y, -halfExtents.z),
PxVec3(-halfExtents.x, -halfExtents.y, +halfExtents.z),
PxVec3(-halfExtents.x, +halfExtents.y, -halfExtents.z),
PxVec3(+halfExtents.x, -halfExtents.y, -halfExtents.z),
PxVec3(+halfExtents.x, -halfExtents.y, +halfExtents.z),
PxVec3(+halfExtents.x, +halfExtents.y, -halfExtents.z)
};
PxU32 numVerts=6;
return createConvexMesh(verts,numVerts,physics,cooking);
}
PxConvexMesh* createCylinderConvexMesh(const PxF32 width, const PxF32 radius, const PxU32 numCirclePoints, PxPhysics& physics, PxCooking& cooking)
{
#define MAX_NUM_VERTS_IN_CIRCLE 16
PX_ASSERT(numCirclePoints<MAX_NUM_VERTS_IN_CIRCLE);
PxVec3 verts[2*MAX_NUM_VERTS_IN_CIRCLE];
PxU32 numVerts=2*numCirclePoints;
const PxF32 dtheta=2*PxPi/(1.0f*numCirclePoints);
for(PxU32 i=0;i<MAX_NUM_VERTS_IN_CIRCLE;i++)
{
const PxF32 theta=dtheta*i;
const PxF32 cosTheta=radius*PxCos(theta);
const PxF32 sinTheta=radius*PxSin(theta);
verts[2*i+0]=PxVec3(-0.5f*width, cosTheta, sinTheta);
verts[2*i+1]=PxVec3(+0.5f*width, cosTheta, sinTheta);
}
return createConvexMesh(verts,numVerts,physics,cooking);
}
PxConvexMesh* createSquashedCuboidMesh(const PxF32 baseLength, const PxF32 baseDepth, const PxF32 height1, const PxF32 height2, PxPhysics& physics, PxCooking& cooking)
{
const PxF32 x=baseLength*0.5f;
const PxF32 z=baseDepth*0.5f;
PxVec3 verts[8]=
{
PxVec3(-x,-0.5f*height1,-z),
PxVec3(-x,-0.5f*height1,+z),
PxVec3(+x,-0.5f*height1,-z),
PxVec3(+x,-0.5f*height1,+z),
PxVec3(-x,-0.5f*height1+height2,-z),
PxVec3(-x,+0.5f*height1,+z),
PxVec3(+x,-0.5f*height1+height2,-z),
PxVec3(+x,+0.5f*height1,+z)
};
PxU32 numVerts=8;
return createConvexMesh(verts,numVerts,physics,cooking);
}
PxConvexMesh* createPrismConvexMesh(const PxF32 baseLength, const PxF32 baseDepth, const PxF32 height, PxPhysics& physics, PxCooking& cooking)
{
const PxF32 x=baseLength*0.5f;
const PxF32 z=baseDepth*0.5f;
PxVec3 verts[6]=
{
PxVec3(-x, 0, -z),
PxVec3(-x, 0, +z),
PxVec3(+x, 0, -z),
PxVec3(+x, 0, +z),
PxVec3(-x, height, 0),
PxVec3(+x, height, 0),
};
PxU32 numVerts=6;
return createConvexMesh(verts,numVerts,physics,cooking);
}
PxConvexMesh* createChassisConvexMesh(const PxVec3* verts, const PxU32 numVerts, PxPhysics& physics, PxCooking& cooking)
{
return createConvexMesh(verts,numVerts,physics,cooking);
}
PxConvexMesh* createWheelConvexMesh(const PxVec3* verts, const PxU32 numVerts, PxPhysics& physics, PxCooking& cooking)
{
//Extract the wheel radius and width from the aabb of the wheel convex mesh.
PxVec3 wheelMin(PX_MAX_F32,PX_MAX_F32,PX_MAX_F32);
PxVec3 wheelMax(-PX_MAX_F32,-PX_MAX_F32,-PX_MAX_F32);
for(PxU32 i=0;i<numVerts;i++)
{
wheelMin.x=PxMin(wheelMin.x,verts[i].x);
wheelMin.y=PxMin(wheelMin.y,verts[i].y);
wheelMin.z=PxMin(wheelMin.z,verts[i].z);
wheelMax.x=PxMax(wheelMax.x,verts[i].x);
wheelMax.y=PxMax(wheelMax.y,verts[i].y);
wheelMax.z=PxMax(wheelMax.z,verts[i].z);
}
const PxF32 wheelWidth=wheelMax.x-wheelMin.x;
const PxF32 wheelRadius=PxMax(wheelMax.y,wheelMax.z);
return createCylinderConvexMesh(wheelWidth,wheelRadius,8,physics,cooking);
}

View File

@ -0,0 +1,48 @@
//
// 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 VEHICLE_COOKING_H
#define VEHICLE_COOKING_H
#include "PxPhysicsAPI.h"
using namespace physx;
PxConvexMesh* createConvexMesh(const PxVec3* verts, const PxU32 numVerts, PxPhysics& physics, PxCooking& cooking);
PxConvexMesh* createCuboidConvexMesh(const PxVec3& halfExtents, PxPhysics& physics, PxCooking& cooking);
PxConvexMesh* createWedgeConvexMesh(const PxVec3& halfExtents, PxPhysics& physics, PxCooking& cooking);
PxConvexMesh* createCylinderConvexMesh(const PxF32 width, const PxF32 radius, const PxU32 numCirclePoints, PxPhysics& physics, PxCooking& cooking);
PxConvexMesh* createSquashedCuboidMesh(const PxF32 baseLength, const PxF32 baseDepth, const PxF32 height1, const PxF32 height2, PxPhysics& physics, PxCooking& cooking);
PxConvexMesh* createPrismConvexMesh(const PxF32 baseLength, const PxF32 baseDepth, const PxF32 height, PxPhysics& physics, PxCooking& cooking);
PxConvexMesh* createWheelConvexMesh(const PxVec3* verts, const PxU32 numVerts, PxPhysics& physics, PxCooking& cooking);
PxConvexMesh* createChassisConvexMesh(const PxVec3* verts, const PxU32 numVerts, PxPhysics& physics, PxCooking& cooking);
#endif //VEHICLE_COOKING_H

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,226 @@
//
// 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 SAMPLE_VEHICLE_VEHICLE_MANAGER_H
#define SAMPLE_VEHICLE_VEHICLE_MANAGER_H
#include "vehicle/PxVehicleSDK.h"
#include "vehicle/PxVehicleDrive4W.h"
#include "vehicle/PxVehicleDriveNW.h"
#include "vehicle/PxVehicleDriveTank.h"
#include "vehicle/PxVehicleUpdate.h"
#include "PxFoundation.h"
#if PX_DEBUG_VEHICLE_ON
#include "vehicle/PxVehicleUtilTelemetry.h"
#endif
using namespace physx;
namespace physx
{
class PxScene;
class PxBatchQuery;
class PxCooking;
class PxMaterial;
class PxConvexMesh;
struct PxVehicleDrivableSurfaceType;
}
class SampleVehicleSceneQueryData;
class SampleVehicleWheelQueryResults;
class PxVehicle4WAlloc;
//Collision types and flags describing collision interactions of each collision type.
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,
};
//Id of drivable surface (used by suspension raycast filtering).
enum
{
DRIVABLE_SURFACE_ID=0xffffffff
};
//Drivable surface types.
enum
{
SURFACE_TYPE_MUD=0,
SURFACE_TYPE_TARMAC,
SURFACE_TYPE_SNOW,
SURFACE_TYPE_GRASS,
MAX_NUM_SURFACE_TYPES
};
struct SurfaceTypeNames
{
static const char* getName(PxU32 type)
{
static char surfaceTypes[MAX_NUM_SURFACE_TYPES+1][64]=
{
"mud",
"tarmac",
"ice",
"grass",
};
return surfaceTypes[type];
}
};
//Tire types.
enum
{
TIRE_TYPE_WETS=0,
TIRE_TYPE_SLICKS,
TIRE_TYPE_ICE,
TIRE_TYPE_MUD,
MAX_NUM_TIRE_TYPES
};
struct TireFrictionMultipliers
{
static float getValue(PxU32 surfaceType, PxU32 tireType)
{
//Tire model friction for each combination of drivable surface type and tire type.
static PxF32 tireFrictionMultipliers[MAX_NUM_SURFACE_TYPES][MAX_NUM_TIRE_TYPES]=
{
//WETS SLICKS ICE MUD
{0.95f, 0.95f, 0.95f, 0.95f}, //MUD
{1.10f, 1.15f, 1.10f, 1.10f}, //TARMAC
{0.70f, 0.70f, 0.70f, 0.70f}, //ICE
{0.80f, 0.80f, 0.80f, 0.80f} //GRASS
};
return tireFrictionMultipliers[surfaceType][tireType];
}
};
class SampleVehicle_VehicleManager
{
public:
enum
{
MAX_NUM_4W_VEHICLES=8,
MAX_NUM_6W_VEHICLES=2,
MAX_NUM_4W_TANKS=2
};
SampleVehicle_VehicleManager();
~SampleVehicle_VehicleManager();
void init(PxPhysics& physics, const PxMaterial** drivableSurfaceMaterials, const PxVehicleDrivableSurfaceType* drivableSurfaceTypes);
void shutdown();
//Create a vehicle ready to drive.
void 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);
void 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);
void 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);
void 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);
PX_FORCE_INLINE PxU32 getNbVehicles() const { return mNumVehicles; }
PX_FORCE_INLINE PxVehicleWheels* getVehicle(const PxU32 i) { return mVehicles[i]; }
PX_FORCE_INLINE const PxVehicleWheelQueryResult& getVehicleWheelQueryResults(const PxU32 i) const { return mVehicleWheelQueryResults[i]; }
void addVehicle(const PxU32 i, PxVehicleWheels* vehicle);
//Start the suspension raycasts (always call before calling update)
void suspensionRaycasts(PxScene* scene);
//Update vehicle dynamics and compute forces/torques to apply to sdk rigid bodies.
#if PX_DEBUG_VEHICLE_ON
void updateAndRecordTelemetryData(const PxF32 timestep, const PxVec3& gravity, PxVehicleWheels* focusVehicleNW, PxVehicleTelemetryData* telemetryDataNW);
#else
void update(const PxF32 timestep, const PxVec3& gravity);
#endif
//Reset the car back to its rest state with a specified transform.
void resetNWCar(const PxTransform& transform, const PxU32 vehicleId);
//Switch the player's vehicle to 3-wheeled modes and back to 4-wheeled mode.
void switchTo3WDeltaMode(const PxU32 vehicleId);
void switchTo3WTadpoleMode(const PxU32 vehicleId);
void switchTo4WMode(const PxU32 vehicleId);
PxSerializationRegistry* getSerializationRegistry() { return mSerializationRegistry; }
private:
//Array of all cars and report data for each car.
PxVehicleWheels* mVehicles[MAX_NUM_4W_VEHICLES+MAX_NUM_6W_VEHICLES];
PxVehicleWheelQueryResult mVehicleWheelQueryResults[MAX_NUM_4W_VEHICLES+MAX_NUM_6W_VEHICLES];
PxU32 mNumVehicles;
//sdk raycasts (for the suspension lines).
SampleVehicleSceneQueryData* mSqData;
PxBatchQuery* mSqWheelRaycastBatchQuery;
//Reports for each wheel.
SampleVehicleWheelQueryResults* mWheelQueryResults;
//Cached simulation data of focus vehicle in 4W mode.
PxVehicleWheelsSimData* mWheelsSimData4W;
PxVehicleDriveSimData4W mDriveSimData4W;
bool mIsIn3WMode;
//Friction from combinations of tire and surface types.
PxVehicleDrivableSurfaceToTireFrictionPairs* mSurfaceTirePairs;
//Initialise a car back to its start transform and state.
void resetNWCar(const PxTransform& startTransform, PxVehicleWheels* car);
//Serialization
PxSerializationRegistry* mSerializationRegistry;
};
#endif //SAMPLE_VEHICLE_VEHICLE_MANAGER_H

View File

@ -0,0 +1,73 @@
//
// 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 "SampleVehicle_WheelQueryResults.h"
#include "vehicle/PxVehicleSDK.h"
#include "PsFoundation.h"
#include "PsUtilities.h"
//#define CHECK_MSG(exp, msg) (!!(exp) || (physx::shdfnd::getFoundation().error(physx::PxErrorCode::eINVALID_PARAMETER, __FILE__, __LINE__, msg), 0) )
SampleVehicleWheelQueryResults* SampleVehicleWheelQueryResults::allocate(const PxU32 maxNumWheels)
{
const PxU32 size = sizeof(SampleVehicleWheelQueryResults) + sizeof(PxWheelQueryResult)*maxNumWheels;
SampleVehicleWheelQueryResults* resData = (SampleVehicleWheelQueryResults*)PX_ALLOC(size, "SampleVehicleWheelQueryResults");
resData->init();
PxU8* ptr = (PxU8*) resData;
ptr += sizeof(SampleVehicleWheelQueryResults);
resData->mWheelQueryResults = (PxWheelQueryResult*)ptr;
ptr += sizeof(PxWheelQueryResult)*maxNumWheels;
resData->mMaxNumWheels=maxNumWheels;
for(PxU32 i=0;i<maxNumWheels;i++)
{
new(&resData->mWheelQueryResults[i]) PxWheelQueryResult();
}
return resData;
}
void SampleVehicleWheelQueryResults::free()
{
PX_FREE(this);
}
PxWheelQueryResult* SampleVehicleWheelQueryResults::addVehicle(const PxU32 numWheels)
{
PX_ASSERT((mNumWheels + numWheels) <= mMaxNumWheels);
PxWheelQueryResult* r = &mWheelQueryResults[mNumWheels];
mNumWheels += numWheels;
return r;
}

View File

@ -0,0 +1,82 @@
//
// 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 SAMPLEVEHICLE_WHEELQUERYRESULTS_H
#define SAMPLEVEHICLE_WHEELQUERYRESULTS_H
#include "vehicle/PxVehicleSDK.h"
#include "vehicle/PxVehicleUpdate.h"
using namespace physx;
//Data structure to store reports for each wheel.
class SampleVehicleWheelQueryResults
{
public:
//Allocate a buffer of wheel query results for up to maxNumWheels.
static SampleVehicleWheelQueryResults* allocate(const PxU32 maxNumWheels);
//Free allocated buffer.
void free();
PxWheelQueryResult* addVehicle(const PxU32 numWheels);
private:
//One result for each wheel.
PxWheelQueryResult* mWheelQueryResults;
//Maximum number of wheels.
PxU32 mMaxNumWheels;
//Number of wheels
PxU32 mNumWheels;
SampleVehicleWheelQueryResults()
: mWheelQueryResults(NULL),mMaxNumWheels(0), mNumWheels(0)
{
init();
}
~SampleVehicleWheelQueryResults()
{
}
void init()
{
mWheelQueryResults=NULL;
mMaxNumWheels=0;
mNumWheels=0;
}
};
#endif //SAMPLEVEHICLE_WHEELQUERYRESULTS_H