#include "dxstdafx.h" #include "./Terrain.h" #include #include "UserContactReport.h" #include "NxPhysics.h" Terrain::Terrain(void):Node() { this->nodeType |= GameScene::NODE_TERRAIN; } void Terrain::generateTerrain(std::string filename, int _numVertsPerRow, int _numVertsPerCol) { numVertsPerRow = _numVertsPerRow; numVertsPerCol = _numVertsPerCol; cellSpacing = this->myScene->getWidth() / (_numVertsPerRow - 1); heightScale = this->myScene->getHeight() / 255; numVertices = numVertsPerRow * numVertsPerCol; patchSize = 16; numberOfPatches = (numVertsPerRow-1)/patchSize * (numVertsPerCol-1)/patchSize; //read heightmap heightmap = readRawFile(filename); //scale heights for(UINT i = 0; i < heightmap.size(); i++) heightmap[i] *= heightScale; //copy to checkmap originalHeightmap.resize(heightmap.size()); for(UINT i = 0; i < heightmap.size(); i++) originalHeightmap[i] = heightmap[i]; //create Material(s) standardMats = new D3DMATERIAL9[1]; memset(standardMats, 0, 1); standardMats[0].Diffuse = D3DXCOLOR(1.0f, 1.0f, 1.0f, 1.0f); standardMats[0].Ambient = D3DXCOLOR(1.0f, 1.0f, 1.0f, 1.0f); standardMats[0].Specular = D3DXCOLOR(0.0f, 0.0f, 0.0f, 1.0f); standardMats[0].Emissive = D3DXCOLOR(0.0f, 0.0f, 0.0f, 1.0f); standardMats[0].Power = 5.0f; // load Dummy Texture for raytracer: Textures.push_back(0); //load effect loadEffect(); //create patches createTerrainPatches(); } Terrain::~Terrain(void) { for (int i = 0; i < numberOfPatches; i++) { //terrainPatches[i].clear(); } terrainPatches.clear(); delete [] standardMats; } void Terrain::setTextures(std::string texture0, std::string texture1, std::string texture2) { this->texture0 = texture0; this->texture1 = texture1; this->texture2 = texture2; this->texture3 = texture3; } std::vector Terrain::readRawFile(std::string fileName) { std::vector heightmap(numVertices); // A height for each vertex std::vector in( numVertices ); std::ifstream inFile(fileName.c_str(), std::ios_base::binary); if( inFile == 0 ) this->myScene->manager->printToConsole("Error loading heightmap"); else this->myScene->manager->printToConsole("heightmap loaded successfully"); inFile.read( (char*)&in[0], // buffer (std::streamsize)in.size());// number of bytes to read into buffer inFile.close(); // copy BYTE vector to int vector heightmap.resize(numVertices); for(UINT i = 0; i < in.size(); i++) heightmap[i] = in[i]; return heightmap; } void Terrain::loadEffect() { this->TerrainEffect = this->myScene->manager->getEffect(GameManager::EFFECT_TERRAIN); if(!this->TerrainEffect) { this->TerrainEffect = this->myScene->manager->loadEffect(GameManager::EFFECT_TERRAIN, L"shaders/terrain.obj"); } // // Save Frequently Accessed Parameter Handles // TexHandleTop = TerrainEffect->GetParameterByName(0, "Top"); TexHandleSlope = TerrainEffect->GetParameterByName(0, "Slope"); TexHandleBottom = TerrainEffect->GetParameterByName(0, "Bottom"); AmbientHandle = TerrainEffect->GetParameterByName(0, "Ambient"); SunDirectionHandle = TerrainEffect->GetParameterByName(0, "Sun_Direction"); ShaderTechHandle = TerrainEffect->GetTechniqueByName("TerrainShader"); // // Set Effect Parameters // // // Set texture IDirect3DTexture9* tex = 0; tex = this->myScene->manager->resManager.loadTexture(this->texture0); TerrainEffect->SetTexture(TexHandleTop, tex); tex = 0; tex = this->myScene->manager->resManager.loadTexture(this->texture1); TerrainEffect->SetTexture(TexHandleSlope, tex); tex = 0; tex = this->myScene->manager->resManager.loadTexture(this->texture2); TerrainEffect->SetTexture(TexHandleBottom, tex); //set light for shader:: Vector temp = this->myScene->getSunDirection(); temp.normalize(); D3DXVECTOR4 lightDirection(-temp.x, -temp.y, -temp.z, 0); TerrainEffect->SetVector(SunDirectionHandle, &lightDirection); TerrainEffect->SetVector(AmbientHandle, &D3DXVECTOR4(0.4f, 0.4f, 0.4f, 0)); } float Terrain::getHeight(float x, float z) { if(x<0 || z<0 || x>this->getSizeX() || z>this->getSizeZ() ) return 0; x = x/this->cellSpacing; z = z/this->cellSpacing; int x_int = (int)x; int z_int = (int)z; float height1 = heightmap[x_int + z_int * this->numVertsPerCol] + (x - x_int)*(heightmap[x_int +1 + z_int * this->numVertsPerCol] - heightmap[x_int + z_int * this->numVertsPerCol]); float height2 = heightmap[x_int + (z_int+1) * this->numVertsPerCol] + (x - x_int)*(heightmap[x_int +1 + (z_int+1) * this->numVertsPerCol] - heightmap[x_int + (z_int+1) * this->numVertsPerCol]); return (height1 + (z - z_int) * (height2 - height1)); } float Terrain::getOriginalHeight(float x, float z) { if(x<0 || z<0 || x>this->getSizeX() || z>this->getSizeZ() ) return 0; x = x/this->cellSpacing; z = z/this->cellSpacing; int x_int = (int)x; int z_int = (int)z; float height1 = originalHeightmap[x_int + z_int * this->numVertsPerCol] + (x - x_int)*(originalHeightmap[x_int +1 + z_int * this->numVertsPerCol] - originalHeightmap[x_int + z_int * this->numVertsPerCol]); float height2 = originalHeightmap[x_int + (z_int+1) * this->numVertsPerCol] + (x - x_int)*(originalHeightmap[x_int +1 + (z_int+1) * this->numVertsPerCol] - originalHeightmap[x_int + (z_int+1) * this->numVertsPerCol]); return (height1 + (z - z_int) * (height2 - height1)); } float Terrain::getSizeX() { return (this->numVertsPerRow-1) * this->cellSpacing; } float Terrain::getSizeZ() { return (this->numVertsPerCol-1) * this->cellSpacing; } float Terrain::getSlopeX(float x, float z) { if(x<0 || z<0 || x>this->getSizeX() || z>this->getSizeZ() ) return 0; x = x/this->cellSpacing; z = z/this->cellSpacing; int x_int = (int)x; int z_int = (int)z; return heightmap[(x_int + 1) + z_int*this->numVertsPerCol] - heightmap[x_int + z_int*this->numVertsPerCol]; } float Terrain::getSlopeZ(float x, float z) { if(x<0 || z<0 || x>this->getSizeX() || z>this->getSizeZ() ) return 0; x = x/this->cellSpacing; z = z/this->cellSpacing; int x_int = (int)x; int z_int = (int)z; return heightmap[(x_int) + (z_int+1)*this->numVertsPerCol] - heightmap[x_int + z_int*this->numVertsPerCol]; } void Terrain::impact(float x, float z, int powerRadius) { //radius must never be larger than patchSize! if(powerRadius>patchSize) powerRadius = patchSize; //round impacts to int int x_int = (int)(((int)(x + 0.5))/this->cellSpacing); int z_int = (int)(((int)(z + 0.5))/this->cellSpacing); //check that the impact is inside the terrain: if (x_int - powerRadius < 0) { x_int = powerRadius; x = x_int * this->cellSpacing; } if (z_int - powerRadius < 0) { z_int = powerRadius; z = z_int * this->cellSpacing; } if (x_int + powerRadius > this->numVertsPerRow-1) { x_int = this->numVertsPerRow - powerRadius -2; x = x_int * this->cellSpacing; } if (z_int + powerRadius > this->numVertsPerCol-1) { z_int = this->numVertsPerCol - powerRadius -2; z = z_int * this->cellSpacing; } float impactheight = this->getOriginalHeight(x, z) + powerRadius*2*this->cellSpacing/3; //calculate patch coordinates int patch_x=(int)x_int/patchSize; int patch_z=(int)z_int/patchSize; //calculate patch number int patchNumber = (numVertsPerCol-1)/patchSize * patch_z + patch_x; //calculate local coordinates (in patch) int local_x = x_int - patch_x * patchSize; int local_z = z_int - patch_z * patchSize; int leftBorder = local_x - powerRadius; int rightBorder = local_x + powerRadius; int topBorder = local_z - powerRadius; int bottomBorder = local_z + powerRadius; //check patches in the middle //update central patch updatePatch(patchNumber, max(leftBorder, 0), max(topBorder, 0), min(rightBorder, patchSize), min(bottomBorder,patchSize), powerRadius, impactheight, (int)x, (int)z, patch_x, patch_z); if(topBorder <= 0) { //top middle patch affected updatePatch(patchNumber - (numVertsPerCol-1)/patchSize, max(leftBorder,0), patchSize+topBorder, min(patchSize, rightBorder), patchSize, powerRadius, impactheight, (int)x, (int)z, patch_x, patch_z-1); } if (bottomBorder >= patchSize) { //bottom middle patch affected updatePatch(patchNumber + (numVertsPerCol-1)/patchSize, max(leftBorder,0), 0, min(patchSize, rightBorder), bottomBorder-patchSize, powerRadius, impactheight, (int)x, (int)z, patch_x, patch_z+1); } //check patches on the left if(leftBorder <= 0) { //left patches are affected too //middle left patch affected updatePatch(patchNumber-1, patchSize+leftBorder, max(topBorder, 0), patchSize, min(bottomBorder,patchSize), powerRadius, impactheight, (int)x, (int)z, patch_x-1, patch_z); if(topBorder <= 0) { //top left patch affected updatePatch(patchNumber - (numVertsPerCol-1)/patchSize -1, patchSize+leftBorder, patchSize+topBorder, patchSize, patchSize, powerRadius, impactheight, (int)x, (int)z, patch_x-1, patch_z-1); } if (bottomBorder >= patchSize) { //bottom left patch affected updatePatch(patchNumber + (numVertsPerCol-1)/patchSize -1, patchSize+leftBorder, 0, patchSize, bottomBorder-patchSize, powerRadius, impactheight, (int)x, (int)z, patch_x-1, patch_z+1); } } //check patches on the right if(rightBorder >= patchSize) { //right patches are affected too //middle right patch affected updatePatch(patchNumber+1, 0, max(topBorder, 0), rightBorder-patchSize, min(bottomBorder,patchSize), powerRadius, impactheight, (int)x, (int)z, patch_x+1, patch_z); if(topBorder <= 0) { //top right patch affected updatePatch(patchNumber - (numVertsPerCol-1)/patchSize +1, 0, patchSize+topBorder, rightBorder-patchSize, patchSize, powerRadius, impactheight, (int)x, (int)z, patch_x+1, patch_z-1); } if (bottomBorder >= patchSize) { //bottom right patch affected updatePatch(patchNumber + (numVertsPerCol-1)/patchSize +1, 0, 0, rightBorder-patchSize, bottomBorder-patchSize, powerRadius, impactheight, (int)x, (int)z, patch_x+1, patch_z+1); } } } void Terrain::updatePatch(int patchNumber, int x_top, int z_top, int x_bottom, int z_bottom, int powerRadius, float impactheight, int globalImpCenterX, int globalImpCenterZ, int patch_x, int patch_z) { Vertex* pVertices; LPD3DXPMESH * ppMesh = 0; LPD3DXMESH * pMesh = 0; if(patchNumber<0 || patchNumber>=this->numberOfPatches) { return; } int x_offset = patch_x * patchSize; int z_offset = patch_z * patchSize; D3DXCOLOR tempColor; tempColor.r = 0; tempColor.b = 0; tempColor.g = 1; if(this->terrainPatches[patchNumber]->isPMesh()) { ppMesh = this->terrainPatches[patchNumber]->getProgressiveMesh(); int CurrentFaces = (*ppMesh)->GetNumFaces(); (*ppMesh)->SetNumFaces((*ppMesh)->GetMaxFaces()); (*ppMesh)->LockVertexBuffer(D3DLOCK_DISCARD, (void**)&pVertices ); for (int k = 0; k <= patchSize; k++) { for(int l = 0; l <= patchSize; l++) { int CurrentIndex = k*(patchSize+1) + l; float distance = (((pVertices[CurrentIndex].x+(x_offset*this->cellSpacing)) - globalImpCenterX) * ((pVertices[CurrentIndex].x+(x_offset*this->cellSpacing)) - globalImpCenterX) + ((pVertices[CurrentIndex].z+(z_offset*this->cellSpacing)) - globalImpCenterZ) * ((pVertices[CurrentIndex].z+(z_offset*this->cellSpacing)) - globalImpCenterZ)); //float distance = sqrt(((pVertices[CurrentIndex].x) - globalImpCenterX) * ((pVertices[CurrentIndex].x) - globalImpCenterX) + ((pVertices[CurrentIndex].z) - globalImpCenterZ) * ((pVertices[CurrentIndex].z) - globalImpCenterZ)); float radQuadrat = powerRadius*this->cellSpacing * powerRadius*this->cellSpacing; if(radQuadrat >= distance) { float depth = sqrt(radQuadrat - distance); if (pVertices[CurrentIndex].y >= impactheight - depth) { //update vertex in buffer pVertices[CurrentIndex].y = max(0.55f, impactheight - depth); pVertices[CurrentIndex].color = D3DCOLOR_COLORVALUE(tempColor.r,1-tempColor.r-tempColor.b,tempColor.b,0); //update heightmap heightmap[(z_offset+k) * this->numVertsPerCol + (x_offset+l)] = max(0.55f, impactheight - depth); } } } } (*ppMesh)->SetNumFaces(CurrentFaces); } else { pMesh = this->terrainPatches[patchNumber]->getMesh(); (*pMesh)->LockVertexBuffer( D3DLOCK_DISCARD, (void**)&pVertices ); for (int k = z_top; k <= z_bottom; k++) { for(int l = x_top; l <= x_bottom; l++) { int CurrentIndex = k*(patchSize+1) + l; float distance = (((pVertices[CurrentIndex].x+(x_offset*this->cellSpacing)) - globalImpCenterX) * ((pVertices[CurrentIndex].x+(x_offset*this->cellSpacing)) - globalImpCenterX) + ((pVertices[CurrentIndex].z+(z_offset*this->cellSpacing)) - globalImpCenterZ) * ((pVertices[CurrentIndex].z+(z_offset*this->cellSpacing)) - globalImpCenterZ)); float radQuadrat = powerRadius*this->cellSpacing * powerRadius*this->cellSpacing; if(radQuadrat >= distance) { float depth = sqrt(radQuadrat - distance); if (pVertices[CurrentIndex].y >= impactheight - depth) { pVertices[CurrentIndex].color = D3DCOLOR_COLORVALUE(tempColor.r,1-tempColor.r-tempColor.b,tempColor.b,0); if(pVertices[CurrentIndex].y > 0.55f) { //update vertex in buffer pVertices[CurrentIndex].y = max(0.55f, impactheight - depth); //update heightmap heightmap[(z_offset+k) * this->numVertsPerCol + (x_offset+l)] = max(0.55f, impactheight - depth); } } } } } } if(this->terrainPatches[patchNumber]->isPMesh()) { (*ppMesh)->UnlockVertexBuffer(); //(*ppMesh)->SetNumFaces((*ppMesh)->GetMaxFaces()/4); } else { (*pMesh)->UnlockVertexBuffer(); } //Recalculate PhysicMesh NxActor* actor = this->terrainPatches[patchNumber]->getActor(); NxActorDesc* actorDesc = this->terrainPatches[patchNumber]->getActorDescriptor(); if(actor->getNbShapes()!=0) { actor->releaseShape(*actor->getShapes()[0]); actorDesc->shapes.popBack(); } this->terrainPatches[patchNumber]->generatePhysicMesh(Object3d::COL_HEIGHTFIELD); actor->createShape(this->terrainPatches[patchNumber]->pMeshShapeDesc); this->terrainPatches[patchNumber]->setColDetGroup(UserContactReport::COLGROUP_TERRAIN); actor->getShapes()[0]->setFlag(NX_SF_VISUALIZATION, false); } Vector* Terrain::getNormals() { // this function is needed for the normal calculation of the WHOLE heightmap // therefore a temporary mesh is created, and the normals calculated with // this mesh are copied into a vector array. // this vector array is later used to set the proper normals in the terrain patches // create the array in which the normals are stored: Vector *tempNormals = new Vector[this->numVertices]; memset(tempNormals, 0, this->numVertices); //creating mesh pointer LPD3DXMESH pMesh; //generate mesh HRESULT hr = D3DXCreateMeshFVF((this->numVertsPerCol-1) * (this->numVertsPerRow-1) * 2, numVertices, D3DXMESH_DYNAMIC, Vertex::FVF_Flags, DXUTGetD3DDevice(), &pMesh ); if(hr != S_OK) { this->myScene->manager->printToConsole("error occured during mesh initialization!"); } //vertices array: Vertex* pVertices; int count = 0; // fill the vertices: int StartIndex = 0; pMesh->LockVertexBuffer( 0, (void**)&pVertices ); for (int k = 0; k < this->numVertsPerCol; k++) { for(int l = 0; l < this->numVertsPerRow; l++) { int CurrentIndex = StartIndex + l; pVertices[count++] = Vertex(l * cellSpacing, (float)heightmap[CurrentIndex], k * cellSpacing, 0,0,0,0x00000000,0,0); } StartIndex += numVertsPerRow; } pMesh->UnlockVertexBuffer(); // fill the indices: int baseIndex = 0; WORD* pIndicesBig = NULL; pMesh->LockIndexBuffer( 0, (void**)&pIndicesBig ); { for(int k = 0; k < numVertsPerCol-1; k++) { for(int l = 0; l < numVertsPerRow-1; l++) { pIndicesBig[baseIndex] = (WORD)((k+1) * (numVertsPerRow) + l); pIndicesBig[baseIndex + 1] = (WORD)(k * (numVertsPerRow) + l + 1); pIndicesBig[baseIndex + 2] = (WORD)(k * (numVertsPerRow) + l); pIndicesBig[baseIndex + 3] = (WORD)((k+1) * (numVertsPerRow) + l + 1); pIndicesBig[baseIndex + 4] = (WORD)(k * (numVertsPerRow) + l + 1); pIndicesBig[baseIndex + 5] = (WORD)((k+1) * (numVertsPerRow) + l); // next quad baseIndex += 6; } } } pMesh->UnlockIndexBuffer(); //generate new DWORD array DWORD *adjacencyInfo = new DWORD[pMesh->GetNumFaces() * 3]; memset(adjacencyInfo,0,pMesh->GetNumFaces() * 3); // Get the adjacency info of the mesh. pMesh->GenerateAdjacency(0.0f, adjacencyInfo); // now compute the normals: D3DXComputeNormals(pMesh, adjacencyInfo); // now copy the proper normals into the array: pMesh->LockVertexBuffer( 0, (void**)&pVertices ); for(UINT i = 0; i < pMesh->GetNumVertices(); i++) { tempNormals[i].x = pVertices[i].nx; tempNormals[i].y = pVertices[i].ny; tempNormals[i].z = pVertices[i].nz; } pMesh->UnlockVertexBuffer(); //clean up: delete [] adjacencyInfo; pMesh->Release(); return tempNormals; } void Terrain::createTerrainPatches() { float min_height = 1000; //needed for blending factors float max_height = 0; //needed for blending factors // check & set max height values for multitex for(UINT i = 0; i < this->heightmap.size(); i++) { if (heightmap[i] < min_height) { min_height = heightmap[i]; } if (heightmap[i] > max_height) { max_height = heightmap[i]; } } min_height /= 255; max_height /= 255; //calculate normals normals = getNormals(); // create weights array for progressive mesh so no gaps between the patches appear! float *weights = new float[(this->patchSize+1)*(this->patchSize+1)]; memset(weights, 0, (this->patchSize+1)*(this->patchSize+1)); char temp[100]; sprintf(temp, "Number of terrain patches: %d", numberOfPatches); this->myScene->manager->printToConsole(temp); int currentPatch = 0; for (int i = 0; i < (numVertsPerCol-1)/patchSize; i++) { for (int j = 0; j < (numVertsPerRow-1)/patchSize; j++) { //calculate current patch index currentPatch = i*(numVertsPerCol-1)/patchSize + j; //generate Object3d for current patch and add it to the scene //Object3d *p = (Object3d *) this->myScene->createNode(this->myScene->NODE_OBJECT3D, *this->myScene->getRoot(), true); Object3d *p = (Object3d *) this->myScene->createNode(this->myScene->NODE_OBJECT3D, *this->myScene->getRoot(), false); //set bounding box to HUGE :) p->minAABBox.x = minAABBox.y = minAABBox.z = 9999999; p->maxAABBox.x = maxAABBox.y = maxAABBox.z = -9999999; SPTR renderer(new TerrainRenderer); renderer->setScene(*this->myScene); TerrainRenderer *temp = (TerrainRenderer*)renderer.get(); temp->setEffect(this->TerrainEffect); this->myScene->connectNodeAndRenderer(*p, renderer); //set mesh position //p->setPosition(0.0f, 0.0f, 0.0f); p->setPosition(j * patchSize * cellSpacing, 0, i * patchSize * cellSpacing); //creating mesh pointer LPD3DXMESH * pMesh = p->getMesh(); //generate mesh HRESULT hr = 0; hr = D3DXCreateMeshFVF((patchSize * patchSize *2), ((patchSize+1)*(patchSize+1)), D3DXMESH_MANAGED, Vertex::FVF_Flags, DXUTGetD3DDevice(), pMesh ); if(hr != S_OK) { this->myScene->manager->printToConsole("error occured during mesh initialization!"); } //vertices array: Vertex* pVertices; int count = 0; //lock vertex buffer (*pMesh)->LockVertexBuffer( 0, (void**)&pVertices ); // fill the vertices: int StartIndex = i * patchSize * numVertsPerCol + j * patchSize; for (int k = 0; k <= patchSize; k++) { for(int l = 0; l <= patchSize; l++) { int CurrentIndex = StartIndex + l; // set the vertex data pVertices[count] = Vertex(l * cellSpacing, (float)heightmap[CurrentIndex], k * cellSpacing, normals[CurrentIndex].x, normals[CurrentIndex].y, normals[CurrentIndex].z, 0x00000000, (float)(j*patchSize+l) * 1/this->numVertsPerRow*16, (float)(i*patchSize+k) * 1/this->numVertsPerCol*16); // check bounding box: if (pVertices[count].x < p->minAABBox.x) p->minAABBox.x = pVertices[count].x; if (pVertices[count].y < p->minAABBox.y) p->minAABBox.y = pVertices[count].y; if (pVertices[count].z < p->minAABBox.z) p->minAABBox.z = pVertices[count].z; if (pVertices[count].x > p->maxAABBox.x) p->maxAABBox.x = pVertices[count].x; if (pVertices[count].y > p->maxAABBox.y) p->maxAABBox.y = pVertices[count].y; if (pVertices[count].z > p->maxAABBox.z) p->maxAABBox.z = pVertices[count].z; // set the weight if (l == 0 || k == 0 || l == patchSize || k == patchSize) { weights[count] = 1.0f; } else { weights[count] = 0.0f; } count++; } StartIndex += numVertsPerRow; } //unlock vertex buffer (*pMesh)->UnlockVertexBuffer(); // fill the indices: WORD* pIndices = NULL; DWORD* attributeBuffer = NULL; //to define the subsets int baseIndex = 0; int attrCount = 0; (*pMesh)->LockIndexBuffer( 0, (void**)&pIndices ); (*pMesh)->LockAttributeBuffer(0, &attributeBuffer); (*pMesh)->LockVertexBuffer( 0, (void**)&pVertices ); { for(int k = 0; k < patchSize; k++) { for(int l = 0; l < patchSize; l++) { pIndices[baseIndex] = (WORD)((k+1) * (patchSize+1) + l); pIndices[baseIndex + 1] = (WORD)(k * (patchSize+1) + l + 1); pIndices[baseIndex + 2] = (WORD)(k * (patchSize+1) + l); //if(pVertices[pIndices[baseIndex]].y == 0 && pVertices[pIndices[baseIndex + 1]].y == 0 && pVertices[pIndices[baseIndex + 2]].y == 0) { // attributeBuffer[attrCount++] = 1; //} else { attributeBuffer[attrCount++] = 0; //} pIndices[baseIndex + 3] = (WORD)((k+1) * (patchSize+1) + l + 1); pIndices[baseIndex + 4] = (WORD)(k * (patchSize+1) + l + 1); pIndices[baseIndex + 5] = (WORD)((k+1) * (patchSize+1) + l); //if(pVertices[pIndices[baseIndex + 3]].y == 0 && pVertices[pIndices[baseIndex + 4]].y == 0 && pVertices[pIndices[baseIndex + 5]].y == 0) { // attributeBuffer[attrCount++] = 1; //} else { attributeBuffer[attrCount++] = 0; //} // next quad baseIndex += 6; } } } (*pMesh)->UnlockVertexBuffer(); (*pMesh)->UnlockAttributeBuffer(); (*pMesh)->UnlockIndexBuffer(); // assign material array: p->Materials.push_back(standardMats[0]); // assign textures: for (UINT k = 0; k < this->Textures.size(); k++) { p->Textures.push_back(this->Textures[0]); } // assign colours for multitexturing: Vector nach_oben (0,1,0); (*pMesh)->LockVertexBuffer( 0, (void**)&pVertices ); for (int k = 0; k < (patchSize+1); k++) { for (int l = 0; l < (patchSize+1); l++) { int curPatch = k * (patchSize + 1) + l; D3DXCOLOR tempColor; Vector vertnormal(pVertices[curPatch].nx, pVertices[curPatch].ny, pVertices[curPatch].nz); tempColor.r = (pVertices[curPatch].y / 255 - min_height) * (1 / (max_height-min_height)); tempColor.b = 1 - tempColor.r; tempColor.g = (nach_oben.dotProd(vertnormal)); //versuch das ganze zu verbessern: if(tempColor.g < 0.9) { tempColor.g *= tempColor.g * tempColor.g; tempColor.r *= tempColor.g; tempColor.b *= tempColor.g; } else { tempColor.g = 0; } pVertices[curPatch].color = D3DCOLOR_COLORVALUE(tempColor.r,1-tempColor.r-tempColor.b,tempColor.b,0); } } (*pMesh)->UnlockVertexBuffer(); // model creation finished, set value to true p->setModelLoaded(true); //PhysicHeightfield Stuff p->generatePhysicMesh(p->COL_HEIGHTFIELD); p->setBehaveAs(p->KINEMATIC); p->setColDetGroup(UserContactReport::COLGROUP_TERRAIN); p->getActor()->setSolverIterationCount(2); p->getActor()->getShapes()[0]->setFlag(NX_SF_VISUALIZATION, false); // convert to progressive mesh // ich nehm das mal raus, zum zeit sparen beim laden //p->generateAndUsePMesh(weights); //adding patch to vector terrainPatches.push_back(p); } } delete [] weights; delete [] normals; }