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/TerrainMesh.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/TerrainMesh.cpp')
| -rw-r--r-- | KaplaDemo/samples/sampleViewer3/TerrainMesh.cpp | 367 |
1 files changed, 367 insertions, 0 deletions
diff --git a/KaplaDemo/samples/sampleViewer3/TerrainMesh.cpp b/KaplaDemo/samples/sampleViewer3/TerrainMesh.cpp new file mode 100644 index 00000000..e35dd319 --- /dev/null +++ b/KaplaDemo/samples/sampleViewer3/TerrainMesh.cpp @@ -0,0 +1,367 @@ +#include <algorithm> +#include "TerrainMesh.h" +#include "PxPhysics.h" +#include "PxCooking.h" +#include "PxScene.h" +#include "Shader.h" +#include "geometry/PxHeightFieldSample.h" +#include "geometry/PxHeightFieldDesc.h" +#include "geometry/PxHeightFieldGeometry.h" +#include "PxRigidStatic.h" +#include "Texture.h" +#include "TerrainMesh.h" + +#include "PhysXMacros.h" +#include "SceneVehicleSceneQuery.h" +#include "VehicleManager.h" +#include "PxDefaultStreams.h" + +#define USE_HEIGHTFIELD 1 + + +TerrainMesh::~TerrainMesh() { + //myScene->removeActor(*hfActor); + hfActor->release(); + if (mMesh) delete mMesh; +} + +TerrainMesh::TerrainMesh(PxPhysics& physics, PxCooking& cooking, PxScene& scene, PxMaterial& material, PxVec3 midPoint, const char* heightMapName, const char* textureName, float hfScale, float maxHeight, Shader* shader, + bool invert) { + mShader = shader; + mMesh = 0; + myScene = &scene; + BmpLoaderBuffer heightMapFile; + if (!heightMapFile.loadFile(heightMapName)) { + fprintf(stderr, "Error loading bmp '%s'\n"); + return; + } + + const PxReal heightScale = 0.005f; + //const PxReal heightScale = 0.01f; + + unsigned int hfWidth = heightMapFile.mWidth; + unsigned int hfHeight = heightMapFile.mHeight; + unsigned char* heightmap = heightMapFile.mRGB; + const double i255 = 1.0/255.0; + + PxTransform pose = PX_TRANSFORM_ID; + pose.p = midPoint + PxVec3(-((hfWidth - 1)*0.5f*hfScale), 0, -((hfHeight - 1)*0.5f*hfScale)); + mHFPose = pose; + + + PxU32 hfNumVerts = hfWidth*hfHeight; + + PxHeightFieldSample* samples = new PxHeightFieldSample[hfNumVerts]; + memset(samples,0,hfNumVerts*sizeof(PxHeightFieldSample)); + + + PxFilterData simulationFilterData; + simulationFilterData.word0 = COLLISION_FLAG_GROUND; + simulationFilterData.word1 = COLLISION_FLAG_GROUND_AGAINST; + PxFilterData queryFilterData; + VehicleSetupDrivableShapeQueryFilterData(&queryFilterData); + static PxI32 maxH = -2000000; + static PxI32 minH = 20000000; + for(PxU32 y = 0; y < hfHeight; y++) + { + for(PxU32 x = 0; x < hfWidth; x++) + { + + PxU8 heightVal = heightmap[(y + x*hfWidth) * 3]; + if (invert) + heightVal = 255 - heightVal; + PxI32 h = PxI32((maxHeight*heightVal*i255) / heightScale); + //Do a snap-to-grid... + + h = ((h >> 4) << 4); + + maxH = PxMax(h, maxH); + minH = PxMin(h, minH); + + //h = h & (~0x7f); + + //printf("%d ", h); + PX_ASSERT(h<=0xffff); + + const PxU32 Index = x + y*hfWidth; + samples[Index].height = (PxI16)(h); + samples[Index].materialIndex0 = 0; + samples[Index].materialIndex1 = 0; + samples[Index].clearTessFlag(); + } + } + + + + + + // texture + if (strcmp(textureName, "") == 0) hfTexture = 0; else + hfTexture = loadImgTexture(textureName); + mMesh = new GLMesh(GL_TRIANGLES); + mMesh->vertices.resize(hfNumVerts); + mMesh->normals.resize(hfNumVerts); + mMesh->texCoords.resize(hfNumVerts*2); + mMesh->indices.clear(); + float us = 1.0f / hfWidth; + float vs = 1.0f / hfHeight; + terrainHeights.clear(); + terrainNormals.clear(); + for (int i = 0; i < hfHeight; i++) + { + for (int j = 0; j < hfWidth; j++) + { + PxReal height = PxReal(samples[i + j*hfWidth].height) * heightScale; + + mMesh->vertices[i*hfWidth + j] = PxVec3(hfScale*j, height, hfScale*i) + pose.p; + terrainHeights.push_back(mMesh->vertices[i*hfWidth+j].y); + mMesh->texCoords[(i*hfWidth + j)*2] = j*us; + mMesh->texCoords[(i*hfWidth + j)*2+1] = i*vs; + } + } + + xStart = pose.p.x; + zStart = pose.p.z; + dx = hfScale; + + for (int i = 0; i < hfHeight-1; i++) { + for (int j = 0; j < hfWidth-1; j++) { + //mMesh->vertices[i*hfWidth + j] = PxVec3(hfScale*j, maxHeight*heightmap[(j+i*hfWidth)*3]*i255, hfScale*i); + + + mMesh->indices.push_back(j + i*hfWidth); + mMesh->indices.push_back(j + (i + 1)*hfWidth); + mMesh->indices.push_back((j + 1) + i*hfWidth); + + mMesh->indices.push_back((j + 1) + i*hfWidth); + mMesh->indices.push_back(j + (i + 1)*hfWidth); + mMesh->indices.push_back((j + 1) + (i + 1)*hfWidth); + + } + } + mMesh->normals.resize(hfNumVerts); + for (int i = 0; i < hfNumVerts; i++) { + mMesh->normals[i] = PxVec3(0.0f, 0.0f, 0.0f); + } + + int numTris = mMesh->indices.size() / 3; + for (int i = 0; i < numTris; i++) { + int i0 = mMesh->indices[i*3]; + int i1 = mMesh->indices[i*3+1]; + int i2 = mMesh->indices[i*3+2]; + PxVec3 p0 = mMesh->vertices[i0]; + PxVec3 p1 = mMesh->vertices[i1]; + PxVec3 p2 = mMesh->vertices[i2]; + + PxVec3 normal = (p1-p0).cross(p2-p0); + mMesh->normals[i0] += normal; + mMesh->normals[i1] += normal; + mMesh->normals[i2] += normal; + } + for (int i = 0; i < hfNumVerts; i++) { + mMesh->normals[i].normalize(); + } + mMesh->genVBOIBO(); + mMesh->updateVBOIBO(false); + mMaterial.init(); + mMaterial.texId = hfTexture; + + terrainNormals = mMesh->normals; + + width = hfWidth; + height = hfHeight; + idx = 1.0f/dx; + + +#if USE_HEIGHTFIELD + + PxHeightFieldDesc hfDesc; + //hfDesc.format = PxHeightFieldFormat::eS16_TM; + hfDesc.nbColumns = hfWidth; + hfDesc.nbRows = hfHeight; + hfDesc.samples.data = samples; + hfDesc.samples.stride = sizeof(PxHeightFieldSample); + + PxHeightField* heightField = cooking.createHeightField(hfDesc, physics.getPhysicsInsertionCallback()); + + + + hfActor = physics.createRigidStatic(pose); + + PxHeightFieldGeometry hfGeom(heightField, PxMeshGeometryFlags(), heightScale, hfScale, hfScale); + PxShape* hfShape = hfActor->createShape(hfGeom, material); + + hfShape->setQueryFilterData(queryFilterData); + hfShape->setSimulationFilterData(simulationFilterData); + + scene.addActor(*hfActor); + + delete[] samples; +#else + PxTriangleMeshDesc meshDesc; + + meshDesc.points.data = &mMesh->vertices[0]; + meshDesc.points.count = mMesh->vertices.size(); + meshDesc.points.stride = sizeof(PxVec3); + + meshDesc.triangles.stride = sizeof(PxU32)*3; + meshDesc.triangles.count = mMesh->indices.size()/3; + meshDesc.triangles.data = &mMesh->indices[0]; + + meshDesc.flags = PxMeshFlags(); + + PxTriangleMeshGeometry geom; + + PxCookingParams params = cooking.getParams(); + params.buildGRBData = true; + + cooking.setParams(params); + + PxDefaultMemoryOutputStream writeBuffer; + bool status = cooking.cookTriangleMesh(meshDesc, writeBuffer); + PX_ASSERT(status); + PxDefaultMemoryInputData readBuffer(writeBuffer.getData(), writeBuffer.getSize()); + PxTriangleMesh* triangleMesh = physics.createTriangleMesh(readBuffer); + + geom.triangleMesh = triangleMesh; + + hfActor = physics.createRigidStatic(PxTransform(PxIdentity)); + + PxShape* meshShape = hfActor->createShape(geom, material); + + meshShape->setQueryFilterData(queryFilterData); + meshShape->setSimulationFilterData(simulationFilterData); + + scene.addActor(*hfActor); + + +#endif + + +} + +void TerrainMesh::draw(bool useShader) { + if (useShader) mShader->activate(mMaterial); + mMesh->drawVBOIBO(); + if (useShader) mShader->deactivate(); +} + + +float TerrainMesh::getHeight(float x, float z) { + + float nx = (x-xStart)*idx; + float nz = (z-zStart)*idx; + + int ix = floor(nx); + int iz = floor(nz); + float fx = nx-ix; + float fz = nz-iz; + + int ixp1 = ix+1; + int izp1 = iz+1; + ix = min(max(ix,0), width-1); + iz = min(max(iz,0), height-1); + ixp1 = min(max(ixp1,0), width-1); + izp1 = min(max(izp1,0), height-1); + + int i00 = ix+iz*width; + int i10 = ixp1+iz*width; + int i01 = ix+izp1*width; + int i11 = ixp1+izp1*width; + + float w00 = (1.0f-fx)*(1.0f-fz); + float w10 = (fx)*(1.0f-fz); + float w01 = (1.0f-fx)*(fz); + float w11 = (fx)*(fz); + + return w00*terrainHeights[i00] + + w10*terrainHeights[i10] + + w01*terrainHeights[i01] + + w11*terrainHeights[i11]; +} + + +float TerrainMesh::getHeightNormal(float x, float z, PxVec3& normal) { + + float nx = (x-xStart)*idx; + float nz = (z-zStart)*idx; + + int ix = floor(nx); + int iz = floor(nz); + float fx = nx-ix; + float fz = nz-iz; + + int ixp1 = ix+1; + int izp1 = iz+1; + ix = min(max(ix,0), width-1); + iz = min(max(iz,0), height-1); + ixp1 = min(max(ixp1,0), width-1); + izp1 = min(max(izp1,0), height-1); + + int i00 = ix+iz*width; + int i10 = ixp1+iz*width; + int i01 = ix+izp1*width; + int i11 = ixp1+izp1*width; + + float w00 = (1.0f-fx)*(1.0f-fz); + float w10 = (fx)*(1.0f-fz); + float w01 = (1.0f-fx)*(fz); + float w11 = (fx)*(fz); + + normal = w00*terrainNormals[i00] + + w10*terrainNormals[i10] + + w01*terrainNormals[i01] + + w11*terrainNormals[i11]; + normal.normalize(); + + return w00*terrainHeights[i00] + + w10*terrainHeights[i10] + + w01*terrainHeights[i01] + + w11*terrainHeights[i11]; + +} + + +float TerrainMesh::getHeightNormalCondition(float x, float y, float z, PxVec3& normal) { + + float nx = (x-xStart)*idx; + float nz = (z-zStart)*idx; + + int ix = floor(nx); + int iz = floor(nz); + float fx = nx-ix; + float fz = nz-iz; + + int ixp1 = ix+1; + int izp1 = iz+1; + ix = min(max(ix,0), width-1); + iz = min(max(iz,0), height-1); + ixp1 = min(max(ixp1,0), width-1); + izp1 = min(max(izp1,0), height-1); + + int i00 = ix+iz*width; + int i10 = ixp1+iz*width; + int i01 = ix+izp1*width; + int i11 = ixp1+izp1*width; + + float w00 = (1.0f-fx)*(1.0f-fz); + float w10 = (fx)*(1.0f-fz); + float w01 = (1.0f-fx)*(fz); + float w11 = (fx)*(fz); + + float h = w00*terrainHeights[i00] + + w10*terrainHeights[i10] + + w01*terrainHeights[i01] + + w11*terrainHeights[i11]; + + if (h <= y) { + normal = w00*terrainNormals[i00] + + w10*terrainNormals[i10] + + w01*terrainNormals[i01] + + w11*terrainNormals[i11]; + normal.normalize(); + + } + + return h; +} |