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 /KaplaDemo/samples/sampleViewer3/SceneVehicle.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 'KaplaDemo/samples/sampleViewer3/SceneVehicle.cpp')
| -rw-r--r-- | KaplaDemo/samples/sampleViewer3/SceneVehicle.cpp | 1193 |
1 files changed, 1193 insertions, 0 deletions
diff --git a/KaplaDemo/samples/sampleViewer3/SceneVehicle.cpp b/KaplaDemo/samples/sampleViewer3/SceneVehicle.cpp new file mode 100644 index 00000000..69468a48 --- /dev/null +++ b/KaplaDemo/samples/sampleViewer3/SceneVehicle.cpp @@ -0,0 +1,1193 @@ +#include "SceneVehicle.h" +#include "Convex.h" +#include "PxSimpleFactory.h" +#include "PxRigidStatic.h" +#include "PxShape.h" +#include "foundation/PxMathUtils.h" +#include "foundation/PxMat44.h" +#include "PsString.h" +#include "CmPhysxCommon.h" + +#include <stdio.h> +#include <GL/glut.h> + +#include "SimScene.h" +#include "CompoundCreator.h" +#include "TerrainMesh.h" + +#include "PhysXMacros.h" + +#include "PxRigidBodyExt.h" + +#include "vehicle/PxVehicleSDK.h" +#include "vehicle/PxVehicleDrive4W.h" +#include "vehicle/PxVehicleUtilSetup.h" +#include "vehicle/PxVehicleUtil.h" +#include "SceneVehicleCooking.h" +#include "SceneVehicleSceneQuery.h" +#include "SampleViewerGamepad.h" +#include "RawLoader.h" +#include "TerrainRandomSamplePrecompute.h" +#include "MediaPath.h" +#include "glmesh.h" +#include "Texture.h" +#include "PxShapeExt.h" + +static bool createVehicleDemo = true; + + + +/////////////////////////////////// +//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)) +}; + +//////////////////////////////////////////////////////////////// +//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 +}; + +enum MaterialID +{ + MATERIAL_TERRAIN_MUD = 1000, + MATERIAL_ROAD_TARMAC = 1001, + MATERIAL_ROAD_SNOW = 1002, + MATERIAL_ROAD_GRASS = 1003, +}; + + +static const char gCarPartNames[NUM_CAR4W_RENDER_COMPONENTS][64] = +{ + "frontwheelleftshape", + "frontwheelrightshape", + "backwheelleftshape", + "backwheelrightshape", + "car_02_visshape", + "car_02_windowsshape" +}; + +//////////////////////////////////////////////////////////////// +//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 }; +static GLMesh* gCarPartRenderMesh[6] = { NULL, NULL, NULL, NULL, NULL, NULL }; + + +extern bool LoadTexture(const char *filename, GLuint &texId, bool createMipmaps, GLuint type = GL_TEXTURE_2D, int *width = NULL, int *height = NULL); + +// ---------------------------------------------------------------------------------------------- +SceneVehicle::SceneVehicle(PxPhysics* pxPhysics, PxCooking *pxCooking, bool isGrb, + Shader *defaultShader, const char *resourcePath, float slowMotionFactor) : + SceneKapla(pxPhysics, pxCooking, isGrb, defaultShader, resourcePath, slowMotionFactor) +{ + mChassisMaterialDrivable = NULL; + mChassisMaterialNonDrivable = NULL; + if (createVehicleDemo) + mCameraDisable = true; + else + mCameraDisable = false; + mNumTextures = 0; + mNumMaterials = 0; + //onInit(pxPhysics, pxCooking, pxScene); +} + + +void SceneVehicle::onInit(PxScene* pxScene) +{ + SceneKapla::onInit(pxScene); + createStandardMaterials(); + if (createVehicleDemo) + createVehicle(mPxPhysics); + SceneKapla::createTerrain("terrain_ll2.bmp", ""); + + const PxVec3 dims(0.08f, 0.25f, 1.0f); + + PxMaterial* DefaultMaterial = mPxPhysics->createMaterial(0.5f, 0.25f, 0.1f); + + ShaderMaterial mat; + mat.init(); + + PxFilterData simFilterData; + simFilterData.word0 = COLLISION_FLAG_OBSTACLE; + simFilterData.word1 = COLLISION_FLAG_OBSTACLE_AGAINST; + //simFilterData.word2 = PxPairFlag::eMODIFY_CONTACTS; + + PxFilterData queryFilterData; + //VehicleSetupDrivableShapeQueryFilterData(&queryFilterData); + + createCylindricalTower(96, 3.6f, 3.6f, 14, dims, PxVec3(-10.f, -1.10f, 20.f), DefaultMaterial, mat, simFilterData, queryFilterData, 10.f); + createCylindricalTower(96, 5.8f, 5.8f, 10, dims, PxVec3(-10.f, -1.10f, 20.f), DefaultMaterial, mat, simFilterData, queryFilterData, 10.f); + createCylindricalTower(128, 8.f, 8.f, 8, dims, PxVec3(-10.f, -1.10f, 20.f), DefaultMaterial, mat, simFilterData, queryFilterData, 10.f); + createCylindricalTower(196, 10.2f, 10.2f, 6, dims, PxVec3(-10.f, -1.10f, 20.f), DefaultMaterial, mat, simFilterData, queryFilterData, 10.f); + + + createCylindricalTower(384, 35.f, 35.f, 6, dims, PxVec3(0.f, -1.10f, 0.f), DefaultMaterial, mat, simFilterData, queryFilterData, 10.f); + + + /*PxFilterData planeFilterData; + simFilterData.word0 = COLLISION_FLAG_GROUND; + simFilterData.word1 = COLLISION_FLAG_GROUND_AGAINST; + + VehicleSetupDrivableShapeQueryFilterData(&queryFilterData); + + createGroundPlane(planeFilterData, PxVec3(0,0,0), queryFilterData); + + PxTransform pose = mVehicleManager.getVehicle()->getRigidDynamicActor()->getGlobalPose(); + pose.p.y += 3.f; + + mVehicleManager.getVehicle()->getRigidDynamicActor()->setGlobalPose(pose);*/ + +} + +void SceneVehicle::setScene(PxScene* pxScene) +{ + SceneKapla::setScene(pxScene); + mVehicleManager.clearBatchQuery(); +} + +void SceneVehicle::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]) + { + printf("SceneVehicle : create mStandardMaterials failed"); + } + + //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) + { + printf("SceneVehicle : create mChassisMaterialDrivable failed"); + } + + mChassisMaterialNonDrivable = getPhysics().createMaterial(1.0f, 1.0f, 0.0f); + if (!mChassisMaterialNonDrivable) + { + printf("SceneVehicle : create mChassisMaterialNonDrivable failed"); + } +} + +static void computeTerrain(bool* done, float* pVB, PxU32 x0, PxU32 y0, PxU32 currentSize, float value, PxU32 initSize, TerrainRandomSamplePrecompute& 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 SceneVehicle::createTerrain(PxU32 size, float width, float chaos) +{ + mNbTerrainVerts = size*size; + + // Vertex buffer + mTerrainVB = new PxF32[(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 = new bool[(sizeof(bool)*mNbTerrainVerts)]; + PxU32* tagBuffer = new PxU32[(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; + + TerrainRandomSamplePrecompute randomPrecomputed(*this, mResourcePath); + 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] = new PxU32[(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]++; + } + } + } + + delete[] tagBuffer; + delete[] doneBuffer; +} + + +void SceneVehicle::newMesh(const RAWMesh& data) +{ + + 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 vmin(PX_MAX_F32, PX_MAX_F32, PX_MAX_F32); + PxVec3 vmax(-PX_MAX_F32, -PX_MAX_F32, -PX_MAX_F32); + for (PxU32 i = 0; i < data.mNbVerts; i++) + { + vmin.x = PxMin(vmin.x, data.mVerts[i].x); + vmin.y = PxMin(vmin.y, data.mVerts[i].y); + vmin.z = PxMin(vmin.z, data.mVerts[i].z); + vmax.x = PxMax(vmax.x, data.mVerts[i].x); + vmax.y = PxMax(vmax.y, data.mVerts[i].y); + vmax.z = PxMax(vmax.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 = (vmin + vmax)*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; + } + } + + gCarPartRenderMesh[carPart] = createRenderMesh(data); + + //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] = data.mTransform.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; + } + } + +} + + +void SceneVehicle::importRAWFile(const char* fname, PxReal scale, bool recook) +{ + + bool status = loadRAWfile(FindMediaFile(fname, mResourcePath), *this, scale); + if (!status) + { + std::string msg = "Sample can not load file "; + msg += FindMediaFile(fname, mResourcePath); + msg += "\n"; + printf("%s", msg.c_str()); + } +} + +void SceneVehicle::createVehicle(PxPhysics* pxPhysics) +{ + //Initialise the sdk. + + mVehicleManager.init(getPhysics(), (const PxMaterial**)mStandardMaterials, mVehicleDrivableSurfaceTypes); + + importRAWFile("car2.raw", 1.0f); + + mVehicleManager.create4WVehicle(getScene(), getPhysics(), getCooking(), *mChassisMaterialDrivable, gChassisMass, gWheelCentreOffsets4, gChassisConvexMesh, + gWheelConvexMeshes4, gPlayerCarStartTransforms[0], true); +} + +//----------------------------------------------------------------------------------------------- + +void SceneVehicle::newMaterial(const RAWMaterial& data) +{ + ShaderMaterial& materials = mCarPartMaterial[mNumMaterials++]; + materials.init(mTextureIds[mNumMaterials - 1]); + //materials.setColor(data.mDiffuseColor.x, data.mDiffuseColor.y, data.mDiffuseColor.z); + materials.setColor(1, 0, 0); + materials.diffuseCoeff = 0.5f; + materials.specularCoeff = 0.707f; +} + +//----------------------------------------------------------------------------------------------- + +void SceneVehicle::newTexture(const RAWTexture& data) +{ + char fullPath[512]; + int len = strlen(data.mName); + for (PxU32 i = 0; i < len-4; ++i) + { + fullPath[i] = data.mName[i]; + } + fullPath[len - 4] = '\0'; + strcat(fullPath, ".bmp"); + + + string fName = FindMediaFile(fullPath, mResourcePath); + //string fName = FindMediaFile("car02_diffuse2.bmp", mResourcePath); + + mTextureIds[mNumTextures++] = loadImgTexture(fName.c_str()); + +} + +// ---------------------------------------------------------------------------------------------- +void SceneVehicle::handleMouseButton(int button, int state, int x, int y) +{ + mMouseX = x; + mMouseY = y; + + mMouseDown = (state == GLUT_DOWN); + + PxVec3 orig, dir; + getMouseRay(x, y, orig, dir); + + if (glutGetModifiers() & GLUT_ACTIVE_SHIFT) { + if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) { + if (mSimScene) + mSimScene->pickStart(orig, dir); + } + } + if (button == GLUT_LEFT_BUTTON && state == GLUT_UP) { + if (mSimScene) + mSimScene->pickRelease(); + } +} + +// ---------------------------------------------------------------------------------------------- +void SceneVehicle::handleMouseMotion(int x, int y) +{ + mMouseX = x; + mMouseY = y; + + if (mSimScene && mSimScene->getPickActor() != NULL) { + PxVec3 orig, dir; + getMouseRay(x, y, orig, dir); + mSimScene->pickMove(orig, dir); + } +} +//ofstream orays("ray.txt"); + +// ---------------------------------------------------------------------------------------------- +void SceneVehicle::handleKeyDown(unsigned char key, int x, int y) +{ + if (mCameraDisable) + { + switch (key) + { + case ' ': + { + float vel = 1.0f; + PxVec3 orig, dir; + getMouseRay(mMouseX, mMouseY, orig, dir); + /* + float sx = 0.0f, sy = 30.0f, sz = 0.0f; + int nx = 10; + int ny = 10; + float dx = 1.0f; + for (int i = 0; i < ny; i++) { + for (int j = 0; j < nx; j++) { + shoot(PxVec3(sx+j*dx, sy, sz + i*dx), PxVec3(0.0f,1.0f,0.0f)); + } + } + + */ + shoot(mCameraPos, dir); + //orays<<"{"<<mCameraPos.x<<","<<mCameraPos.y<<","<<mCameraPos.z<<","<<dir.x<<","<<dir.y<<","<<dir.z<<"},\n"; + //orays.flush(); + //printf("{%f,%f,%f,%f,%f,%f},\n ", mCameraPos.x, mCameraPos.y, mCameraPos.z, dir.x, dir.y, dir.z); + break; + } + case 'w': + case 'W': + { + mControlInputs.setAccelKeyPressed(true); + break; + } + case 's': + case 'S': + { + mControlInputs.setBrakeKeyPressed(true); + break; + } + case 'a': + case 'A': + { + mControlInputs.setSteerRightKeyPressed(true); + + break; + } + case 'd': + case 'D': + { + mControlInputs.setSteerLeftKeyPressed(true); + break; + } + default: + { + break; + } + } + } + +} + +// ---------------------------------------------------------------------------------------------- +void SceneVehicle::handleKeyUp(unsigned char key, int x, int y) +{ + if (mCameraDisable) + { + switch (key) + { + case 'v': + if (mSimScene) mSimScene->toggleDebugDrawing(); break; + case ' ': + { + mGunActive = false; + } + case 'w': + case 'W': + { + mControlInputs.setAccelKeyPressed(false); + break; + } + case 's': + case 'S': + { + mControlInputs.setBrakeKeyPressed(false); + break; + } + case 'a': + case 'A': + { + mControlInputs.setSteerRightKeyPressed(false); + + break; + } + case 'd': + case 'D': + { + mControlInputs.setSteerLeftKeyPressed(false); + break; + } + default: + { + break; + } + } + } +} + +// ---------------------------------------------------------------------------------------------- +void SceneVehicle::handleSpecialKey(unsigned char key, int x, int y) +{ + SceneKapla::handleSpecialKey(key, x, y); + switch (key) + { + case GLUT_KEY_F7: { + mCameraDisable = !mCameraDisable; + break; + } + } +} + +//------------------------------------------------------------------------------------------------- + +void SceneVehicle::handleGamepadButton(int button, bool state) +{ + if (mCameraDisable) + { + switch (button) + { + case SampleViewerGamepad::GAMEPAD_A: + { + float vel = 1.0f; + PxVec3 orig, dir; + getMouseRay(mMouseX, mMouseY, orig, dir); + /* + float sx = 0.0f, sy = 30.0f, sz = 0.0f; + int nx = 10; + int ny = 10; + float dx = 1.0f; + for (int i = 0; i < ny; i++) { + for (int j = 0; j < nx; j++) { + shoot(PxVec3(sx+j*dx, sy, sz + i*dx), PxVec3(0.0f,1.0f,0.0f)); + } + } + + */ + shoot(mCameraPos, dir); + //orays<<"{"<<mCameraPos.x<<","<<mCameraPos.y<<","<<mCameraPos.z<<","<<dir.x<<","<<dir.y<<","<<dir.z<<"},\n"; + //orays.flush(); + //printf("{%f,%f,%f,%f,%f,%f},\n ", mCameraPos.x, mCameraPos.y, mCameraPos.z, dir.x, dir.y, dir.z); + break; + } + case SampleViewerGamepad::GAMEPAD_DPAD_LEFT: + { + mControlInputs.setGearDown(state); + break; + } + case SampleViewerGamepad::GAMEPAD_DPAD_RIGHT: + { + mControlInputs.setGearUp(state); + break; + } + case SampleViewerGamepad::GAMEPAD_DPAD_DOWN: + { + mControlInputs.setHandbrake(state); + break; + } + default: + { + break; + } + } + } + +} + +//------------------------------------------------------------------------------------------------- + +void SceneVehicle::handleGamepadAxis(int axis, float val) +{ + switch (axis) + { + case SampleViewerGamepad::GAMEPAD_LEFT_STICK_X: + { + mControlInputs.setSteer(-val); + break; + } + default: + break; + } +} + +//------------------------------------------------------------------------------------------------- + +void SceneVehicle::handleGamepadTrigger(int trigger, float val) +{ + if(trigger == SampleViewerGamepad::GAMEPAD_RIGHT_SHOULDER_TRIGGER) + { + mControlInputs.setAccel(val); + } + else + { + if (trigger == SampleViewerGamepad::GAMEPAD_LEFT_SHOULDER_TRIGGER) + { + mControlInputs.setBrake(val); + } + } +} + +//------------------------------------------------------------------------------------------------- +void SceneVehicle::getCamera(PxVec3& pos, PxVec3& dir) +{ + if (mCameraDisable) + { + pos = mCameraPos; + dir = mCameraDir.getNormalized(); + } + +} + +// ---------------------------------------------------------------------------------------------- +void SceneVehicle::preSim(float dt) +{ + SceneKapla::preSim(dt); + + if (createVehicleDemo) + { + 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()); + + mVehicleController.update(dt, mVehicleManager.getWheelQueryResult(), *mVehicleManager.getVehicle()); + } + + + +} + +// ---------------------------------------------------------------------------------------------- +void SceneVehicle::postSim(float dt) +{ + + SceneKapla::postSim(dt); + + if (createVehicleDemo) + { + //update vehicle + //mVehicleManager.suspensionRaycasts(&getScene()); + mVehicleManager.suspensionSweeps(&getScene()); + + if (dt > 0.f) + { + mVehicleManager.update(dt, getScene().getGravity()); + } + + //Update the camera. + mCameraController.setInputs( + mControlInputs.getRotateY(), + mControlInputs.getRotateZ()); + + mCameraController.update(dt, *mVehicleManager.getVehicle(), getScene()); + + setCamera(mCameraController.getCameraPos(), mCameraController.getCameraTar() - mCameraController.getCameraPos(), PxVec3(0.f, 1.f, 0.f), 40.f); + } + + +} + +void SceneVehicle::renderCar(bool useShader) +{ + PxRigidDynamic* dyn = mVehicleManager.getVehicle()->getRigidDynamicActor(); + + PxShape* shapes[5]; + + dyn->getShapes(shapes, 5); + + PxMat44 bodyGlobalPose(dyn->getGlobalPose());// PxShapeExt::getGlobalPose(*shapes[i], *dyn)); + + if (useShader) + mDefaultShader->activate(mCarPartMaterial[0]); + + for (PxU32 i = 0; i < 5; ++i) + { + + PxMat44 globalPose(PxShapeExt::getGlobalPose(*shapes[i], *dyn)); + + glMatrixMode(GL_MODELVIEW); + + glPushMatrix(); + + glMultMatrixf(&globalPose.column0.x); + + gCarPartRenderMesh[i]->drawVBOIBO(); + + glPopMatrix(); + + } + + if (useShader) + mDefaultShader->deactivate(); + + + if (useShader) + mDefaultShader->activate(mCarPartMaterial[1]); + + glMatrixMode(GL_MODELVIEW); + + glPushMatrix(); + + glMultMatrixf(&bodyGlobalPose.column0.x); + + gCarPartRenderMesh[5]->drawVBOIBO(); + + glPopMatrix(); + + if (useShader) + mDefaultShader->deactivate(); + +} + +void SceneVehicle::render(bool useShader) +{ + if (createVehicleDemo) + renderCar(useShader); + + SceneKapla::render(useShader); +} + + +PxFilterFlags VehicleFilterShader +(PxFilterObjectAttributes attributes0, PxFilterData filterData0, +PxFilterObjectAttributes attributes1, PxFilterData filterData1, +PxPairFlags& pairFlags, const void* constantBlock, PxU32 constantBlockSize) +{ + PX_UNUSED(attributes0); + PX_UNUSED(attributes1); + PX_UNUSED(constantBlock); + PX_UNUSED(constantBlockSize); + + if ((0 == (filterData0.word0 & filterData1.word1)) && (0 == (filterData1.word0 & filterData0.word1))) + { + if (filterData0.word0 != 0 && filterData1.word0 != 0) + return PxFilterFlag::eSUPPRESS; + } + + pairFlags = PxPairFlag::eCONTACT_DEFAULT; + pairFlags |= PxPairFlags(PxU16(filterData0.word2 | filterData1.word2)); + + return PxFilterFlags(); + + //pairFlags = PxPairFlag::eDETECT_DISCRETE_CONTACT; + //return PxFilterFlags(); +} + +struct ActorUserData +{ + ActorUserData() + : vehicle(NULL), + actor(NULL) + { + } + + const PxVehicleWheels* vehicle; + const PxActor* actor; +}; + +struct ShapeUserData +{ + ShapeUserData() + : isWheel(false), + wheelId(0xffffffff) + { + } + + bool isWheel; + PxU32 wheelId; +}; + +ActorUserData gActorUserData; +ShapeUserData gShapeUserDatas[PX_MAX_NB_WHEELS]; + +#define POINT_REJECT_ANGLE 45.0f*PxPi/180.0f +#define NORMAL_REJECT_ANGLE 30.0f*PxPi/180.0f +#define WHEEL_TANGENT_VELOCITY_MULTIPLIER 0.1f + +//The class WheelContactModifyCallback identifies and modifies rigid body contacts +//that involve a wheel. Contacts that can be identified and managed by the suspension +//system are ignored. Any contacts that remain are modified to account for the rotation +//speed of the wheel around the rolling axis. +class WheelContactModifyCallback : public PxContactModifyCallback +{ +public: + + WheelContactModifyCallback() + : PxContactModifyCallback() + { + } + + ~WheelContactModifyCallback(){} + + void onContactModify(PxContactModifyPair* const pairs, PxU32 count) + { + for (PxU32 i = 0; i < count; i++) + { + const PxRigidActor** actors = pairs[i].actor; + const PxShape** shapes = pairs[i].shape; + + //Search for actors that represent vehicles and shapes that represent wheels. + for (PxU32 j = 0; j < 2; j++) + { + const PxActor* actor = actors[j]; + if (actor->userData && (static_cast<ActorUserData*>(actor->userData))->vehicle) + { + const PxVehicleWheels* vehicle = (static_cast<ActorUserData*>(actor->userData))->vehicle; + PX_ASSERT(vehicle->getRigidDynamicActor() == actors[j]); + + const PxShape* shape = shapes[j]; + if (shape->userData && (static_cast<ShapeUserData*>(shape->userData))->isWheel) + { + const PxU32 wheelId = (static_cast<ShapeUserData*>(shape->userData))->wheelId; + PX_ASSERT(wheelId < vehicle->mWheelsSimData.getNbWheels()); + + //Modify wheel contacts. + PxVehicleModifyWheelContacts(*vehicle, wheelId, WHEEL_TANGENT_VELOCITY_MULTIPLIER, 0.5f, pairs[i]); + } + } + } + } + } + + +private: + +}; +WheelContactModifyCallback gWheelContactModifyCallback; + +//---------------------------------------------------------------------------------------------------- +void SceneVehicle::customizeSceneDesc(PxSceneDesc& sceneDesc) +{ + sceneDesc.filterShader = VehicleFilterShader; //Set the filter shader + sceneDesc.contactModifyCallback = &gWheelContactModifyCallback; //Enable contact modification +} + |