diff options
| author | git perforce import user <a@b> | 2016-10-25 12:29:14 -0600 |
|---|---|---|
| committer | Sheikh Dawood Abdul Ajees <Sheikh Dawood Abdul Ajees> | 2016-10-25 18:56:37 -0500 |
| commit | 3dfe2108cfab31ba3ee5527e217d0d8e99a51162 (patch) | |
| tree | fa6485c169e50d7415a651bf838f5bcd0fd3bfbd /PhysX_3.4/Samples/SampleVehicle/SampleVehicle.cpp | |
| download | physx-3.4-3dfe2108cfab31ba3ee5527e217d0d8e99a51162.tar.xz physx-3.4-3dfe2108cfab31ba3ee5527e217d0d8e99a51162.zip | |
Initial commit:
PhysX 3.4.0 Update @ 21294896
APEX 1.4.0 Update @ 21275617
[CL 21300167]
Diffstat (limited to 'PhysX_3.4/Samples/SampleVehicle/SampleVehicle.cpp')
| -rw-r--r-- | PhysX_3.4/Samples/SampleVehicle/SampleVehicle.cpp | 2271 |
1 files changed, 2271 insertions, 0 deletions
diff --git a/PhysX_3.4/Samples/SampleVehicle/SampleVehicle.cpp b/PhysX_3.4/Samples/SampleVehicle/SampleVehicle.cpp new file mode 100644 index 00000000..52f86b8c --- /dev/null +++ b/PhysX_3.4/Samples/SampleVehicle/SampleVehicle.cpp @@ -0,0 +1,2271 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and related documentation and +// any modifications thereto. Any use, reproduction, disclosure, or +// distribution of this software and related documentation without an express +// license agreement from NVIDIA Corporation is strictly prohibited. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + + +#include "SampleVehicle.h" +#include "RendererMemoryMacros.h" +#include "RenderMeshActor.h" +#include "SampleVehicle_VehicleCooking.h" +#include "SampleVehicle_SceneQuery.h" +#include "PxPhysicsAPI.h" +#include "extensions/PxExtensionsAPI.h" +#include "RenderPhysX3Debug.h" + +#include "SampleVehicleInputEventIds.h" +#include <SampleFrameworkInputEventIds.h> +#include <SampleBaseInputEventIds.h> +#include <SamplePlatform.h> +#include <SampleUserInput.h> +#include <SampleUserInputIds.h> +#include <SampleUserInputDefines.h> +#include "PxTkFile.h" + +REGISTER_SAMPLE(SampleVehicle, "SampleVehicle") + +enum +{ + LOAD_TYPE_VEHICLE=0, + LOAD_TYPE_LOOPTHELOOP, + LOAD_TYPE_SKYDOME, + MAX_NUM_LOAD_TYPES +}; +static PxU32 gLoadType = MAX_NUM_LOAD_TYPES; + +using namespace physx; +using namespace SampleRenderer; +using namespace SampleFramework; + +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////// +//VEHICLE START PARAMETERS +/////////////////////////////////// + +#define NUM_PLAYER_CARS 1 +static PxTransform gPlayerCarStartTransforms[NUM_PLAYER_CARS] = +{ + PxTransform(PxVec3(-154.699753f, 9.863837f, 87.684113f), PxQuat(-0.000555f, -0.267015, 0.000155, -0.963692 )) +}; + +#define NUM_NONPLAYER_4W_VEHICLES 7 +#if NUM_NONPLAYER_4W_VEHICLES +static PxTransform gVehicle4WStartTransforms[NUM_NONPLAYER_4W_VEHICLES] = +{ + //Stack of 2 cars + PxTransform(PxVec3(-78.796158f,9.8764671f,155.47554f), PxQuat(0.00062184106f,0.97696519f,-0.0029967001f,0.21337670f)), + PxTransform(PxVec3(-78.796158f,11.7764671f,155.47554f), PxQuat(0.00062184106f,0.97696519f,-0.0029967001f,0.21337670f)), + + //Stack of 2 cars + PxTransform(PxVec3(-80.391357f,9.8760214f,161.93578f), PxQuat(1.0251222e-005f, 0.98799443f, -6.0369461e-005f, 0.15448983f)), + PxTransform(PxVec3(-80.391357f,11.7760214f,161.93578f), PxQuat(1.0251222e-005f, 0.98799443f, -6.0369461e-005f, 0.15448983f)), + + //Bookends to car stacks + PxTransform(PxVec3(-77.945328f,9.9765568f,151.78404f), PxQuat(0.0014836629f,-0.86193967f,0.0024594457f,0.50700283f)), + PxTransform(PxVec3(-80.395328f,9.8786600f,167.44662f), PxQuat(0.0014836629f,-0.86193967f,0.0024594457f,0.50700283f)), + + //Car in-between two ramps + PxTransform(PxVec3(116.04498f,9.9760214f,139.02933f), PxQuat(7.5981094e-005f,-0.38262743f,-3.1461415e-005f,-0.92390275f)), +}; +#endif + +#define NUM_NONPLAYER_6W_VEHICLES 1 +#if NUM_NONPLAYER_6W_VEHICLES +static PxTransform gVehicle6WStartTransforms[NUM_NONPLAYER_6W_VEHICLES]= +{ + //6-wheeled car + PxTransform(PxVec3(-158.09471f,9.8649321f,80.359474f), PxQuat(-0.0017525638f,-0.24773766f,0.00040674198f,-0.96882552f)) +}; +#endif + +#define NUM_NONPLAYER_4W_TANKS 0 +#if NUM_NONPLAYER_4W_TANKS +static PxTransform gTank4WStartTransforms[NUM_NONPLAYER_4W_TANKS]= +{ + //6-wheeled car + PxTransform(PxVec3(-158.09471f,9.8649321f,80.359474f), PxQuat(-0.0017525638f,-0.24773766f,0.00040674198f,-0.96882552f)) +}; +#endif + +#define NUM_NONPLAYER_6W_TANKS 0 +#if NUM_NONPLAYER_6W_TANKS +static PxTransform gTank6WStartTransforms[NUM_NONPLAYER_6W_TANKS]= +{ + //6-wheeled car + PxTransform(PxVec3(-158.09471f,9.8649321f,80.359474f), PxQuat(-0.0017525638f,-0.24773766f,0.00040674198f,-0.96882552f)) +}; +#endif + + +PxU32 gNumVehicleAdded=0; + +//////////////////////////////////////////////////////////////// +//VEHICLE SETUP DATA +//////////////////////////////////////////////////////////////// + +PxF32 gChassisMass=1500.0f; +PxF32 gSuspensionShimHeight=0.125f; + +//////////////////////////////////////////////////////////////// +//RENDER USER DATA TO ASSOCIATE EACH RENDER MESH WITH A +//VEHICLE PHYSICS COMPONENT +//////////////////////////////////////////////////////////////// + +enum +{ + CAR_PART_FRONT_LEFT_WHEEL=0, + CAR_PART_FRONT_RIGHT_WHEEL, + CAR_PART_REAR_LEFT_WHEEL, + CAR_PART_REAR_RIGHT_WHEEL, + CAR_PART_CHASSIS, + CAR_PART_WINDOWS, + NUM_CAR4W_RENDER_COMPONENTS, + CAR_PART_EXTRA_WHEEL0=NUM_CAR4W_RENDER_COMPONENTS, + CAR_PART_EXTRA_WHEEL1, + NUM_CAR6W_RENDER_COMPONENTS +}; + +static const char gCarPartNames[NUM_CAR4W_RENDER_COMPONENTS][64]= +{ + "frontwheelleftshape", + "frontwheelrightshape", + "backwheelleftshape", + "backwheelrightshape", + "car_02_visshape", + "car_02_windowsshape" +}; + +struct CarRenderUserData +{ + PxU8 carId; + PxU8 carPart; + PxU8 carPartDependency; + PxU8 pad; +}; + +static const CarRenderUserData gCar4WRenderUserData[NUM_CAR6W_RENDER_COMPONENTS] = +{ + //wheel fl wheel fr wheel rl wheel rl chassis windows extra wheel0 extra wheel1 + {0,0,255}, {0,1,255}, {0,2,255}, {0,3,255}, {0,4,255}, {0,4,4}, {255,255,255}, {255,255,255} +}; + +static const CarRenderUserData gCar6WRenderUserData[NUM_CAR6W_RENDER_COMPONENTS] = +{ + //wheel fl wheel fr wheel rl wheel rl chassis windows extra wheel0 extra wheel1 + {0,0,255}, {0,1,255}, {0,2,255}, {0,3,255}, {0,6,255}, {0,6,6}, {0,4,255}, {0,5,255} +}; + +CarRenderUserData gVehicleRenderUserData[NUM_PLAYER_CARS + NUM_NONPLAYER_4W_VEHICLES + NUM_NONPLAYER_6W_VEHICLES + NUM_NONPLAYER_4W_TANKS + NUM_NONPLAYER_6W_TANKS][NUM_CAR6W_RENDER_COMPONENTS]; + +RenderMeshActor* gRenderMeshActors[NUM_CAR6W_RENDER_COMPONENTS]={NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL}; + +//////////////////////////////////////////////////////////////// +//TRANSFORM APPLIED TO CHASSIS RENDER MESH VERTS +//THAT IS REQUIRED TO PLACE AABB OF CHASSIS RENDER MESH AT ORIGIN +//AT CENTRE-POINT OF WHEELS. +//////////////////////////////////////////////////////////////// + +static PxVec3 gChassisMeshTransform(0,0,0); + +//////////////////////////////////////////////////////////////// +//WHEEL CENTRE OFFSETS FROM CENTRE OF CHASSIS RENDER MESH AABB +//OF 4-WHEELED VEHICLE +//////////////////////////////////////////////////////////////// + +static PxVec3 gWheelCentreOffsets4[4]; + +//////////////////////////////////////////////////////////////// +//CONVEX HULL OF RENDER MESH FOR CHASSIS AND WHEELS OF +//4-WHEELED VEHICLE +//////////////////////////////////////////////////////////////// + +static PxConvexMesh* gChassisConvexMesh=NULL; +static PxConvexMesh* gWheelConvexMeshes4[4]={NULL,NULL,NULL,NULL}; + +//////////////////////////////////////////////////////////////// +//Revolute joints and gian pendula +//////////////////////////////////////////////////////////////// + +#define MAX_NUM_PENDULA 4 + +PxTransform gPendulaBallStartTransforms[MAX_NUM_PENDULA]= +{ + PxTransform(PxVec3( 151.867020 , 11.364232 , 97.350906 ), PxQuat( -0.000106 , -0.951955 , 0.000370 , -0.306239 ) ) , + PxTransform(PxVec3( 163.001953 , 11.364203 , 77.854568 ), PxQuat( -0.000070 , -0.971984 , 0.000323 , -0.235048 ) ) , + PxTransform(PxVec3( 173.971405 , 11.364145 , 45.944290 ), PxQuat( -0.000050 , -0.994988 , 0.000448 , -0.099990 ) ) , + PxTransform(PxVec3( 179.876785 , 11.364090 , 3.679581 ), PxQuat( -0.000024 , -1.000000 , 0.000431 , -0.000193 ) ) +}; + +PxF32 gPendulumBallRadius=2.0f; +PxF32 gPendulumBallMass=1000.0f; +PxF32 gPendulumShaftLength=10.0f; +PxF32 gPendulumShaftWidth=0.1f; +PxF32 gPendulumSuspensionStructureWidth=13.0f; + +PxRevoluteJoint* gRevoluteJoints[MAX_NUM_PENDULA]={NULL,NULL,NULL,NULL}; +PxF32 gRevoluteJointDriveSpeeds[MAX_NUM_PENDULA]={0.932f,1.0f,1.237f,0.876f}; +PxF32 gRevoluteJointTimers[MAX_NUM_PENDULA]={0,0,0,0}; +PxU32 gNumRevoluteJoints=0; +PxF32 gRevoluteJointMaxTheta=0; + +//////////////////////////////////////////////////////////////// +//Route +//////////////////////////////////////////////////////////////// + +PxTransform gWayPoints[35]= +{ + PxTransform(PxVec3( -154.699753 , 9.863837 , 87.684113 ), PxQuat( -0.000555 , -0.267015 , 0.000155 , -0.963692 ) ) , + PxTransform(PxVec3( -133.385757 , 9.863703 , 118.680717 ), PxQuat( -0.000620 , -0.334975 , 0.000219 , -0.942227 ) ) , + PxTransform(PxVec3( -103.853020 , 9.863734 , 146.631256 ), PxQuat( -0.000560 , -0.474673 , 0.000301 , -0.880162 ) ) , + PxTransform(PxVec3( -20.397881 , 9.862607 , 177.345657 ), PxQuat( -0.000938 , -0.674493 , 0.000867 , -0.738281 ) ) , + PxTransform(PxVec3( 14.272619 , 9.863173 , 178.745789 ), PxQuat( -0.000736 , -0.723563 , 0.000740 , -0.690257 ) ) , + PxTransform(PxVec3( 49.057743 , 9.862507 , 173.464539 ), PxQuat( -0.000387 , -0.794072 , 0.001316 , -0.607822 ) ) , + PxTransform(PxVec3( 82.226036 , 9.862642 , 159.649200 ), PxQuat( -0.000670 , -0.853613 , 0.001099 , -0.520905 ) ) , + PxTransform(PxVec3( 158.675018 , 9.864265 , 86.166740 ), PxQuat( -0.000052 , -0.973169 , 0.000286 , -0.230092 ) ) , + PxTransform(PxVec3( 165.983170 , 9.857763 , 67.031097 ), PxQuat( -0.014701 , -0.979587 , 0.002133 , 0.200471 ) ) , + PxTransform(PxVec3( 177.577393 , 9.864532 , 30.462427 ), PxQuat( 0.000022 , -0.998473 , -0.000423 , -0.055239 ) ) , + PxTransform(PxVec3( 180.127686 , 9.864151 , -10.116920 ), PxQuat( 0.000011 , 0.999869 , 0.000295 , -0.016194 ) ) , + PxTransform(PxVec3( 174.281616 , 9.863608 , -42.319435 ), PxQuat( 0.000168 , 0.989981 , -0.001008 , -0.141194 ) ) , + PxTransform(PxVec3( 166.054413 , 9.864248 , -68.973045 ), PxQuat( -0.000052 , 0.985021 , -0.000213 , -0.172433 ) ) , + PxTransform(PxVec3( 154.505814 , 9.864180 , -77.992622 ), PxQuat( -0.000098 , 0.754213 , -0.000129 , -0.656630 ) ) , + PxTransform(PxVec3( 140.834076 , 9.863158 , -78.122841 ), PxQuat( -0.000730 , 0.709598 , -0.000737 , -0.704606 ) ) , + PxTransform(PxVec3( 100.152573 , 9.853898 , -78.407364 ), PxQuat( 0.066651 , 0.683499 , 0.070412 , -0.723484 ) ) , + PxTransform(PxVec3( 68.866241 , 10.293923 , -77.979095 ), PxQuat( -0.045687 , 0.703115 , -0.044258 , -0.708225 ) ), + PxTransform(PxVec3( 26.558704 , 10.495461 , -77.729164 ), PxQuat( -0.018349 , 0.708445 , -0.018563 , -0.705283 ) ) , + PxTransform(PxVec3( -2.121686 , 9.860541 , -77.735886 ), PxQuat( -0.000792 , 0.706926 , -0.000792 , -0.707287 ) ) , + PxTransform(PxVec3( -28.991186 , 9.867218 , -77.722122 ), PxQuat( -0.000251 , 0.706926 , -0.000251 , -0.707287 ) ) , + PxTransform(PxVec3( -59.285870 , 9.861916 , -77.746246 ), PxQuat( -0.001042 , 0.708723 , -0.001048 , -0.705485 ) ) , + PxTransform(PxVec3( -73.170433 , 9.863565 , -78.034157 ), PxQuat( -0.001567 , 0.736642 , -0.001323 , -0.676280 ) ) , + PxTransform(PxVec3( -77.792152 , 9.864209 , -87.821510 ), PxQuat( 0.000006 , 0.999772 , -0.000294 , -0.021342 ) ) , + PxTransform(PxVec3( -78.164032 , 9.862655 , -114.313690 ), PxQuat( -0.000010 , 0.999962 , -0.001280 , -0.008618 ) ), + PxTransform(PxVec3( -78.567627 , 9.862757 , -137.274292 ), PxQuat( -0.000010 , 0.999961 , -0.001146 , -0.008796 ) ) , + PxTransform(PxVec3( -80.392769 , 9.863695 , -149.740082 ), PxQuat( -0.000149 , 0.987276 , -0.000512 , -0.159015 ) ) , + PxTransform(PxVec3( -88.452507 , 9.864114 , -152.396698 ), PxQuat( -0.000355 , 0.622921 , -0.000278 , -0.782285 ) ) , + PxTransform(PxVec3( -106.042450 , 9.863844 , -144.640076 ), PxQuat( -0.000485 , 0.459262 , -0.000133 , -0.888301 ) ) , + PxTransform(PxVec3( -134.893997 , 15.093562 , -114.433586 ), PxQuat( 0.073759 , 0.354141 , 0.027569 , -0.931871 ) ) , + PxTransform(PxVec3( -145.495453 , 9.864394 , -101.019417 ), PxQuat( -0.000351 , 0.305924 , -0.000104 , -0.952056 ) ) , + PxTransform(PxVec3( -152.808212 , 9.864192 , -86.800613 ), PxQuat( -0.000099 , 0.206095 , -0.000015 , -0.978532 ) ) , + PxTransform(PxVec3( -156.457855 , 9.864244 , -81.270035 ), PxQuat( -0.000420 , 0.201378 , -0.000086 , -0.979514 ) ) , + PxTransform(PxVec3( -169.079376 , 10.192255 , -48.906967 ), PxQuat( 0.003633 , 0.179159 , 0.000892 , -0.983813 ) ) , + PxTransform(PxVec3( -151.470123 , 7.783551 , -17.838057 ), PxQuat( 0.029215 , -0.077987 , -0.050732 , -0.995234 ) ) , + PxTransform(PxVec3( -171.549225 , 9.864206 , 47.239426 ), PxQuat( -0.000319 , -0.159609 , 0.000039 , -0.987180 ) ) +}; +PxU32 gNumWayPoints=35; + +/////////////////////////////////////////////////////////////////////////////// + + +SampleVehicle::SampleVehicle(PhysXSampleApplication& app) : + PhysXSample (app), + mTerrainVB (NULL), + mNbTerrainVerts (0), + mNbIB (0), + mChassisMaterialDrivable (NULL), + mChassisMaterialNonDrivable (NULL), + mTerrainMaterial (NULL), + mRoadMaterial (NULL), + mRoadIceMaterial (NULL), + mRoadGravelMaterial (NULL), + mPlayerVehicle (0), + mPlayerVehicleType (ePLAYER_VEHICLE_TYPE_VEHICLE4W), + //mPlayerVehicleType (ePLAYER_VEHICLE_TYPE_VEHICLE6W), + //mPlayerVehicleType (ePLAYER_VEHICLE_TYPE_TANK4W), + //mPlayerVehicleType (ePLAYER_VEHICLE_TYPE_TANK6W), + //mTankDriveModel (PxVehicleDriveTankControlModel::eSPECIAL), + //mTankDriveModel (PxVehicleDriveTankControlModel::eSTANDARD), + mTerrainSize (256), + mTerrainWidth (2.0f), + mHFActor (NULL), + mHideScreenText (false), + mDebugRenderFlag (false), + mFixCar (false), + mBackToStart (false), + m3WModeIncremented (false), + m3WMode (0), + mForwardSpeedHud (0.0f) +{ + mCreateGroundPlane = false; + //mStepperType = FIXED_STEPPER; + + for(PxU32 i=0;i<MAX_NUM_INDEX_BUFFERS;i++) + mStandardMaterials[i] = NULL; + +#if PX_DEBUG_VEHICLE_ON + mDebugRenderActiveGraphChannelWheel = 0; + mDebugRenderActiveGraphChannelEngine = 0; + mTelemetryData4W = NULL; + mTelemetryData6W = NULL; +#endif +} + +SampleVehicle::~SampleVehicle() +{ +} + +/////////////////////////////////////////////////////////////////////////////// + +void SampleVehicle::customizeSample(SampleSetup& setup) +{ + setup.mName = "SampleVehicle"; +} + +void SampleVehicle::setupTelemetryData() +{ +#if PX_DEBUG_VEHICLE_ON + + mDebugRenderActiveGraphChannelWheel=PxVehicleWheelGraphChannel::eWHEEL_OMEGA; + mDebugRenderActiveGraphChannelEngine=PxVehicleDriveGraphChannel::eENGINE_REVS; + + { + const PxF32 graphSizeX=0.25f; + const PxF32 graphSizeY=0.25f; + const PxF32 engineGraphPosX=0.5f; + const PxF32 engineGraphPosY=0.5f; + const PxF32 wheelGraphPosX[4]={0.75f,0.25f,0.75f,0.25f}; + const PxF32 wheelGraphPosY[4]={0.75f,0.75f,0.25f,0.25f}; + const PxVec3 backgroundColor(255,255,255); + const PxVec3 lineColorHigh(255,0,0); + const PxVec3 lineColorLow(0,0,0); + + mTelemetryData4W = PxVehicleTelemetryData::allocate(4); + + mTelemetryData4W->setup + (graphSizeX,graphSizeY, + engineGraphPosX,engineGraphPosY, + wheelGraphPosX,wheelGraphPosY, + backgroundColor,lineColorHigh,lineColorLow); + } + + { + const PxF32 graphSizeX=0.225f; + const PxF32 graphSizeY=0.225f; + const PxF32 engineGraphPosX=0.5f; + const PxF32 engineGraphPosY=0.5f; + const PxF32 wheelGraphPosX[6]={0.75f,0.25f,0.75f,0.25f,0.75f,0.25f}; + const PxF32 wheelGraphPosY[8]={0.83f,0.83f,0.17f,0.17f,0.5f,0.5f}; + const PxVec3 backgroundColor(255,255,255); + const PxVec3 lineColorHigh(255,0,0); + const PxVec3 lineColorLow(0,0,0); + + mTelemetryData6W = PxVehicleTelemetryData::allocate(6); + + mTelemetryData6W->setup + (graphSizeX,graphSizeY, + engineGraphPosX,engineGraphPosY, + wheelGraphPosX,wheelGraphPosY, + backgroundColor,lineColorHigh,lineColorLow); + } + +#endif +} + +/////////////////////////////////////////////////////////////////////////////// + +void SampleVehicle::onInit() +{ + mNbThreads = PxMax(PxI32(shdfnd::Thread::getNbPhysicalCores())-1, 0); + + PhysXSample::onInit(); + + PxSceneWriteLock scopedLock(*mScene); + +#if defined(SERIALIZE_VEHICLE_BINARY) + mMemory = NULL; +#endif + + //Create physx objects. + createStandardMaterials(); + createVehicles(); + createTrack(mTerrainSize, mTerrainWidth, mTerrainSize*4.0f); + createObstacles(); + + //Setup camera. + setCameraController(NULL); + + //Setup debug render data. + setupTelemetryData(); + + //Setup the waypoint system. + mWayPoints.setWayPoints(gWayPoints,gNumWayPoints); + + //Load the skydome. + gLoadType = LOAD_TYPE_SKYDOME; + importRAWFile("sky_mission_race1.raw", 1.0f); + + //Set up the fog. + getRenderer()->setFog(SampleRenderer::RendererColor(40,40,40), 225.0f); +} + +void SampleVehicle::newMesh(const RAWMesh& data) +{ + if(LOAD_TYPE_LOOPTHELOOP==gLoadType) + { + PxMaterial* saved = mMaterial; + mMaterial = mStandardMaterials[SURFACE_TYPE_TARMAC]; + PhysXSample::newMesh(data); + mMaterial = saved; + } + else if(LOAD_TYPE_VEHICLE==gLoadType) + { + PxU32 carPart=0xffffffff; + if(0==Ps::strcmp(data.mName,gCarPartNames[CAR_PART_CHASSIS])) + { + carPart=CAR_PART_CHASSIS; + + //Find the min and max of the set of verts. + PxVec3 min(PX_MAX_F32,PX_MAX_F32,PX_MAX_F32); + PxVec3 max(-PX_MAX_F32,-PX_MAX_F32,-PX_MAX_F32); + for(PxU32 i=0;i<data.mNbVerts;i++) + { + min.x=PxMin(min.x,data.mVerts[i].x); + min.y=PxMin(min.y,data.mVerts[i].y); + min.z=PxMin(min.z,data.mVerts[i].z); + max.x=PxMax(max.x,data.mVerts[i].x); + max.y=PxMax(max.y,data.mVerts[i].y); + max.z=PxMax(max.z,data.mVerts[i].z); + } + + //Make sure the chassis has an aabb that is centred at (0,0,0). + //This just makes it a lot easier to set the centre of mass offset relative to the centre of the actor. + gChassisMeshTransform=(min+max)*0.5f; + + //Make sure wheel offsets are symmetric (they are not quite symmetric left to right or front to back). + gWheelCentreOffsets4[CAR_PART_FRONT_LEFT_WHEEL].x=-gWheelCentreOffsets4[CAR_PART_FRONT_RIGHT_WHEEL].x; + gWheelCentreOffsets4[CAR_PART_REAR_LEFT_WHEEL].x=-gWheelCentreOffsets4[CAR_PART_REAR_RIGHT_WHEEL].x; + gWheelCentreOffsets4[CAR_PART_FRONT_LEFT_WHEEL].y=gWheelCentreOffsets4[CAR_PART_REAR_LEFT_WHEEL].y; + gWheelCentreOffsets4[CAR_PART_FRONT_RIGHT_WHEEL].y=gWheelCentreOffsets4[CAR_PART_REAR_RIGHT_WHEEL].y; + + //Make an adjustment so that the the centre of the four wheels is at the origin. + //Again, this just makes it a lot easier to set the centre of mass because we have a known point + //that represents the origin. Also, it kind of makes sense that the default centre of mass is at the + //centre point of the wheels. + PxF32 wheelOffsetZ=0; + for(PxU32 i=0;i<=CAR_PART_REAR_RIGHT_WHEEL;i++) + { + wheelOffsetZ+=gWheelCentreOffsets4[i].z; + } + wheelOffsetZ*=0.25f; + gChassisMeshTransform.z+=wheelOffsetZ; + + //Reposition the mesh verts. + PxVec3* verts = const_cast<PxVec3*>(data.mVerts); + for(PxU32 i=0;i<data.mNbVerts;i++) + { + verts[i]-=gChassisMeshTransform; + } + + //Need a convex mesh for the chassis. + gChassisConvexMesh=createChassisConvexMesh(data.mVerts,data.mNbVerts,getPhysics(),getCooking()); + } + else if(0==Ps::strcmp(data.mName,gCarPartNames[CAR_PART_FRONT_LEFT_WHEEL])) + { + carPart=CAR_PART_FRONT_LEFT_WHEEL; + gWheelConvexMeshes4[CAR_PART_FRONT_LEFT_WHEEL]=createWheelConvexMesh(data.mVerts,data.mNbVerts,getPhysics(),getCooking()); + } + else if(0==Ps::strcmp(data.mName,gCarPartNames[CAR_PART_FRONT_RIGHT_WHEEL])) + { + carPart=CAR_PART_FRONT_RIGHT_WHEEL; + gWheelConvexMeshes4[CAR_PART_FRONT_RIGHT_WHEEL]=createWheelConvexMesh(data.mVerts,data.mNbVerts,getPhysics(),getCooking()); + } + else if(0==Ps::strcmp(data.mName,gCarPartNames[CAR_PART_REAR_LEFT_WHEEL])) + { + carPart=CAR_PART_REAR_LEFT_WHEEL; + gWheelConvexMeshes4[CAR_PART_REAR_LEFT_WHEEL]=createWheelConvexMesh(data.mVerts,data.mNbVerts,getPhysics(),getCooking()); + } + else if(0==Ps::strcmp(data.mName,gCarPartNames[CAR_PART_REAR_RIGHT_WHEEL])) + { + carPart=CAR_PART_REAR_RIGHT_WHEEL; + gWheelConvexMeshes4[CAR_PART_REAR_RIGHT_WHEEL]=createWheelConvexMesh(data.mVerts,data.mNbVerts,getPhysics(),getCooking()); + } + else if(0==Ps::strcmp(data.mName,gCarPartNames[CAR_PART_WINDOWS])) + { + carPart=CAR_PART_WINDOWS; + //Take the offset that was required to centre the chassis and apply it to everything that is dependent on the chassis transform. + PxVec3* verts = const_cast<PxVec3*>(data.mVerts); + for(PxU32 i=0;i<data.mNbVerts;i++) + { + verts[i]-=gChassisMeshTransform; + } + for(PxU32 i=0;i<=CAR_PART_REAR_RIGHT_WHEEL;i++) + { + gWheelCentreOffsets4[i]-=gChassisMeshTransform; + } + } + + RenderMeshActor* meshActor = createRenderMeshFromRawMesh(data); + PX_ASSERT(carPart!=0xffffffff); + gRenderMeshActors[carPart]=meshActor; + + //Store the wheel offsets from the centre. + for(PxU32 i=0;i<=CAR_PART_REAR_RIGHT_WHEEL;i++) + { + if(0==Ps::strcmp(data.mName,gCarPartNames[i])) + { + gWheelCentreOffsets4[i]=meshActor->getTransform().p; + gWheelCentreOffsets4[i].y-=gSuspensionShimHeight; + + //The left and right wheels seem to be mixed up. + //Swap them to correct this. + gWheelCentreOffsets4[i].x*=-1.0f; + } + } + } + else if(LOAD_TYPE_SKYDOME==gLoadType) + { + createRenderMeshFromRawMesh(data); + } + else + { + getSampleErrorCallback().reportError(PxErrorCode::eINTERNAL_ERROR, "Unknown mesh type", __FILE__, __LINE__); + } +} + +void SampleVehicle::onShutdown() +{ + { + PxSceneWriteLock scopedLock(*mScene); + for(PxU32 i=0;i<mNbIB;i++) + SAMPLE_FREE(mIB[i]); + SAMPLE_FREE(mTerrainVB); + +#if PX_DEBUG_VEHICLE_ON + mTelemetryData4W->free(); + mTelemetryData6W->free(); +#endif + mVehicleManager.shutdown(); + } + + PhysXSample::onShutdown(); + +#if defined(SERIALIZE_VEHICLE_BINARY) + if(mMemory) + SAMPLE_FREE(mMemory); +#endif +} + + +void SampleVehicle::onTickPreRender(PxF32 dtime) +{ + mScene->lockWrite(); + if(mFixCar) + { + //Get the transform of the last crossed waypoint and reset the player car + //at this transform. + resetFocusVehicleAtWaypoint(); + mFixCar=false; + //Reset the control logic driving the car back to start state to avoid mismatch + //between vehicle gears and state stored in vehicle controller. + mVehicleController.clear(); +#if PX_DEBUG_VEHICLE_ON + //Clear all the graph data because the discontinuity in car position makes the stored data redundant. + clearTelemetryData(); +#endif + } + else if(mBackToStart) + { + //Set the progress back to zero. + mWayPoints.setBackAtStart(); + //Get the transform of the last crossed waypoint (this will now be the start + //waypoint) and reset the player car at this transform. + resetFocusVehicleAtWaypoint(); + mBackToStart=false; + //Reset the control logic driving the car back to start state to avoid mismatch + //between vehicle gears and state stored in vehicle controller. + mVehicleController.clear(); +#if PX_DEBUG_VEHICLE_ON + //Clear all the graph data because the discontinuity in car position makes the stored data redundant. + clearTelemetryData(); +#endif + } + + //Only switch to 3-wheeled if driving a 4-wheeled car. + if(ePLAYER_VEHICLE_TYPE_VEHICLE4W==mPlayerVehicleType) + { + if(m3WModeIncremented) + { + const PxU32 old3WMode=m3WMode; + const PxU32 new3WMode=(m3WMode+1)%3; + if(0==old3WMode && 1==new3WMode) + { + mVehicleManager.switchTo3WDeltaMode(mPlayerVehicle); + } + else if(1==old3WMode && 2==new3WMode) + { + mVehicleManager.switchTo3WTadpoleMode(mPlayerVehicle); + } + else if(2==old3WMode && 0==new3WMode) + { + mVehicleManager.switchTo4WMode(mPlayerVehicle); + } + m3WModeIncremented=false; + m3WMode=new3WMode; + } + } + + //Make sure we can still update the camera in pause model. + if(mPause) + { + mCameraController.setInputs( + mControlInputs.getRotateY(), + mControlInputs.getRotateZ()); + updateCameraController(dtime, getActiveScene()); + } + + //Set the global transforms of all actors that have user data. + const size_t nbVehicleGraphicsMeshes = mVehicleGraphics.size(); + for(PxU32 i=0;i<nbVehicleGraphicsMeshes;i++) + { + //Get the mesh actor that represents a vehicle render component. + RenderMeshActor* actor = mVehicleGraphics[i]; + + //Get the data that associates the render component with a physics vehicle component. + const CarRenderUserData* carRenderUserData=(CarRenderUserData*)actor->mUserData; + const PxU8 carId=carRenderUserData->carId; + const PxU8 carPart=carRenderUserData->carPart; + const PxU8 carPartDependency=carRenderUserData->carPartDependency; + + //Get the physics shapes of the vehicle. + //The transform of these shapes will be applied to the render meshes. + PxShape* carShapes[PX_MAX_NB_WHEELS+1]; + const PxVehicleWheels& vehicle=*mVehicleManager.getVehicle(carId); + const PxU32 numShapes=vehicle.getRigidDynamicActor()->getNbShapes(); + const PxRigidDynamic& vehicleActor = *vehicle.getRigidDynamicActor(); + vehicleActor.getShapes(carShapes,numShapes); + + //Set the transform of the render component from the associated physics shape transform. + if(255==carPartDependency) + { + //The transform of this car component has been computed by the vehicle physics + //and stored in the composite bound of the car (chassis + wheels). + actor->setTransform(PxShapeExt::getGlobalPose(*carShapes[carPart], vehicleActor)); + + //update bounds of render actor, for camera cull + actor->setWorldBounds(PxShapeExt::getWorldBounds(*carShapes[carPart], vehicleActor)); + } + else + { + //The transform of this car component hasn't been computed by the vehicle physics. + //The transform is just an offset from another vehicle physics component. + //(This is kind of like a very,very simple skeleton of hierarchical transforms that would normally + //be used to render a vehicle). + actor->setTransform(PxShapeExt::getGlobalPose(*carShapes[carPartDependency], vehicleActor)); + + //update bounds of render actor, for camera cull + actor->setWorldBounds(PxShapeExt::getWorldBounds(*carShapes[carPartDependency], vehicleActor)); + } + } + + getCamera().lookAt(mCameraController.getCameraPos(), mCameraController.getCameraTar()); + + mScene->unlockWrite(); + + // Update the physics + PhysXSample::onTickPreRender(dtime); + +} + +void SampleVehicle::onTickPostRender(PxF32 dtime) +{ + // Fetch results + PhysXSample::onTickPostRender(dtime); + + if(mDebugRenderFlag) + { + drawWheels(); + drawVehicleDebug(); + } + + //Draw the next three way-points. + const RendererColor colors[3]={RendererColor(255,0,0),RendererColor(0,255,0),RendererColor(0,0,255)}; + PxVec3 v[3]; + PxVec3 w[3]; + PxU32 numPoints=0; + mWayPoints.getNextWayPointsAndLineDirs(numPoints,v[0],v[1],v[2],w[0],w[1],w[2]); + for(PxU32 i=0;i<numPoints;i++) + { + getDebugRenderer()->addLine(v[i],v[i]+PxVec3(0,5,0),colors[i]); + getDebugRenderer()->addLine(v[i]-w[i],v[i]+w[i],colors[i]); + } +} + +void SampleVehicle::onSubstep(PxF32 dtime) +{ + //Update the vehicle controls. + switch(mPlayerVehicleType) + { + case ePLAYER_VEHICLE_TYPE_VEHICLE4W: + case ePLAYER_VEHICLE_TYPE_VEHICLE6W: + mVehicleController.setCarKeyboardInputs( + mControlInputs.getAccelKeyPressed(), + mControlInputs.getBrakeKeyPressed(), + mControlInputs.getHandbrakeKeyPressed(), + mControlInputs.getSteerLeftKeyPressed(), + mControlInputs.getSteerRightKeyPressed(), + mControlInputs.getGearUpKeyPressed(), + mControlInputs.getGearDownKeyPressed()); + mVehicleController.setCarGamepadInputs( + mControlInputs.getAccel(), + mControlInputs.getBrake(), + mControlInputs.getSteer(), + mControlInputs.getGearUp(), + mControlInputs.getGearDown(), + mControlInputs.getHandbrake()); + break; + case ePLAYER_VEHICLE_TYPE_TANK4W: + case ePLAYER_VEHICLE_TYPE_TANK6W: + mVehicleController.setTankKeyboardInputs( + mControlInputs.getAccelKeyPressed(), + mControlInputs.getThrustLeftKeyPressed(), + mControlInputs.getThrustRightKeyPressed(), + mControlInputs.getBrakeLeftKeyPressed(), + mControlInputs.getBrakeRightKeyPressed(), + mControlInputs.getGearUpKeyPressed(), + mControlInputs.getGearDownKeyPressed()); + mVehicleController.setTankGamepadInputs( + mControlInputs.getAccel(), + mControlInputs.getThrustLeft(), + mControlInputs.getThrustRight(), + mControlInputs.getBrakeLeft(), + mControlInputs.getBrakeRight(), + mControlInputs.getGearUp(), + mControlInputs.getGearDown()); + break; + default: + PX_ASSERT(false); + break; + } + + updateVehicleController(dtime); + + //Update the vehicles. + mVehicleManager.suspensionRaycasts(&getActiveScene()); + + if (dtime > 0.0f) + { + PxSceneWriteLock scopedLock(*mScene); +#if PX_DEBUG_VEHICLE_ON + updateVehicleManager(dtime,getActiveScene().getGravity()); +#else + mVehicleManager.update(dtime,getActiveScene().getGravity()); +#endif + } + + //Update the camera. + mCameraController.setInputs( + mControlInputs.getRotateY(), + mControlInputs.getRotateZ()); + updateCameraController(dtime,getActiveScene()); + + //Update the revolute joints. + //If the joint has exceeded the rotation limit then reverse the drive velocity + //to make the joint rotate in the opposite direction. + for(PxU32 i=0;i<gNumRevoluteJoints;i++) + { + PxSceneWriteLock scopedLock(*mScene); + //Get the two actors of the joint. + PxRigidActor* actor0=NULL; + PxRigidActor* actor1=NULL; + gRevoluteJoints[i]->getActors(actor0,actor1); + + //Work out the rotation angle of the joint. + const PxF32 cosTheta=PxAbs(actor1->is<PxRigidDynamic>()->getGlobalPose().q.getBasisVector1().y); + const PxF32 theta=PxAcos(cosTheta); + + //If the joint rotation limit has been exceeded then reverse the drive direction. + //It's possible to reverse the direction but then after a timestep or two for it to still be beyond the rotation limit. + //To avoid switching back and forth don't switch drive direction until a minimum time has passed since the last drive direction change. + //Its possible that the pendulum has hit the car and is unable to reach the limit. A nice fix for this is to keep a track of the time + //passed since the last direction change and reverse the joint drive direction if a time limit has been reached. This gives the car + //a chance to escape the pendulum. + if((theta > gRevoluteJointMaxTheta && gRevoluteJointTimers[i]>4*dtime) || gRevoluteJointTimers[i] > 4*gRevoluteJointMaxTheta/gRevoluteJointDriveSpeeds[i]) + { + //Help the joint by setting the actor momenta to zero. + ((PxRigidDynamic*)actor1)->setLinearVelocity(PxVec3(0,0,0)); + ((PxRigidDynamic*)actor1)->setAngularVelocity(PxVec3(0,0,0)); + + //Switch the joint drive direction. + const PxF32 currDriveVel=gRevoluteJoints[i]->getDriveVelocity(); + const PxF32 newDriveVel=-currDriveVel; + gRevoluteJoints[i]->setDriveVelocity(newDriveVel); + + //Reset the timer. + gRevoluteJointTimers[i]=0; + } + + //Increment the joint timer. + gRevoluteJointTimers[i]+=dtime; + } + + { + PxSceneReadLock scopedLock(*mScene); + + //Update the progress around the track with the latest vehicle transform. + PxRigidDynamic* actor=getFocusVehicleRigidDynamicActor(); + mWayPoints.update(actor->getGlobalPose(),dtime); + + //Cache forward speed for the HUD to avoid making API calls while vehicle update is running + const PxVehicleWheels& focusVehicle = *mVehicleManager.getVehicle(mPlayerVehicle); + mForwardSpeedHud = focusVehicle.computeForwardSpeed(); + } +} + +void SampleVehicle::helpRender(PxU32 x, PxU32 y, PxU8 textAlpha) +{ + Renderer* renderer = getRenderer(); + const PxU32 yInc=18; + const PxF32 scale=0.5f; + const PxF32 shadowOffset=6.0f; + const RendererColor textColor(255, 255, 255, textAlpha); + const bool isKeyboardSupported = getApplication().getPlatform()->getSampleUserInput()->keyboardSupported(); + const bool isPadSupported = getApplication().getPlatform()->getSampleUserInput()->gamepadSupported(); + const char* msg; + + + if(ePLAYER_VEHICLE_TYPE_TANK4W==mPlayerVehicleType || ePLAYER_VEHICLE_TYPE_TANK6W==mPlayerVehicleType) + { + renderer->print(x, y += yInc, "TODO: document inputs for ePLAYER_VEHICLE_TYPE_TANK4W, ePLAYER_VEHICLE_TYPE_TANK6W", scale, shadowOffset, textColor); + if(PxVehicleDriveTankControlModel::eSPECIAL==mTankDriveModel) + { + } + else + { + } + } + else + { + if (isPadSupported && isKeyboardSupported) + renderer->print(x, y += yInc, "Use right stick or numpad keys to rotate the camera", scale, shadowOffset, textColor); + else if (isPadSupported) + renderer->print(x, y += yInc, "Use right stick to rotate the camera", scale, shadowOffset, textColor); + else if (isKeyboardSupported) + renderer->print(x, y += yInc, "Use numpad keys to rotate the camera", scale, shadowOffset, textColor); + + if (isPadSupported) + renderer->print(x, y += yInc, "Use left stick to steer", scale, shadowOffset, textColor); + + msg = mApplication.inputInfoMsg("Press "," for accelerate", VEH_ACCELERATE_PAD, VEH_ACCELERATE_KBD); + if(msg) + renderer->print(x, y += yInc, msg, scale, shadowOffset, textColor); + msg = mApplication.inputInfoMsg("Press "," for brake", CAR_BRAKE_PAD, CAR_BRAKE_KBD); + if(msg) + renderer->print(x, y += yInc, msg, scale, shadowOffset, textColor); + msg = mApplication.inputInfoMsg("Press "," to steer", CAR_STEER_LEFT_KBD, CAR_STEER_RIGHT_KBD); + if(msg) + renderer->print(x, y += yInc, msg, scale, shadowOffset, textColor); + } + + msg = mApplication.inputInfoMsg("Press "," for handbrake", CAR_HANDBRAKE_PAD, CAR_HANDBRAKE_KBD); + if(msg) + renderer->print(x, y += yInc, msg, scale, shadowOffset, textColor); + + if(!getFocusVehicleUsesAutoGears()) + { + msg = mApplication.inputInfoMsg("Press "," to gear up", VEH_GEAR_UP_PAD, VEH_GEAR_UP_KBD); + if(msg) + renderer->print(x, y += yInc, msg, scale, shadowOffset, textColor); + msg = mApplication.inputInfoMsg("Press "," to gear down", VEH_GEAR_DOWN_PAD, VEH_GEAR_DOWN_KBD); + if(msg) + renderer->print(x, y += yInc, msg, scale, shadowOffset, textColor); + } + + msg = mApplication.inputInfoMsg("Press "," to toggle car debug render",DEBUG_RENDER_FLAG , -1); + if(msg) + renderer->print(x, y += yInc, msg, scale, shadowOffset, textColor); + msg = mApplication.inputInfoMsg("Press "," to go back to start",RETRY, -1); + if(msg) + renderer->print(x, y += yInc, msg, scale, shadowOffset, textColor); + msg = mApplication.inputInfoMsg("Press "," to go back to last waypoint",FIX_CAR, -1); + if(msg) + renderer->print(x, y += yInc, msg, scale, shadowOffset, textColor); + +#if PX_DEBUG_VEHICLE_ON + if(mDebugRenderFlag) + { + msg = mApplication.inputInfoMsg("Press "," to increment wheel graphs", DEBUG_RENDER_WHEEL,-1); + if(msg) + renderer->print(x, y += yInc, msg, scale, shadowOffset, textColor); + msg = mApplication.inputInfoMsg("Press "," to increment central graphs", DEBUG_RENDER_ENGINE,-1); + if(msg) + renderer->print(x, y += yInc, msg, scale, shadowOffset, textColor); + } +#endif +} + +void SampleVehicle::descriptionRender(PxU32 x, PxU32 y, PxU8 textAlpha) +{ + bool print=(textAlpha!=0.0f); + + if(print) + { + Renderer* renderer = getRenderer(); + const PxU32 yInc = 24; + const PxReal scale = 0.5f; + const PxReal shadowOffset = 6.0f; + const RendererColor textColor(255, 255, 255, textAlpha); + + char line0[256]="This sample demonstrates vehicle simulation using PhysX. In particular,"; + char line1[256]="vehicle instantiation, the setup of vehicle description data, and"; + char line2[256]="integration with the PhysX SDK are all presented. Key concepts such"; + char line3[256]="as raycast and simulation filtering are illustrated as a means to"; + char line4[256]="tailor vehicle interaction with the scene. The setup and rendering"; + char line5[256]="of vehicle telemetry data is also shown. Finally, physics obstacles"; + char line6[256]="such as swinging pendula exemplify the configuration and run-time "; + char line7[256]="control of driven joints using PhysX."; + + renderer->print(x, y+=yInc, line0, scale, shadowOffset, textColor); + renderer->print(x, y+=yInc, line1, scale, shadowOffset, textColor); + renderer->print(x, y+=yInc, line2, scale, shadowOffset, textColor); + renderer->print(x, y+=yInc, line3, scale, shadowOffset, textColor); + renderer->print(x, y+=yInc, line4, scale, shadowOffset, textColor); + renderer->print(x, y+=yInc, line5, scale, shadowOffset, textColor); + renderer->print(x, y+=yInc, line6, scale, shadowOffset, textColor); + renderer->print(x, y+=yInc, line7, scale, shadowOffset, textColor); + } +} + +void SampleVehicle::customizeRender() +{ + drawHud(); + if(mDebugRenderFlag) + { + drawFocusVehicleGraphsAndPrintTireSurfaces(); + } + + const PxU32 width=getCamera().getScreenWidth(); + const PxU32 height=getCamera().getScreenHeight(); + + const PxU32 xCentre=280*width/800; + const PxU32 xRight=570*width/800; + const PxU32 yBottom=600*height/600; + + const PxU32 yInc=18; + + Renderer* renderer = getRenderer(); + + char time[64]; + sprintf(time, "Curr Lap Time: %1.1f \n", mWayPoints.getTimeElapsed()); + renderer->print(xRight, yBottom - yInc*2, time); + sprintf(time, "Best Lap Time: %1.1f \n", mWayPoints.getMinTimeElapsed()); + renderer->print(xRight, yBottom - yInc*3, time); + + if(!mCameraController.getIsLockedOnVehicleTransform()) + { + renderer->print(xCentre, yBottom - yInc*4, "Camera decoupled from car"); + } +} + +/////////////////////////////////////////////////////////////////////////////// + +PxFilterFlags SampleVehicleFilterShader( + PxFilterObjectAttributes attributes0, PxFilterData filterData0, + PxFilterObjectAttributes attributes1, PxFilterData filterData1, + PxPairFlags& pairFlags, const void* constantBlock, PxU32 constantBlockSize) +{ + PX_UNUSED(constantBlock); + PX_UNUSED(constantBlockSize); + + // let triggers through + if(PxFilterObjectIsTrigger(attributes0) || PxFilterObjectIsTrigger(attributes1)) + { + pairFlags = PxPairFlag::eTRIGGER_DEFAULT; + return PxFilterFlags(); + } + + + + // use a group-based mechanism for all other pairs: + // - Objects within the default group (mask 0) always collide + // - By default, objects of the default group do not collide + // with any other group. If they should collide with another + // group then this can only be specified through the filter + // data of the default group objects (objects of a different + // group can not choose to do so) + // - For objects that are not in the default group, a bitmask + // is used to define the groups they should collide with + if ((filterData0.word0 != 0 || filterData1.word0 != 0) && + !(filterData0.word0&filterData1.word1 || filterData1.word0&filterData0.word1)) + return PxFilterFlag::eSUPPRESS; + + pairFlags = PxPairFlag::eCONTACT_DEFAULT; + + // The pairFlags for each object are stored in word2 of the filter data. Combine them. + pairFlags |= PxPairFlags(PxU16(filterData0.word2 | filterData1.word2)); + return PxFilterFlags(); +} + + +void SampleVehicle::customizeSceneDesc(PxSceneDesc& sceneDesc) +{ + sceneDesc.filterShader = SampleVehicleFilterShader; + sceneDesc.flags |= PxSceneFlag::eREQUIRE_RW_LOCK; +} + +/////////////////////////////////////////////////////////////////////////////// + +void SampleVehicle::createStandardMaterials() +{ + const PxF32 restitutions[MAX_NUM_SURFACE_TYPES] = {0.2f, 0.2f, 0.2f, 0.2f}; + const PxF32 staticFrictions[MAX_NUM_SURFACE_TYPES] = {0.5f, 0.5f, 0.5f, 0.5f}; + const PxF32 dynamicFrictions[MAX_NUM_SURFACE_TYPES] = {0.5f, 0.5f, 0.5f, 0.5f}; + + for(PxU32 i=0;i<MAX_NUM_SURFACE_TYPES;i++) + { + //Create a new material. + mStandardMaterials[i] = getPhysics().createMaterial(staticFrictions[i], dynamicFrictions[i], restitutions[i]); + if(!mStandardMaterials[i]) + { + getSampleErrorCallback().reportError(PxErrorCode::eINTERNAL_ERROR, "createMaterial failed", __FILE__, __LINE__); + } + + //Set up the drivable surface type that will be used for the new material. + mVehicleDrivableSurfaceTypes[i].mType = i; + } + + mChassisMaterialDrivable = getPhysics().createMaterial(0.0f, 0.0f, 0.0f); + if(!mChassisMaterialDrivable) + { + getSampleErrorCallback().reportError(PxErrorCode::eINTERNAL_ERROR, "createMaterial failed", __FILE__, __LINE__); + } + + mChassisMaterialNonDrivable = getPhysics().createMaterial(1.0f, 1.0f, 0.0f); + if(!mChassisMaterialNonDrivable) + { + getSampleErrorCallback().reportError(PxErrorCode::eINTERNAL_ERROR, "createMaterial failed", __FILE__, __LINE__); + } +} + +/////////////////////////////////////////////////////////////////////////////// +static const char* getPlatformName() +{ +#if PX_X86 + return "PC32"; +#elif PX_X64 + return "PC64"; +#elif PX_ARM_FAMILY + return "ARM"; +#else + return ""; +#endif +} + +const char* SampleVehicle::getFocusVehicleName() +{ + switch(mPlayerVehicleType) + { + case ePLAYER_VEHICLE_TYPE_VEHICLE4W: + return "VEHICLE4W"; + case ePLAYER_VEHICLE_TYPE_TANK4W: + return "TANK4W"; + case ePLAYER_VEHICLE_TYPE_VEHICLE6W: + return "VEHICLE6W"; + case ePLAYER_VEHICLE_TYPE_TANK6W: + return "TANK6W"; + default: + return NULL; + } +} + +static PxU32 GetFileSize(const char* name) +{ + if(!name) return 0; + +#ifndef SEEK_END +#define SEEK_END 2 +#endif + + SampleFramework::File* fp; + if (PxToolkit::fopen_s(&fp, name, "rb")) + return 0; + fseek(fp, 0, SEEK_END); + PxU32 eof_ftell = (PxU32)ftell(fp); + fclose(fp); + return eof_ftell; +} + +void SampleVehicle::createVehicles() +{ + bool hasFocusVehicle = false; + //Make sure that we set the foundation before doing anything. + mVehicleManager.init(getPhysics(),(const PxMaterial**)mStandardMaterials,mVehicleDrivableSurfaceTypes); + + //Not added any vehicles yet. + gNumVehicleAdded=0; + + //Load the vehicle model (this will add the render actors for the chassis, 4 wheels, and windows). + gLoadType = LOAD_TYPE_VEHICLE; + importRAWFile("car2.raw", 1.0f); + + //The extra wheels of an 8-wheeled vehicle are instanced from the 4 wheels of the 4-wheeled car. + gRenderMeshActors[CAR_PART_EXTRA_WHEEL0]=gRenderMeshActors[CAR_PART_FRONT_LEFT_WHEEL]; + gRenderMeshActors[CAR_PART_EXTRA_WHEEL1]=gRenderMeshActors[CAR_PART_FRONT_RIGHT_WHEEL]; + + //Clear the array of render actors before adding the actors for each vehicle. + for(PxU32 i=0;i<mRenderActors.size();i++) + { + RenderBaseActor* renderActor=mRenderActors[i]; + renderActor->setRendering(false); + } + + //Load the player car. + switch(mPlayerVehicleType) + { + case ePLAYER_VEHICLE_TYPE_VEHICLE4W: + case ePLAYER_VEHICLE_TYPE_TANK4W: + { + for(PxU32 i=0;i<NUM_CAR4W_RENDER_COMPONENTS;i++) + { + gVehicleRenderUserData[gNumVehicleAdded][i]=gCar4WRenderUserData[i]; + gVehicleRenderUserData[gNumVehicleAdded][i].carId=PxU8(gNumVehicleAdded); + + RenderMeshActor* clone=SAMPLE_NEW(RenderMeshActor)(*gRenderMeshActors[i]); + clone->setRendering(true); + clone->mUserData=&gVehicleRenderUserData[gNumVehicleAdded][i]; + clone->setEnableCameraCull(true); + + mVehicleGraphics.push_back(clone); + mRenderActors.push_back(clone); + } + + mPlayerVehicle=0; + if(!hasFocusVehicle) + { + if(ePLAYER_VEHICLE_TYPE_VEHICLE4W==mPlayerVehicleType) + { + mVehicleManager.create4WVehicle(getActiveScene(),getPhysics(),getCooking(),*mChassisMaterialDrivable,gChassisMass,gWheelCentreOffsets4,gChassisConvexMesh,gWheelConvexMeshes4,gPlayerCarStartTransforms[0],true); + } + else + { + mVehicleManager.create4WTank(getActiveScene(),getPhysics(),getCooking(),*mChassisMaterialDrivable,gChassisMass,gWheelCentreOffsets4,gChassisConvexMesh,gWheelConvexMeshes4,gPlayerCarStartTransforms[0],true,mTankDriveModel); + } + } + + gNumVehicleAdded++; + } + break; + + case ePLAYER_VEHICLE_TYPE_VEHICLE6W: + case ePLAYER_VEHICLE_TYPE_TANK6W: + { + for(PxU32 i=0;i<NUM_CAR4W_RENDER_COMPONENTS;i++) + { + gVehicleRenderUserData[gNumVehicleAdded][i]=gCar6WRenderUserData[i]; + gVehicleRenderUserData[gNumVehicleAdded][i].carId=PxU8(gNumVehicleAdded); + + RenderMeshActor* clone=SAMPLE_NEW(RenderMeshActor)(*gRenderMeshActors[i]); + clone->setRendering(true); + clone->mUserData=&gVehicleRenderUserData[gNumVehicleAdded][i]; + clone->setEnableCameraCull(true); + + mVehicleGraphics.push_back(clone); + mRenderActors.push_back(clone); + } + + gVehicleRenderUserData[gNumVehicleAdded][CAR_PART_EXTRA_WHEEL0]=gCar6WRenderUserData[CAR_PART_EXTRA_WHEEL0]; + gVehicleRenderUserData[gNumVehicleAdded][CAR_PART_EXTRA_WHEEL1]=gCar6WRenderUserData[CAR_PART_EXTRA_WHEEL1]; + gVehicleRenderUserData[gNumVehicleAdded][CAR_PART_EXTRA_WHEEL0].carId = PxU8(gNumVehicleAdded); + gVehicleRenderUserData[gNumVehicleAdded][CAR_PART_EXTRA_WHEEL1].carId = PxU8(gNumVehicleAdded); + + //Add the extra wheels. + RenderMeshActor* clone; + clone = SAMPLE_NEW(RenderMeshActor)(*gRenderMeshActors[CAR_PART_EXTRA_WHEEL0]); + clone->setRendering(true); + clone->mUserData=&gVehicleRenderUserData[gNumVehicleAdded][CAR_PART_EXTRA_WHEEL0]; + clone->setEnableCameraCull(true); + mVehicleGraphics.push_back(clone); + mRenderActors.push_back(clone); + clone = SAMPLE_NEW(RenderMeshActor)(*gRenderMeshActors[CAR_PART_EXTRA_WHEEL1]); + clone->setRendering(true); + clone->mUserData=&gVehicleRenderUserData[gNumVehicleAdded][CAR_PART_EXTRA_WHEEL1]; + clone->setEnableCameraCull(true); + mVehicleGraphics.push_back(clone); + mRenderActors.push_back(clone); + + mPlayerVehicle=0; + + if(!hasFocusVehicle) + { + if(ePLAYER_VEHICLE_TYPE_VEHICLE6W==mPlayerVehicleType) + { + mVehicleManager.create6WVehicle(getActiveScene(),getPhysics(),getCooking(),*mChassisMaterialDrivable,gChassisMass,gWheelCentreOffsets4,gChassisConvexMesh,gWheelConvexMeshes4,gPlayerCarStartTransforms[0],true); + } + else + { + mVehicleManager.create6WTank(getActiveScene(),getPhysics(),getCooking(),*mChassisMaterialDrivable,gChassisMass,gWheelCentreOffsets4,gChassisConvexMesh,gWheelConvexMeshes4,gPlayerCarStartTransforms[0],true,mTankDriveModel); + } + } + gNumVehicleAdded++; + } + break; + + default: + PX_ASSERT(false); + break; + } + +#if NUM_NONPLAYER_4W_VEHICLES + for(PxU32 i=0;i<NUM_NONPLAYER_4W_VEHICLES;i++) + { + //Clone the meshes from the instanced meshes. + for(PxU32 j=0;j<NUM_CAR4W_RENDER_COMPONENTS;j++) + { + gVehicleRenderUserData[gNumVehicleAdded][j]=gCar4WRenderUserData[j]; + gVehicleRenderUserData[gNumVehicleAdded][j].carId=PxU8(gNumVehicleAdded); + + RenderMeshActor* clone = SAMPLE_NEW(RenderMeshActor)(*gRenderMeshActors[j]); + clone->setRendering(true); + clone->mUserData=&gVehicleRenderUserData[gNumVehicleAdded][j]; + clone->setEnableCameraCull(true); + + mVehicleGraphics.push_back(clone); + mRenderActors.push_back(clone); + } + + //Add the next vehicle. + mVehicleManager.create4WVehicle(getActiveScene(),getPhysics(),getCooking(),*mChassisMaterialNonDrivable,gChassisMass,gWheelCentreOffsets4,gChassisConvexMesh,gWheelConvexMeshes4,gVehicle4WStartTransforms[i],true); + + gNumVehicleAdded++; + } +#endif + +#if NUM_NONPLAYER_6W_VEHICLES + for(PxU32 i=0;i<NUM_NONPLAYER_6W_VEHICLES;i++) + { + //Clone the meshes from the instanced meshes. + for(PxU32 j=0;j<NUM_CAR4W_RENDER_COMPONENTS;j++) + { + gVehicleRenderUserData[gNumVehicleAdded][j]=gCar6WRenderUserData[j]; + gVehicleRenderUserData[gNumVehicleAdded][j].carId=PxU8(gNumVehicleAdded); + + RenderMeshActor* clone = SAMPLE_NEW(RenderMeshActor)(*gRenderMeshActors[j]); + clone->setRendering(true); + clone->mUserData=&gVehicleRenderUserData[gNumVehicleAdded][j]; + clone->setEnableCameraCull(true); + + mVehicleGraphics.push_back(clone); + mRenderActors.push_back(clone); + } + + //Add the extra wheels. + + gVehicleRenderUserData[gNumVehicleAdded][CAR_PART_EXTRA_WHEEL0]=gCar6WRenderUserData[CAR_PART_EXTRA_WHEEL0]; + gVehicleRenderUserData[gNumVehicleAdded][CAR_PART_EXTRA_WHEEL1]=gCar6WRenderUserData[CAR_PART_EXTRA_WHEEL1]; + gVehicleRenderUserData[gNumVehicleAdded][CAR_PART_EXTRA_WHEEL0].carId = PxU8(gNumVehicleAdded); + gVehicleRenderUserData[gNumVehicleAdded][CAR_PART_EXTRA_WHEEL1].carId = PxU8(gNumVehicleAdded); + + RenderMeshActor* clone; + clone = SAMPLE_NEW(RenderMeshActor)(*gRenderMeshActors[CAR_PART_EXTRA_WHEEL0]); + clone->setRendering(true); + clone->mUserData=&gVehicleRenderUserData[gNumVehicleAdded][CAR_PART_EXTRA_WHEEL0]; + clone->setEnableCameraCull(true); + mVehicleGraphics.push_back(clone); + mRenderActors.push_back(clone); + clone = SAMPLE_NEW(RenderMeshActor)(*gRenderMeshActors[CAR_PART_EXTRA_WHEEL1]); + clone->setRendering(true); + clone->mUserData=&gVehicleRenderUserData[gNumVehicleAdded][CAR_PART_EXTRA_WHEEL1]; + clone->setEnableCameraCull(true); + mVehicleGraphics.push_back(clone); + mRenderActors.push_back(clone); + + //Add the next vehicle. + mVehicleManager.create6WVehicle(getActiveScene(),getPhysics(),getCooking(),*mChassisMaterialNonDrivable,gChassisMass,gWheelCentreOffsets4,gChassisConvexMesh,gWheelConvexMeshes4,gVehicle6WStartTransforms[i],true); + + gNumVehicleAdded++; + } +#endif + +#if NUM_NONPLAYER_4W_TANKS + for(PxU32 i=0;i<NUM_NONPLAYER_4W_TANKS;i++) + { + //Clone the meshes from the instanced meshes. + for(PxU32 j=0;j<NUM_CAR4W_RENDER_COMPONENTS;j++) + { + gVehicleRenderUserData[gNumVehicleAdded][j]=gCar4WRenderUserData[j]; + gVehicleRenderUserData[gNumVehicleAdded][j].carId=PxU8(gNumVehicleAdded); + + RenderMeshActor* clone = SAMPLE_NEW(RenderMeshActor)(*gRenderMeshActors[j]); + clone->setRendering(true); + clone->mUserData=&gVehicleRenderUserData[gNumVehicleAdded][j]; + clone->setEnableCameraCull(true); + + mVehicleGraphics.push_back(clone); + mRenderActors.push_back(clone); + } + + mPlayerVehicle=0; + //Add the next vehicle. + mVehicleManager.create4WTank(getActiveScene(),getPhysics(),getCooking(),*mChassisMaterial,gChassisMass,gWheelCentreOffsets4,gChassisConvexMesh,gWheelConvexMeshes4,gTank4WStartTransforms[i],true, PxVehicleDriveTank::eDRIVE_MODEL_SPECIAL); + + gNumVehicleAdded++; + } +#endif + +#if NUM_NONPLAYER_6W_TANKS + for(PxU32 i=0;i<NUM_NONPLAYER_6W_TANKS;i++) + { + //Clone the meshes from the instanced meshes. + for(PxU32 j=0;j<NUM_CAR4W_RENDER_COMPONENTS;j++) + { + gVehicleRenderUserData[gNumVehicleAdded][j]=gTank6WRenderUserData[j]; + gVehicleRenderUserData[gNumVehicleAdded][j].carId=PxU8(gNumVehicleAdded); + + RenderMeshActor* clone = SAMPLE_NEW(RenderMeshActor)(*gRenderMeshActors[j]); + clone->setRendering(true); + clone->mUserData=&gVehicleRenderUserData[gNumVehicleAdded][j]; + clone->setEnableCameraCull(true); + + mVehicleGraphics.push_back(clone); + mRenderActors.push_back(clone); + } + + //Add the extra wheels. + + gVehicleRenderUserData[gNumVehicleAdded][CAR_PART_EXTRA_WHEEL0]=gTank6WRenderUserData[CAR_PART_EXTRA_WHEEL0]; + gVehicleRenderUserData[gNumVehicleAdded][CAR_PART_EXTRA_WHEEL1]=gTank6WRenderUserData[CAR_PART_EXTRA_WHEEL1]; + gVehicleRenderUserData[gNumVehicleAdded][CAR_PART_EXTRA_WHEEL0].carId = PxU8(gNumVehicleAdded); + gVehicleRenderUserData[gNumVehicleAdded][CAR_PART_EXTRA_WHEEL1].carId = PxU8(gNumVehicleAdded); + + RenderMeshActor* clone; + + clone = SAMPLE_NEW(RenderMeshActor)(*gRenderMeshActors[CAR_PART_EXTRA_WHEEL0]); + clone->setRendering(true); + clone->mUserData=&gVehicleRenderUserData[gNumVehicleAdded][CAR_PART_EXTRA_WHEEL0]; + clone->setEnableCameraCull(true); + mVehicleGraphics.push_back(clone); + mRenderActors.push_back(clone); + + clone = SAMPLE_NEW(RenderMeshActor)(*gRenderMeshActors[CAR_PART_EXTRA_WHEEL1]); + clone->setRendering(true); + clone->mUserData=&gVehicleRenderUserData[gNumVehicleAdded][CAR_PART_EXTRA_WHEEL1]; + clone->setEnableCameraCull(true); + mVehicleGraphics.push_back(clone); + mRenderActors.push_back(clone); + + //Add the next vehicle. + mVehicleManager.create6WTank(getActiveScene(),getPhysics(),getCooking(),*mChassisMaterial,gChassisMass,gWheelCentreOffsets4,gChassisConvexMesh,gWheelConvexMeshes4,gTank6WStartTransforms[i],true); + + gNumVehicleAdded++; + } +#endif +} + +PxRigidStatic* SampleVehicle::addStaticObstacle +(const PxTransform& transform, const PxU32 numShapes, PxTransform* shapeTransforms, PxGeometry** shapeGeometries, PxMaterial** shapeMaterials) +{ + PxFilterData simFilterData; + simFilterData.word0=COLLISION_FLAG_GROUND; + simFilterData.word1=COLLISION_FLAG_GROUND_AGAINST; + PxFilterData qryFilterData; + SampleVehicleSetupDrivableShapeQueryFilterData(&qryFilterData); + + PxRigidStatic* actor=getPhysics().createRigidStatic(transform); + for(PxU32 i=0;i<numShapes;i++) + { + PxShape* shape=PxRigidActorExt::createExclusiveShape(*actor, *shapeGeometries[i], *shapeMaterials[i]); + shape->setLocalPose(shapeTransforms[i]); + shape->setSimulationFilterData(simFilterData); + shape->setQueryFilterData(qryFilterData); + } + getActiveScene().addActor(*actor); + createRenderObjectsFromActor(actor); + return actor; +} + +PxRigidDynamic* SampleVehicle::addDynamicObstacle +(const PxTransform& transform, const PxF32 mass, const PxU32 numShapes, PxTransform* shapeTransforms, PxGeometry** shapeGeometries, PxMaterial** shapeMaterials) +{ + PxFilterData simFilterData; + simFilterData.word0=COLLISION_FLAG_OBSTACLE; + simFilterData.word1=COLLISION_FLAG_OBSTACLE_AGAINST; + PxFilterData qryFilterData; + SampleVehicleSetupNonDrivableShapeQueryFilterData(&qryFilterData); + + PxRigidDynamic* actor = getPhysics().createRigidDynamic(transform); + for(PxU32 i=0;i<numShapes;i++) + { + PxShape* shape = PxRigidActorExt::createExclusiveShape(*actor, *shapeGeometries[i], *shapeMaterials[i]); + shape->setLocalPose(shapeTransforms[i]); + shape->setSimulationFilterData(simFilterData); + shape->setQueryFilterData(qryFilterData); + } + + PxRigidBodyExt::setMassAndUpdateInertia(*actor,mass); + getActiveScene().addActor(*actor); + createRenderObjectsFromActor(actor); + return actor; +} + +PxRigidDynamic* SampleVehicle::addDynamicDrivableObstacle +(const PxTransform& transform, const PxF32 mass, const PxU32 numShapes, PxTransform* shapeTransforms, PxGeometry** shapeGeometries, PxMaterial** shapeMaterials) +{ + PxFilterData simFilterData; + simFilterData.word0=COLLISION_FLAG_DRIVABLE_OBSTACLE; + simFilterData.word1=COLLISION_FLAG_DRIVABLE_OBSTACLE_AGAINST; + PxFilterData qryFilterData; + SampleVehicleSetupDrivableShapeQueryFilterData(&qryFilterData); + + PxRigidDynamic* actor = getPhysics().createRigidDynamic(transform); + for(PxU32 i=0;i<numShapes;i++) + { + PxShape* shape = PxRigidActorExt::createExclusiveShape(*actor, *shapeGeometries[i], *shapeMaterials[i]); + shape->setLocalPose(shapeTransforms[i]); + shape->setSimulationFilterData(simFilterData); + shape->setQueryFilterData(qryFilterData); + } + + PxRigidBodyExt::setMassAndUpdateInertia(*actor,mass); + getActiveScene().addActor(*actor); + createRenderObjectsFromActor(actor); + return actor; +} + +void SampleVehicle::createStack(PxU32 numBaseBoxes, PxF32 boxSize, const PxVec3& pos, const PxQuat& quat) +{ + const PxF32 density=50.0f; + + const PxF32 sizeX = boxSize; + const PxF32 sizeY = boxSize; + const PxF32 sizeZ = boxSize; + + const PxF32 mass = boxSize*boxSize*boxSize*density; + const PxVec3 halfExtents(sizeX*0.5f,sizeY*0.5f,sizeZ*0.5f); + PxBoxGeometry geometry(halfExtents); + PxTransform shapeTransforms[1]={PxTransform(PxIdentity)}; + PxGeometry* shapeGeometries[1]={&geometry}; + PxMaterial* shapeMaterials[1]={mStandardMaterials[SURFACE_TYPE_TARMAC]}; + + const PxF32 spacing = 0.0001f; + PxVec3 relPos(0.0f, sizeY/2, 0.0f); + PxF32 offsetX = -(numBaseBoxes * (sizeX + spacing) * 0.5f); + PxF32 offsetZ = 0.0f; + while(numBaseBoxes) + { + for(PxU32 i=0;i<numBaseBoxes ;i++) + { + relPos.x = offsetX + (PxF32)i * (sizeX + spacing); + relPos.z = offsetZ; + + PxTransform transform(pos + quat.rotate(relPos),quat); + addDynamicObstacle(transform,mass,1,shapeTransforms,shapeGeometries,shapeMaterials); + } + + offsetX += sizeX/2; + relPos.y += (sizeY + spacing); + numBaseBoxes--; + } +} + +void SampleVehicle::createWall(const PxU32 numHorizontalBoxes, const PxU32 numVerticalBoxes, const PxF32 boxSize, const PxVec3& pos, const PxQuat& quat) +{ + const PxF32 density=50.0f; + + const PxF32 sizeX = boxSize; + const PxF32 sizeY = boxSize; + const PxF32 sizeZ = boxSize; + + const PxF32 mass = sizeX*sizeY*sizeZ*density; + const PxVec3 halfExtents(sizeX*0.5f,sizeY*0.5f,sizeZ*0.5f); + PxBoxGeometry geometry(halfExtents); + PxTransform shapeTransforms[1] = {PxTransform(PxIdentity)}; + PxGeometry* shapeGeometries[1] = {&geometry}; + PxMaterial* shapeMaterials[1] = {mStandardMaterials[SURFACE_TYPE_TARMAC]}; + + const PxF32 spacing = 0.0001f; + PxVec3 relPos(0.0f, sizeY/2, 0.0f); + PxF32 offsetX = -(numHorizontalBoxes * (sizeX + spacing) * 0.5f); + PxF32 offsetZ = 0.0f; + + for(PxU32 k=0;k<numVerticalBoxes;k++) + { + for(PxU32 i=0;i<numHorizontalBoxes;i++) + { + relPos.x = offsetX + (sizeX + spacing)*i; + relPos.z = offsetZ; + PxTransform transform(pos + quat.rotate(relPos),quat); + addDynamicObstacle(transform,mass,1,shapeTransforms,shapeGeometries,shapeMaterials); + } + + if(0==(k%2)) + { + offsetX += sizeX/2; + } + else + { + offsetX -= sizeX/2; + } + relPos.y += (sizeY + spacing); + } +} + +void SampleVehicle::createObstacles() +{ + PxSceneWriteLock scopedLock(*mScene); + //Create some giant pendula + { + PxTransform shapeTransforms[3]={PxTransform(PxIdentity),PxTransform(PxIdentity),PxTransform(PxIdentity)}; + PxMaterial* shapeMaterials[3]={NULL,NULL,NULL}; + PxGeometry* shapeGeometries[3]={NULL,NULL,NULL}; + PxShape* shapes[3]={NULL,NULL,NULL}; + + gNumRevoluteJoints=0; + + for(PxU32 i=0;i<MAX_NUM_PENDULA;i++) + { + //Get the transform to position the next pendulum ball. + const PxTransform& ballStartTransform=gPendulaBallStartTransforms[i]; + + //Pendulum made of two shapes : a sphere for the ball and a cylinder for the shaft. + //In the absence of a special material for pendula just use the tarmac material. + PxSphereGeometry geomBall(gPendulumBallRadius); + shapeGeometries[0]=&geomBall; + shapeTransforms[0]=PxTransform(PxIdentity); + shapeMaterials[0]=mStandardMaterials[SURFACE_TYPE_TARMAC]; + PxConvexMeshGeometry geomShaft(createCylinderConvexMesh(gPendulumShaftLength, gPendulumShaftWidth, 8, getPhysics(), getCooking())); + shapeGeometries[1]=&geomShaft; + shapeTransforms[1]=PxTransform(PxVec3(0, 0.5f*gPendulumShaftLength, 0), PxQuat(PxHalfPi, PxVec3(0,0,1))), + shapeMaterials[1]=mStandardMaterials[SURFACE_TYPE_TARMAC]; + + //Ready to add the pendulum as a dynamic object. + PxRigidDynamic* actor=addDynamicObstacle(ballStartTransform,gPendulumBallMass,2,shapeTransforms,shapeGeometries,shapeMaterials); + + //As an optimization we don't want pendulum to intersect with static geometry because the position and + //limits on joint rotation will ensure that this is already impossible. + actor->getShapes(shapes,2); + PxFilterData simFilterData=shapes[0]->getSimulationFilterData(); + simFilterData.word1 &= ~COLLISION_FLAG_GROUND; + shapes[0]->setSimulationFilterData(simFilterData); + shapes[1]->setSimulationFilterData(simFilterData); + //As a further optimization lets set the pendulum shapes to be non-drivable surfaces. + PxFilterData qryFilterData; + SampleVehicleSetupNonDrivableShapeQueryFilterData(&qryFilterData); + shapes[0]->setQueryFilterData(qryFilterData); + shapes[1]->setQueryFilterData(qryFilterData); + + //Add static geometry to give the appearance that something is physically supporting the pendulum. + //This supporting geometry is just a vertical bar and two horizontal bars. + const PxF32 groundClearance=3.0f; + PxConvexMeshGeometry geomHorizontalBar(createCylinderConvexMesh(gPendulumSuspensionStructureWidth, gPendulumShaftWidth, 8, getPhysics(), getCooking())); + PxConvexMeshGeometry geomVerticalBar(createCylinderConvexMesh(gPendulumShaftLength+groundClearance, gPendulumShaftWidth, 8, getPhysics(), getCooking())); + shapeGeometries[0]=&geomHorizontalBar; + shapeMaterials[0]=mStandardMaterials[SURFACE_TYPE_TARMAC]; + shapeTransforms[0]=PxTransform(PxVec3(0, gPendulumShaftLength, 0), PxQuat(PxIdentity)); + shapeGeometries[1]=&geomVerticalBar; + shapeMaterials[1]=mStandardMaterials[SURFACE_TYPE_TARMAC]; + shapeTransforms[1]=PxTransform(PxVec3(0.5f*gPendulumSuspensionStructureWidth, 0.5f*(gPendulumShaftLength-groundClearance), 0), PxQuat(PxHalfPi, PxVec3(0,0,1))); + shapeGeometries[2]=&geomVerticalBar; + shapeMaterials[2]=mStandardMaterials[SURFACE_TYPE_TARMAC]; + shapeTransforms[2]=PxTransform(PxVec3(-0.5f*gPendulumSuspensionStructureWidth, 0.5f*(gPendulumShaftLength-groundClearance), 0), PxQuat(PxHalfPi, PxVec3(0,0,1))); + + //Ready to add the support geometry as a static object. + PxRigidStatic* staticActor=addStaticObstacle(ballStartTransform,3,shapeTransforms,shapeGeometries,shapeMaterials); + + //As an optimization lets disable collision with the dynamic pendulum because the joint limits will make + //collision impossible. + staticActor->getShapes(shapes,3); + simFilterData=shapes[0]->getSimulationFilterData(); + simFilterData.word1 &= ~COLLISION_FLAG_OBSTACLE; + shapes[0]->setSimulationFilterData(simFilterData); + shapes[1]->setSimulationFilterData(simFilterData); + shapes[2]->setSimulationFilterData(simFilterData); + + //Now finally add the joint that will create the pendulum behaviour : rotation around a single axis. + const PxVec3 pendulumPos=ballStartTransform.p + PxVec3(0, gPendulumShaftLength, 0); + PxQuat pendulumRotation=PxQuat(PxHalfPi,PxVec3(0,1,0)); + PxRevoluteJoint* joint=PxRevoluteJointCreate + (getPhysics(), + NULL, PxTransform(pendulumPos, ballStartTransform.q*pendulumRotation), + actor, PxTransform(PxVec3(0,gPendulumShaftLength,0), pendulumRotation)); + joint->setDriveVelocity(gRevoluteJointDriveSpeeds[i]); + joint->setRevoluteJointFlag(PxRevoluteJointFlag::eDRIVE_ENABLED, true); + gRevoluteJoints[gNumRevoluteJoints]=joint; + gNumRevoluteJoints++; + } + + //Work out the maximum angle of rotation allowed before the pendulum hits the support geometry. + //We're going to monitor the pendulum's progress at each update and reverse the pendulum drive speed + //if the limit is exceed. + const PxF32 sinTheta=(gPendulumSuspensionStructureWidth*0.5f - gPendulumBallRadius)/gPendulumShaftLength; + gRevoluteJointMaxTheta=PxAsin(sinTheta); + } + + //Create a see-saw + { + //See-saw made of two separate objects : a static prism-shaped base and a ramp that balances on top of the prism. + //In the absence of a special material for see-saws just reuse the tarmac material. + PxTransform shapeTransforms[1]={PxTransform(PxIdentity)}; + PxMaterial* shapeMaterials[1]={mStandardMaterials[SURFACE_TYPE_TARMAC]}; + PxGeometry* shapeGeometries[1]={NULL}; + + //Add the static prism-shaped object. + PxTransform tBase(PxVec3( -132.940292 , 8.664189 , -116.392891 ), PxQuat( -0.000319 , 0.348920 , -0.000129 , -0.937153 ) ); + PxConvexMesh* meshBase=createPrismConvexMesh(12,3.0f,4.5f,getPhysics(), getCooking()); + PxConvexMeshGeometry geomBase(meshBase); + shapeGeometries[0]=&geomBase; + addStaticObstacle(tBase,1,shapeTransforms,shapeGeometries,shapeMaterials); + + //Add the dynamic ramp that balances on the prism. + PxTransform tRamp(PxVec3( -130.357010 , 12.584847 , -119.381256 ), PxQuat( 0.088919 , 0.347436 , 0.033112 , -0.932891 ) ) ; + PxConvexMesh* meshRamp=createSquashedCuboidMesh(6.0f, 40.0f, 0.25f, 0.065f, getPhysics(), getCooking()); + PxConvexMeshGeometry geomRamp(meshRamp); + shapeGeometries[0]=&geomRamp; + addDynamicDrivableObstacle(tRamp,1000.0f,1,shapeTransforms,shapeGeometries,shapeMaterials); + } + + //Add a really big ramp to jump over the car stack. + { + PxVec3 halfExtentsRamp(5.0f,1.9f,7.0f); + PxConvexMeshGeometry geomRamp(createWedgeConvexMesh(halfExtentsRamp,getPhysics(),getCooking())); + PxTransform shapeTransforms[1]={PxTransform(PxIdentity)}; + PxMaterial* shapeMaterials[1]={mStandardMaterials[SURFACE_TYPE_TARMAC]}; + PxGeometry* shapeGeometries[1]={&geomRamp}; + PxTransform tRamp(PxVec3( -89.849564 , 9.950000 , 154.516617 ), PxQuat( -0.000002 , -0.837118 , -0.000004 , 0.547022 ) ); + addStaticObstacle(tRamp,1,shapeTransforms,shapeGeometries,shapeMaterials); + } + + //Add two ramps side by side with a gap in between + { + PxVec3 halfExtents(3.0f,1.5f,3.5f); + PxConvexMeshGeometry geometry(createWedgeConvexMesh(halfExtents,getPhysics(),getCooking())); + PxTransform shapeTransforms[1]={PxTransform(PxIdentity)}; + PxMaterial* shapeMaterials[1]={mStandardMaterials[SURFACE_TYPE_TARMAC]}; + PxGeometry* shapeGeometries[1]={&geometry}; + PxTransform t1(PxVec3( 112.797081 , 10.086022 , 134.419052 ), PxQuat( 0.000013 , -0.406322 , 0.000006 , 0.913730 ) ); + addStaticObstacle(t1,1,shapeTransforms,shapeGeometries,shapeMaterials); + PxTransform t2(PxVec3( 120.135361 , 10.086023 , 140.594055 ), PxQuat( 0.000013 , -0.406322 , 0.000006 , 0.913730 ) ); + addStaticObstacle(t2,1,shapeTransforms,shapeGeometries,shapeMaterials); + } + + //Add a wall made of dynamic objects with cuboid shapes for bricks. + { + PxTransform t(PxVec3( -37.525650 , 9.864201 , -77.926567 ), PxQuat( -0.000286 , 0.728016 , -0.000290 , -0.685561 ) ) ; + createWall(12,4,1.0f,t.p,t.q); + } + + //Create a kind of cattle grid of cylindrical rods. + { + //Cattle grid made out of 128 identical cylindrical rods. + //Need to instantiate geometry used for the rods. + const PxF32 logRadius=0.125f; + PxConvexMesh* mesh=createCylinderConvexMesh(10.0f,logRadius,8,getPhysics(),getCooking()); + PxConvexMeshGeometry geom(mesh); + + //Set up transform, geometry, and material of each cylindrical rod shape. + PxGeometry* shapeGeometries[128]; + PxMaterial* shapeMaterials[128]; + PxTransform shapeTransforms[128]; + PxTransform shapeTransform=PxTransform(PxVec3(0,0,0),PxQuat(PxIdentity)); + for(PxU32 i=0;i<128;i++) + { + shapeTransforms[i]=shapeTransform; + shapeGeometries[i]=&geom; + shapeMaterials[i]=mStandardMaterials[SURFACE_TYPE_TARMAC]; + + //Work out the position of the next cylindrical rod. + shapeTransform.p.z += (2.40f*logRadius); + shapeTransform.p.y += 0.0025f; + } + + //Ready to add the cattle grid as a static object with a composite bound of 128 cylindrical rods. + PxTransform t(PxVec3( -160.972595 , 8.739249 , -74.141998 ), PxQuat( 0.000407 , -0.165312 , 0.000060 , 0.986241 ) ) ; + addStaticObstacle(t,128,shapeTransforms,shapeGeometries,shapeMaterials); + } + + //Add three static walls + { + PxBoxGeometry box(8,2,1); + PxTransform shapeTransforms[1]={PxTransform(PxIdentity)}; + PxGeometry* shapeGeometries[1]={&box}; + PxMaterial* shapeMaterials[1]={mStandardMaterials[SURFACE_TYPE_TARMAC]}; + + PxTransform t1(PxVec3( -175.981186 , 9.864196 , -25.040220 ), PxQuat( -0.000417 , 0.042262 , -0.000009 , -0.999106 ) ); + addStaticObstacle(t1,1,shapeTransforms,shapeGeometries,shapeMaterials); + PxTransform t2(PxVec3( -174.972122 , 9.864214 , 32.517246 ), PxQuat( -0.000384 , -0.080625 , 0.000019 , -0.996744 ) ) ; + addStaticObstacle(t2,1,shapeTransforms,shapeGeometries,shapeMaterials); + PxTransform t3(PxVec3( 157.825897 , 9.864218 , -83.961632 ), PxQuat( -0.000124 , 0.997806 , -0.000358 , -0.066201 ) ); + addStaticObstacle(t3,1,shapeTransforms,shapeGeometries,shapeMaterials); + } +} + +void SampleVehicle::collectInputEvents(std::vector<const SampleFramework::InputEvent*>& inputEvents) +{ + PhysXSample::collectInputEvents(inputEvents); + + getApplication().getPlatform()->getSampleUserInput()->unregisterInputEvent(CAMERA_GAMEPAD_MOVE_LEFT_RIGHT); + getApplication().getPlatform()->getSampleUserInput()->unregisterInputEvent(CAMERA_GAMEPAD_MOVE_FORWARD_BACK); + getApplication().getPlatform()->getSampleUserInput()->unregisterInputEvent(SPAWN_DEBUG_OBJECT); + getApplication().getPlatform()->getSampleUserInput()->unregisterInputEvent(MENU_VISUALIZATIONS); + getApplication().getPlatform()->getSampleUserInput()->unregisterInputEvent(HIDE_GRAPHICS); + getApplication().getPlatform()->getSampleUserInput()->unregisterInputEvent(VARIABLE_TIMESTEP); + + DIGITAL_INPUT_EVENT_DEF(VEH_SAVE_KBD, WKEY_I, XKEY_I, X1KEY_I, PS3KEY_I, PS4KEY_I, AKEY_UNKNOWN, SCAN_CODE_FORWARD, IKEY_UNKNOWN, SCAN_CODE_FORWARD, WIIUKEY_UNKNOWN); + + + //Driving keyboard controls. + if(ePLAYER_VEHICLE_TYPE_TANK4W==mPlayerVehicleType || ePLAYER_VEHICLE_TYPE_TANK6W==mPlayerVehicleType) + { + DIGITAL_INPUT_EVENT_DEF(VEH_GEAR_DOWN_KBD, SCAN_CODE_9, XKEY_9, X1KEY_9, PS3KEY_9, PS4KEY_9, AKEY_UNKNOWN, SCAN_CODE_9, IKEY_UNKNOWN, SCAN_CODE_9, WIIUKEY_UNKNOWN); + DIGITAL_INPUT_EVENT_DEF(VEH_GEAR_UP_KBD, SCAN_CODE_0, XKEY_0, X1KEY_0, PS3KEY_0, PS4KEY_0, AKEY_UNKNOWN, SCAN_CODE_0, IKEY_UNKNOWN, SCAN_CODE_0, WIIUKEY_UNKNOWN); + + DIGITAL_INPUT_EVENT_DEF(TANK_THRUST_LEFT_KBD, WKEY_Q, XKEY_S, X1KEY_S, PS3KEY_S, PS4KEY_S, AKEY_UNKNOWN, SCAN_CODE_BACKWARD, IKEY_UNKNOWN, SCAN_CODE_BACKWARD, WIIUKEY_UNKNOWN); + DIGITAL_INPUT_EVENT_DEF(TANK_THRUST_RIGHT_KBD, WKEY_I, XKEY_A, X1KEY_A, PS3KEY_A, PS4KEY_A, AKEY_UNKNOWN, SCAN_CODE_LEFT, IKEY_UNKNOWN, SCAN_CODE_LEFT, WIIUKEY_UNKNOWN); + DIGITAL_INPUT_EVENT_DEF(TANK_BRAKE_LEFT_KBD, WKEY_A, XKEY_D, X1KEY_D, PS3KEY_D, PS4KEY_D, AKEY_UNKNOWN, SCAN_CODE_RIGHT, IKEY_UNKNOWN, SCAN_CODE_RIGHT, GAMEPAD_LEFT_SHOULDER_BOT); + DIGITAL_INPUT_EVENT_DEF(TANK_BRAKE_RIGHT_KBD, WKEY_J, XKEY_L, X1KEY_L, PS3KEY_L, PS4KEY_L, AKEY_UNKNOWN, SCAN_CODE_L, IKEY_UNKNOWN, SCAN_CODE_L, GAMEPAD_RIGHT_SHOULDER_BOT); + } + else + { + DIGITAL_INPUT_EVENT_DEF(VEH_ACCELERATE_KBD, SCAN_CODE_FORWARD, XKEY_W, X1KEY_W, PS3KEY_W, PS4KEY_W, AKEY_UNKNOWN, SCAN_CODE_FORWARD, IKEY_UNKNOWN, SCAN_CODE_FORWARD, GAMEPAD_RIGHT_SHOULDER_BOT); + DIGITAL_INPUT_EVENT_DEF(VEH_GEAR_DOWN_KBD, SCAN_CODE_9, XKEY_9, X1KEY_9, PS3KEY_9, PS4KEY_9, AKEY_UNKNOWN, SCAN_CODE_9, IKEY_UNKNOWN, SCAN_CODE_9, WIIUKEY_UNKNOWN); + DIGITAL_INPUT_EVENT_DEF(VEH_GEAR_UP_KBD, SCAN_CODE_0, XKEY_0, X1KEY_0, PS3KEY_0, PS4KEY_0, AKEY_UNKNOWN, SCAN_CODE_0, IKEY_UNKNOWN, SCAN_CODE_0, WIIUKEY_UNKNOWN); + + DIGITAL_INPUT_EVENT_DEF(CAR_BRAKE_KBD, SCAN_CODE_BACKWARD, XKEY_S, X1KEY_S, PS3KEY_S, PS4KEY_S, AKEY_UNKNOWN, SCAN_CODE_BACKWARD, IKEY_UNKNOWN, SCAN_CODE_BACKWARD, GAMEPAD_LEFT_SHOULDER_BOT); + DIGITAL_INPUT_EVENT_DEF(CAR_HANDBRAKE_KBD, SCAN_CODE_L, XKEY_L, X1KEY_L, PS3KEY_L, PS4KEY_L, AKEY_UNKNOWN, SCAN_CODE_L, IKEY_UNKNOWN, SCAN_CODE_L, WIIUKEY_UNKNOWN); + DIGITAL_INPUT_EVENT_DEF(CAR_STEER_LEFT_KBD, SCAN_CODE_LEFT, XKEY_A, X1KEY_A, PS3KEY_A, PS4KEY_A, AKEY_UNKNOWN, SCAN_CODE_LEFT, IKEY_UNKNOWN, SCAN_CODE_LEFT, WIIUKEY_UNKNOWN); + DIGITAL_INPUT_EVENT_DEF(CAR_STEER_RIGHT_KBD, SCAN_CODE_RIGHT, XKEY_D, X1KEY_D, PS3KEY_D, PS4KEY_D, AKEY_UNKNOWN, SCAN_CODE_RIGHT, IKEY_UNKNOWN, SCAN_CODE_RIGHT, WIIUKEY_UNKNOWN); + } + + //Driving gamepad controls + if(ePLAYER_VEHICLE_TYPE_TANK4W==mPlayerVehicleType || ePLAYER_VEHICLE_TYPE_TANK6W==mPlayerVehicleType) + { + DIGITAL_INPUT_EVENT_DEF(VEH_GEAR_DOWN_PAD, GAMEPAD_EAST, GAMEPAD_EAST, GAMEPAD_EAST, GAMEPAD_EAST, GAMEPAD_EAST, AKEY_UNKNOWN, OSXKEY_UNKNOWN, IKEY_UNKNOWN, LINUXKEY_UNKNOWN, GAMEPAD_EAST); + DIGITAL_INPUT_EVENT_DEF(VEH_GEAR_UP_PAD, GAMEPAD_NORTH, GAMEPAD_NORTH, GAMEPAD_NORTH, GAMEPAD_NORTH, GAMEPAD_NORTH, AKEY_UNKNOWN, OSXKEY_UNKNOWN, IKEY_UNKNOWN, LINUXKEY_UNKNOWN, GAMEPAD_NORTH); + + if(PxVehicleDriveTankControlModel::eSPECIAL==mTankDriveModel) + { + ANALOG_INPUT_EVENT_DEF(TANK_THRUST_LEFT_PAD, GAMEPAD_DEFAULT_SENSITIVITY, GAMEPAD_LEFT_STICK_Y, GAMEPAD_LEFT_STICK_Y, GAMEPAD_LEFT_STICK_Y, GAMEPAD_LEFT_STICK_Y, GAMEPAD_LEFT_STICK_Y, GAMEPAD_LEFT_STICK_Y, OSXKEY_UNKNOWN, GAMEPAD_LEFT_STICK_Y, LINUXKEY_UNKNOWN, GAMEPAD_LEFT_STICK_Y); + ANALOG_INPUT_EVENT_DEF(TANK_THRUST_RIGHT_PAD, GAMEPAD_DEFAULT_SENSITIVITY, GAMEPAD_RIGHT_STICK_Y, GAMEPAD_RIGHT_STICK_Y, GAMEPAD_RIGHT_STICK_Y, GAMEPAD_RIGHT_STICK_Y, GAMEPAD_RIGHT_STICK_Y, GAMEPAD_RIGHT_STICK_Y, OSXKEY_UNKNOWN, GAMEPAD_RIGHT_STICK_Y, LINUXKEY_UNKNOWN, GAMEPAD_RIGHT_STICK_Y); + ANALOG_INPUT_EVENT_DEF(TANK_BRAKE_LEFT_PAD, GAMEPAD_DEFAULT_SENSITIVITY, GAMEPAD_LEFT_SHOULDER_BOT, GAMEPAD_LEFT_SHOULDER_BOT, GAMEPAD_LEFT_SHOULDER_BOT, GAMEPAD_LEFT_SHOULDER_BOT, GAMEPAD_LEFT_SHOULDER_BOT, AKEY_UNKNOWN, OSXKEY_UNKNOWN, IKEY_UNKNOWN, LINUXKEY_UNKNOWN, WIIUKEY_UNKNOWN); + ANALOG_INPUT_EVENT_DEF(TANK_BRAKE_RIGHT_PAD, GAMEPAD_DEFAULT_SENSITIVITY, GAMEPAD_RIGHT_SHOULDER_BOT, GAMEPAD_RIGHT_SHOULDER_BOT, GAMEPAD_RIGHT_SHOULDER_BOT, GAMEPAD_RIGHT_SHOULDER_BOT, GAMEPAD_RIGHT_SHOULDER_BOT, AKEY_UNKNOWN, OSXKEY_UNKNOWN, IKEY_UNKNOWN, LINUXKEY_UNKNOWN, WIIUKEY_UNKNOWN); + } + else + { + ANALOG_INPUT_EVENT_DEF(VEH_ACCELERATE_PAD, GAMEPAD_DEFAULT_SENSITIVITY, GAMEPAD_RIGHT_SHOULDER_BOT, GAMEPAD_RIGHT_SHOULDER_BOT, GAMEPAD_RIGHT_SHOULDER_BOT, GAMEPAD_RIGHT_SHOULDER_BOT, GAMEPAD_RIGHT_SHOULDER_BOT, AKEY_UNKNOWN, OSXKEY_UNKNOWN, IKEY_UNKNOWN, LINUXKEY_UNKNOWN, WIIUKEY_UNKNOWN); + ANALOG_INPUT_EVENT_DEF(TANK_THRUST_LEFT_PAD , GAMEPAD_DEFAULT_SENSITIVITY, GAMEPAD_LEFT_STICK_Y, GAMEPAD_LEFT_STICK_Y, GAMEPAD_LEFT_STICK_Y, GAMEPAD_LEFT_STICK_Y, GAMEPAD_LEFT_STICK_Y, GAMEPAD_LEFT_STICK_Y, OSXKEY_UNKNOWN, GAMEPAD_LEFT_STICK_Y, LINUXKEY_UNKNOWN, GAMEPAD_LEFT_STICK_Y); + ANALOG_INPUT_EVENT_DEF(TANK_THRUST_RIGHT_PAD, GAMEPAD_DEFAULT_SENSITIVITY, GAMEPAD_RIGHT_STICK_Y, GAMEPAD_RIGHT_STICK_Y, GAMEPAD_RIGHT_STICK_Y, GAMEPAD_RIGHT_STICK_Y, GAMEPAD_RIGHT_STICK_Y, GAMEPAD_RIGHT_STICK_Y, OSXKEY_UNKNOWN, GAMEPAD_RIGHT_STICK_Y, LINUXKEY_UNKNOWN, GAMEPAD_RIGHT_STICK_Y); + } + + ANALOG_INPUT_EVENT_DEF(CAMERA_ROTATE_LEFT_RIGHT_PAD,GAMEPAD_ROTATE_SENSITIVITY, GAMEPAD_RIGHT_STICK_X, GAMEPAD_RIGHT_STICK_X, GAMEPAD_RIGHT_STICK_X, GAMEPAD_RIGHT_STICK_X, GAMEPAD_RIGHT_STICK_X, GAMEPAD_RIGHT_STICK_X, OSXKEY_UNKNOWN, GAMEPAD_RIGHT_STICK_X, LINUXKEY_UNKNOWN, GAMEPAD_RIGHT_STICK_X); + } + else + { + DIGITAL_INPUT_EVENT_DEF(VEH_GEAR_DOWN_PAD, GAMEPAD_EAST, GAMEPAD_EAST, GAMEPAD_EAST, GAMEPAD_EAST, GAMEPAD_EAST, AKEY_UNKNOWN, OSXKEY_UNKNOWN, IKEY_UNKNOWN, LINUXKEY_UNKNOWN, GAMEPAD_EAST); + DIGITAL_INPUT_EVENT_DEF(VEH_GEAR_UP_PAD, GAMEPAD_NORTH, GAMEPAD_NORTH, GAMEPAD_NORTH, GAMEPAD_NORTH, GAMEPAD_NORTH, AKEY_UNKNOWN, OSXKEY_UNKNOWN, IKEY_UNKNOWN, LINUXKEY_UNKNOWN, GAMEPAD_NORTH); + DIGITAL_INPUT_EVENT_DEF(CAR_HANDBRAKE_PAD, GAMEPAD_SOUTH, GAMEPAD_SOUTH, GAMEPAD_SOUTH, GAMEPAD_SOUTH, GAMEPAD_SOUTH, AKEY_UNKNOWN, OSXKEY_UNKNOWN, IKEY_UNKNOWN, LINUXKEY_UNKNOWN, GAMEPAD_SOUTH); + + ANALOG_INPUT_EVENT_DEF(VEH_ACCELERATE_PAD, GAMEPAD_DEFAULT_SENSITIVITY, GAMEPAD_RIGHT_SHOULDER_BOT, GAMEPAD_RIGHT_SHOULDER_BOT, GAMEPAD_RIGHT_SHOULDER_BOT, GAMEPAD_RIGHT_SHOULDER_BOT, GAMEPAD_RIGHT_SHOULDER_BOT, AKEY_UNKNOWN, OSXKEY_UNKNOWN, IKEY_UNKNOWN, LINUXKEY_UNKNOWN, WIIUKEY_UNKNOWN); + ANALOG_INPUT_EVENT_DEF(CAR_BRAKE_PAD , GAMEPAD_DEFAULT_SENSITIVITY, GAMEPAD_LEFT_SHOULDER_BOT, GAMEPAD_LEFT_SHOULDER_BOT, GAMEPAD_LEFT_SHOULDER_BOT, GAMEPAD_LEFT_SHOULDER_BOT, GAMEPAD_LEFT_SHOULDER_BOT, AKEY_UNKNOWN, OSXKEY_UNKNOWN, IKEY_UNKNOWN, LINUXKEY_UNKNOWN, WIIUKEY_UNKNOWN); + ANALOG_INPUT_EVENT_DEF(CAR_STEER_PAD, GAMEPAD_DEFAULT_SENSITIVITY, GAMEPAD_LEFT_STICK_X, GAMEPAD_LEFT_STICK_X, GAMEPAD_LEFT_STICK_X, GAMEPAD_LEFT_STICK_X, GAMEPAD_LEFT_STICK_X, GAMEPAD_LEFT_STICK_X, OSXKEY_UNKNOWN, GAMEPAD_LEFT_STICK_X, LINUXKEY_UNKNOWN, GAMEPAD_LEFT_STICK_X); + + ANALOG_INPUT_EVENT_DEF(CAR_ACCELERATE_BRAKE, GAMEPAD_DEFAULT_SENSITIVITY, GAMEPAD_LEFT_STICK_Y, XKEY_UNKNOWN, X1KEY_UNKNOWN, PS3KEY_UNKNOWN, PS4KEY_UNKNOWN, GAMEPAD_LEFT_STICK_Y, OSXKEY_UNKNOWN, GAMEPAD_LEFT_STICK_Y, LINUXKEY_UNKNOWN, WIIUKEY_UNKNOWN); + + ANALOG_INPUT_EVENT_DEF(CAMERA_ROTATE_LEFT_RIGHT_PAD,GAMEPAD_ROTATE_SENSITIVITY, GAMEPAD_RIGHT_STICK_X, GAMEPAD_RIGHT_STICK_X, GAMEPAD_RIGHT_STICK_X, GAMEPAD_RIGHT_STICK_X, GAMEPAD_RIGHT_STICK_X, GAMEPAD_RIGHT_STICK_X, OSXKEY_UNKNOWN, GAMEPAD_RIGHT_STICK_X, LINUXKEY_UNKNOWN, GAMEPAD_RIGHT_STICK_X); + ANALOG_INPUT_EVENT_DEF(CAMERA_ROTATE_UP_DOWN_PAD, GAMEPAD_ROTATE_SENSITIVITY, GAMEPAD_RIGHT_STICK_Y, GAMEPAD_RIGHT_STICK_Y, GAMEPAD_RIGHT_STICK_Y, GAMEPAD_RIGHT_STICK_Y, GAMEPAD_RIGHT_STICK_Y, GAMEPAD_RIGHT_STICK_Y, OSXKEY_UNKNOWN, GAMEPAD_RIGHT_STICK_Y, LINUXKEY_UNKNOWN, GAMEPAD_RIGHT_STICK_Y); + } + + //Camera keyboard control on keybord + DIGITAL_INPUT_EVENT_DEF(CAMERA_ROTATE_LEFT_KBD, WKEY_NUMPAD4, XKEY_NUMPAD4, X1KEY_NUMPAD4, PS3KEY_NUMPAD4, PS4KEY_NUMPAD4, AKEY_UNKNOWN, OSXKEY_NUMPAD4, IKEY_UNKNOWN, LINUXKEY_NUMPAD4, WIIUKEY_UNKNOWN); + DIGITAL_INPUT_EVENT_DEF(CAMERA_ROTATE_RIGHT_KBD, WKEY_NUMPAD6, XKEY_NUMPAD6, X1KEY_NUMPAD6, PS3KEY_NUMPAD6, PS4KEY_NUMPAD6, AKEY_UNKNOWN, OSXKEY_NUMPAD6, IKEY_UNKNOWN, LINUXKEY_NUMPAD6, WIIUKEY_UNKNOWN); + DIGITAL_INPUT_EVENT_DEF(CAMERA_ROTATE_UP_KBD, WKEY_NUMPAD8, XKEY_NUMPAD8, X1KEY_NUMPAD8, PS3KEY_NUMPAD8, PS4KEY_NUMPAD8, AKEY_UNKNOWN, OSXKEY_NUMPAD8, IKEY_UNKNOWN, LINUXKEY_NUMPAD8, WIIUKEY_UNKNOWN); + DIGITAL_INPUT_EVENT_DEF(CAMERA_ROTATE_DOWN_KBD, WKEY_NUMPAD2, XKEY_NUMPAD2, X1KEY_NUMPAD2, PS3KEY_NUMPAD2, PS4KEY_NUMPAD2, AKEY_UNKNOWN, OSXKEY_NUMPAD2, IKEY_UNKNOWN, LINUXKEY_NUMPAD2, WIIUKEY_UNKNOWN); + + //General control events on keyboard. + DIGITAL_INPUT_EVENT_DEF(DEBUG_RENDER_FLAG, WKEY_F9, XKEY_F9, X1KEY_F9, PS3KEY_F9, PS4KEY_F9, AKEY_UNKNOWN, OSXKEY_T, IKEY_UNKNOWN, LINUXKEY_F9, WIIUKEY_UNKNOWN); + DIGITAL_INPUT_EVENT_DEF(DEBUG_RENDER_ENGINE, WKEY_2, XKEY_2, X1KEY_2, PS3KEY_2, PS4KEY_2, AKEY_UNKNOWN, OSXKEY_2, IKEY_UNKNOWN, LINUXKEY_2, WIIUKEY_UNKNOWN); + DIGITAL_INPUT_EVENT_DEF(DEBUG_RENDER_WHEEL, WKEY_1, XKEY_1, X1KEY_1, PS3KEY_1, PS4KEY_1, AKEY_UNKNOWN, OSXKEY_1, IKEY_UNKNOWN, LINUXKEY_1, WIIUKEY_UNKNOWN); + DIGITAL_INPUT_EVENT_DEF(FIX_CAR, WKEY_K, XKEY_K, X1KEY_K, PS3KEY_K, PS4KEY_K, AKEY_UNKNOWN, OSXKEY_K, IKEY_UNKNOWN, LINUXKEY_K, WIIUKEY_UNKNOWN); + + //General control events on gamepad. + DIGITAL_INPUT_EVENT_DEF(DEBUG_RENDER_FLAG, GAMEPAD_WEST, GAMEPAD_WEST, GAMEPAD_WEST, GAMEPAD_WEST, GAMEPAD_WEST, AKEY_UNKNOWN, OSXKEY_UNKNOWN, IKEY_UNKNOWN, LINUXKEY_UNKNOWN, GAMEPAD_WEST); + DIGITAL_INPUT_EVENT_DEF(DEBUG_RENDER_ENGINE, GAMEPAD_LEFT_SHOULDER_TOP, GAMEPAD_LEFT_SHOULDER_TOP, GAMEPAD_LEFT_SHOULDER_TOP, GAMEPAD_LEFT_SHOULDER_TOP, GAMEPAD_LEFT_SHOULDER_TOP, AKEY_UNKNOWN, OSXKEY_UNKNOWN, IKEY_UNKNOWN, LINUXKEY_UNKNOWN, GAMEPAD_LEFT_SHOULDER_TOP); + DIGITAL_INPUT_EVENT_DEF(DEBUG_RENDER_WHEEL, GAMEPAD_RIGHT_SHOULDER_TOP, GAMEPAD_RIGHT_SHOULDER_TOP, GAMEPAD_RIGHT_SHOULDER_TOP, GAMEPAD_RIGHT_SHOULDER_TOP, GAMEPAD_RIGHT_SHOULDER_TOP, AKEY_UNKNOWN, OSXKEY_UNKNOWN, IKEY_UNKNOWN, LINUXKEY_UNKNOWN, GAMEPAD_RIGHT_SHOULDER_TOP); + DIGITAL_INPUT_EVENT_DEF(FIX_CAR, GAMEPAD_RIGHT_STICK, GAMEPAD_RIGHT_STICK, GAMEPAD_RIGHT_STICK, GAMEPAD_RIGHT_STICK, GAMEPAD_RIGHT_STICK, AKEY_UNKNOWN, OSXKEY_UNKNOWN, IKEY_UNKNOWN, LINUXKEY_UNKNOWN, GAMEPAD_RIGHT_STICK); + + //General control events on touch + TOUCH_INPUT_EVENT_DEF(FIX_CAR, "Reset Car", ABUTTON_5, IBUTTON_5); + TOUCH_INPUT_EVENT_DEF(CAR_HANDBRAKE_PAD, "Handbrake", AQUICK_BUTTON_1, IQUICK_BUTTON_1); +} + +void SampleVehicle::onDigitalInputEvent(const SampleFramework::InputEvent& ie, bool val) +{ + switch (ie.m_Id) + { + case VEH_SAVE_KBD: + { + if(val) + { +#if defined(SERIALIZE_VEHICLE_RPEX) || defined(SERIALIZE_VEHICLE_BINARY) + PxSerializationRegistry* sr = mVehicleManager.getSerializationRegistry(); + PxVehicleWheels& focusVehicle = *mVehicleManager.getVehicle(mPlayerVehicle); + PxCollection* c = PxCreateCollection(); + c->add( focusVehicle, 1 ); + PxSerialization::complete(*c, *sr, NULL); + PxDefaultFileOutputStream theStream(mVehicleFilePath); +#if defined(SERIALIZE_VEHICLE_RPEX) + PxSerialization::serializeCollectionToXml(theStream, *c, *sr, &getCooking()); +#elif defined(SERIALIZE_VEHICLE_BINARY) + PxSerialization::serializeCollectionToBinary(theStream, *c, *sr); +#endif + c->release(); +#endif + } + } + break; + case VEH_ACCELERATE_KBD: + { + mControlInputs.setAccelKeyPressed(val); + } + break; + case VEH_GEAR_DOWN_KBD: + { + mControlInputs.setGearDownKeyPressed(val); + } + break; + case VEH_GEAR_UP_KBD: + { + mControlInputs.setGearUpKeyPressed(val); + } + break; + case CAR_BRAKE_KBD: + { + mControlInputs.setBrakeKeyPressed(val); + } + break; + case CAR_STEER_LEFT_KBD: + { + mControlInputs.setSteerRightKeyPressed(val); + } + break; + case CAR_STEER_RIGHT_KBD: + { + mControlInputs.setSteerLeftKeyPressed(val); + } + break; + case CAR_HANDBRAKE_KBD: + { + mControlInputs.setHandbrakeKeyPressed(val); + } + break; + + case TANK_THRUST_LEFT_KBD: + { + if(PxVehicleDriveTankControlModel::eSPECIAL==mTankDriveModel) + { + mControlInputs.setThrustLeftKeyPressed(val); + mControlInputs.setAccelKeyPressed(val); + } + else if(val) + { + mControlInputs.setThrustLeftKeyPressed(val); + mControlInputs.setAccelKeyPressed(val); + } + else + { + mControlInputs.setThrustLeftKeyPressed(val); + } + } + break; + case TANK_THRUST_RIGHT_KBD: + { + if(PxVehicleDriveTankControlModel::eSPECIAL==mTankDriveModel) + { + mControlInputs.setThrustRightKeyPressed(val); + mControlInputs.setAccelKeyPressed(val); + } + else if(val) + { + mControlInputs.setThrustRightKeyPressed(val); + mControlInputs.setAccelKeyPressed(val); + } + else + { + mControlInputs.setThrustRightKeyPressed(val); + } + } + break; + case TANK_BRAKE_LEFT_KBD: + { + if(PxVehicleDriveTankControlModel::eSPECIAL==mTankDriveModel) + { + mControlInputs.setBrakeLeftKeyPressed(val); + mControlInputs.setAccelKeyPressed(val); + } + else if(val) + { + mControlInputs.setBrakeLeftKeyPressed(val); + } + else + { + mControlInputs.setBrakeLeftKeyPressed(val); + } + } + break; + case TANK_BRAKE_RIGHT_KBD: + { + if(PxVehicleDriveTankControlModel::eSPECIAL==mTankDriveModel) + { + mControlInputs.setBrakeRightKeyPressed(val); + mControlInputs.setAccelKeyPressed(val); + } + else if(val) + { + mControlInputs.setBrakeRightKeyPressed(val); + } + else + { + mControlInputs.setBrakeRightKeyPressed(val); + } + } + break; + case VEH_GEAR_DOWN_PAD: + { + mControlInputs.setGearDown(val); + } + break; + case VEH_GEAR_UP_PAD: + { + mControlInputs.setGearUp(val); + } + break; + case CAR_HANDBRAKE_PAD: + { + mControlInputs.setHandbrake(val); + } + break; + case AUTOMATIC_GEAR: + { + if(val) + { + mVehicleController.toggleAutoGearFlag(); + } + } + break; + case DEBUG_RENDER_FLAG: + { + if(val) + { + mDebugRenderFlag = !mDebugRenderFlag; + } + } + break; + case DEBUG_RENDER_WHEEL: + { + if(val) + { +#if PX_DEBUG_VEHICLE_ON + mDebugRenderActiveGraphChannelWheel++; + if(mDebugRenderActiveGraphChannelWheel==PxVehicleWheelGraphChannel::eMAX_NB_WHEEL_CHANNELS) + { + mDebugRenderActiveGraphChannelWheel=0; + } +#endif + } + } + break; + case DEBUG_RENDER_ENGINE: + { + if(val) + { +#if PX_DEBUG_VEHICLE_ON + mDebugRenderActiveGraphChannelEngine++; + if(mDebugRenderActiveGraphChannelEngine==PxVehicleDriveGraphChannel::eMAX_NB_DRIVE_CHANNELS) + { + mDebugRenderActiveGraphChannelEngine=0; + } +#endif + } + } + break; + case RETRY: + { + if(val) + mBackToStart=true; + } + break; + case FIX_CAR: + { + if(val) + mFixCar = true; + } + break; + case CAMERA_ROTATE_LEFT_KBD: + { + mControlInputs.setRotateY(val ? -0.5f : 0.0f); + } + break; + case CAMERA_ROTATE_RIGHT_KBD: + { + mControlInputs.setRotateY(val ? 0.5f : 0.0f); + } + break; + case CAMERA_ROTATE_UP_KBD: + { + mControlInputs.setRotateZ(val ? 0.5f : 0.0f); + } + break; + case CAMERA_ROTATE_DOWN_KBD: + { + mControlInputs.setRotateZ(val ? -0.5f : 0.0f); + } + break; + case W3MODE: + { + if(val) + { + m3WModeIncremented=true; + } + } + break; + default: + break; + } + + PhysXSample::onDigitalInputEvent(ie,val); +} + +void SampleVehicle::onAnalogInputEvent(const SampleFramework::InputEvent& ie, float val) +{ + switch(mPlayerVehicleType) + { + case ePLAYER_VEHICLE_TYPE_VEHICLE4W: + case ePLAYER_VEHICLE_TYPE_VEHICLE6W: + + switch (ie.m_Id) + { + case VEH_ACCELERATE_PAD: + { + mControlInputs.setAccel(val); + } + break; + case CAR_BRAKE_PAD: + { + mControlInputs.setBrake(val); + } + break; + case CAR_ACCELERATE_BRAKE: + { + if (val >= 0.0f) + { + mControlInputs.setAccel(val); + mControlInputs.setBrake(0.0f); + } + else + { + mControlInputs.setBrake(-val); + mControlInputs.setAccel(0.0f); + } + } + break; + case CAR_STEER_PAD: + { + mControlInputs.setSteer(-val); + } + break; + case CAMERA_ROTATE_LEFT_RIGHT_PAD: + { + mControlInputs.setRotateY(-val); + } + break; + case CAMERA_ROTATE_UP_DOWN_PAD: + { + mControlInputs.setRotateZ(-val); + } + break; + default: + break; + } + + break; + + case ePLAYER_VEHICLE_TYPE_TANK4W: + case ePLAYER_VEHICLE_TYPE_TANK6W: + + switch (ie.m_Id) + { + case VEH_ACCELERATE_PAD: + { + PX_ASSERT(PxVehicleDriveTankControlModel::eSTANDARD==mTankDriveModel); + mControlInputs.setAccel(val); + } + break; + case TANK_THRUST_RIGHT_PAD: + { + if(PxVehicleDriveTankControlModel::eSPECIAL==mTankDriveModel) + { + mControlInputs.setThrustLeft(val); + mControlInputs.setAccel(val ? 1.0f : 0.0f); + } + else if(val>0) + { + mControlInputs.setThrustLeft(val); + mControlInputs.setBrakeLeft(0.0f); + } + else + { + mControlInputs.setThrustLeft(0.0f); + mControlInputs.setBrakeLeft(-val); + } + } + break; + case TANK_THRUST_LEFT_PAD: + { + if(PxVehicleDriveTankControlModel::eSPECIAL==mTankDriveModel) + { + mControlInputs.setThrustRight(val); + mControlInputs.setAccel(val ? 1.0f : 0.0f); + } + else if(val>0) + { + mControlInputs.setThrustRight(val); + mControlInputs.setBrakeRight(0.0f); + } + else + { + mControlInputs.setThrustRight(0.0f); + mControlInputs.setBrakeRight(-val); + } + } + break; + case TANK_BRAKE_LEFT_PAD: + { + PX_ASSERT(PxVehicleDriveTankControlModel::eSPECIAL==mTankDriveModel); + mControlInputs.setBrakeLeft(val); + } + break; + case TANK_BRAKE_RIGHT_PAD: + { + PX_ASSERT(PxVehicleDriveTankControlModel::eSPECIAL==mTankDriveModel); + mControlInputs.setBrakeRight(val); + } + break; + case CAMERA_ROTATE_LEFT_RIGHT_PAD: + { + mControlInputs.setRotateY(-val); + } + break; + default: + break; + } + break; + + default: + PX_ASSERT(false); + break; + } +} + +/////////////////////////////////////////////////////////////////////////////// + +#if PX_DEBUG_VEHICLE_ON +void SampleVehicle::clearTelemetryData() +{ + mTelemetryData4W->clear(); + mTelemetryData6W->clear(); +} +#endif + +void SampleVehicle::updateCameraController(const PxF32 dtime, PxScene& scene) +{ + mCameraController.update(dtime,*mVehicleManager.getVehicle(mPlayerVehicle),scene); +} + +void SampleVehicle::updateVehicleController(const PxF32 dtime) +{ + PxSceneReadLock scopedLock(*mScene); + mVehicleController.update(dtime, mVehicleManager.getVehicleWheelQueryResults(mPlayerVehicle), *mVehicleManager.getVehicle(mPlayerVehicle)); +} + +void SampleVehicle::updateVehicleManager(const PxF32 dtime, const PxVec3& gravity) +{ + switch(mPlayerVehicleType) + { + case ePLAYER_VEHICLE_TYPE_VEHICLE4W: + case ePLAYER_VEHICLE_TYPE_TANK4W: +#if PX_DEBUG_VEHICLE_ON + mVehicleManager.updateAndRecordTelemetryData(dtime,gravity,mVehicleManager.getVehicle(mPlayerVehicle),mTelemetryData4W); +#else + mVehicleManager.update(dtime,gravity); +#endif + break; + case ePLAYER_VEHICLE_TYPE_VEHICLE6W: + case ePLAYER_VEHICLE_TYPE_TANK6W: +#if PX_DEBUG_VEHICLE_ON + mVehicleManager.updateAndRecordTelemetryData(dtime,gravity,mVehicleManager.getVehicle(mPlayerVehicle),mTelemetryData6W); +#else + mVehicleManager.update(dtime,gravity); +#endif + break; + default: + PX_ASSERT(false); + break; + } +} + +void SampleVehicle::resetFocusVehicleAtWaypoint() +{ + mVehicleManager.resetNWCar(mWayPoints.getResetTransform(),mPlayerVehicle); +} + +PxRigidDynamic* SampleVehicle::getFocusVehicleRigidDynamicActor() +{ + return mVehicleManager.getVehicle(mPlayerVehicle)->getRigidDynamicActor(); +} + +void SampleVehicle::drawFocusVehicleGraphsAndPrintTireSurfaces() +{ + drawGraphsAndPrintTireSurfaceTypes(*mVehicleManager.getVehicle(mPlayerVehicle), mVehicleManager.getVehicleWheelQueryResults(mPlayerVehicle)); +} + +bool SampleVehicle::getFocusVehicleUsesAutoGears() +{ + PxVehicleWheels* vehWheels=mVehicleManager.getVehicle(mPlayerVehicle); + PxVehicleDriveDynData* driveDynData=NULL; + switch(vehWheels->getVehicleType()) + { + case PxVehicleTypes::eDRIVE4W: + { + PxVehicleDrive4W* vehDrive4W=(PxVehicleDrive4W*)vehWheels; + driveDynData=&vehDrive4W->mDriveDynData; + } + break; + case PxVehicleTypes::eDRIVENW: + { + PxVehicleDriveNW* vehDriveNW=(PxVehicleDriveNW*)vehWheels; + driveDynData=&vehDriveNW->mDriveDynData; + } + break; + case PxVehicleTypes::eDRIVETANK: + { + PxVehicleDriveTank* vehDriveTank=(PxVehicleDriveTank*)vehWheels; + driveDynData=&vehDriveTank->mDriveDynData; + } + break; + default: + PX_ASSERT(false); + break; + } + + return driveDynData->getUseAutoGears(); +} |