source: GTP/trunk/App/Games/Jungle_Rumble/src/Terrain.cpp @ 1378

Revision 1378, 24.2 KB checked in by giegl, 18 years ago (diff)

GTPD - Jungle Rumble - integrate into GTP SVN structure

Line 
1#include "dxstdafx.h"
2#include "./Terrain.h"
3#include <iostream>
4#include "UserContactReport.h"
5#include "NxPhysics.h"
6
7Terrain::Terrain(void):Node() {
8        this->nodeType |= GameScene::NODE_TERRAIN;
9}
10
11void Terrain::generateTerrain(std::string filename, int _numVertsPerRow, int _numVertsPerCol)
12{
13        numVertsPerRow = _numVertsPerRow;
14        numVertsPerCol = _numVertsPerCol;
15        cellSpacing = this->myScene->getWidth() / (_numVertsPerRow - 1);
16        heightScale = this->myScene->getHeight() / 255;
17
18        numVertices = numVertsPerRow * numVertsPerCol;
19        patchSize = 16;
20        numberOfPatches = (numVertsPerRow-1)/patchSize * (numVertsPerCol-1)/patchSize;
21       
22        //read heightmap
23        heightmap = readRawFile(filename);
24       
25        //scale heights
26        for(UINT i = 0; i < heightmap.size(); i++)
27                heightmap[i] *= heightScale;
28       
29        //copy to checkmap
30        originalHeightmap.resize(heightmap.size());
31        for(UINT i = 0; i < heightmap.size(); i++)
32                originalHeightmap[i] = heightmap[i];
33       
34        //create Material(s)
35        standardMats = new D3DMATERIAL9[1];
36        memset(standardMats, 0, 1);
37
38        standardMats[0].Diffuse = D3DXCOLOR(1.0f, 1.0f, 1.0f, 1.0f);
39        standardMats[0].Ambient = D3DXCOLOR(1.0f, 1.0f, 1.0f, 1.0f);
40        standardMats[0].Specular = D3DXCOLOR(0.0f, 0.0f, 0.0f, 1.0f);
41        standardMats[0].Emissive = D3DXCOLOR(0.0f, 0.0f, 0.0f, 1.0f);
42        standardMats[0].Power = 5.0f;
43
44        // load Dummy Texture for raytracer:
45        Textures.push_back(0);
46       
47        //load effect
48        loadEffect();
49
50        //create patches
51        createTerrainPatches();
52}
53
54Terrain::~Terrain(void)
55{
56       
57        for (int i = 0; i < numberOfPatches; i++) {
58                //terrainPatches[i].clear();
59        }
60
61        terrainPatches.clear();
62
63        delete [] standardMats;
64}
65
66void Terrain::setTextures(std::string texture0, std::string texture1, std::string texture2) {
67        this->texture0 = texture0;
68        this->texture1 = texture1;
69        this->texture2 = texture2;
70        this->texture3 = texture3;
71}
72
73std::vector<float> Terrain::readRawFile(std::string fileName)
74{
75        std::vector<float> heightmap(numVertices);
76        // A height for each vertex
77        std::vector<BYTE> in( numVertices );
78        std::ifstream inFile(fileName.c_str(), std::ios_base::binary);
79        if( inFile == 0 )
80                this->myScene->manager->printToConsole("Error loading heightmap");
81        else
82                this->myScene->manager->printToConsole("heightmap loaded successfully");
83
84        inFile.read(
85                (char*)&in[0], // buffer
86                (std::streamsize)in.size());// number of bytes to read into buffer
87       
88        inFile.close();
89
90        // copy BYTE vector to int vector
91        heightmap.resize(numVertices);
92        for(UINT i = 0; i < in.size(); i++)
93                heightmap[i] = in[i];
94       
95        return heightmap;
96}
97
98void Terrain::loadEffect() {
99       
100        this->TerrainEffect = this->myScene->manager->getEffect(GameManager::EFFECT_TERRAIN);
101        if(!this->TerrainEffect) {
102                this->TerrainEffect = this->myScene->manager->loadEffect(GameManager::EFFECT_TERRAIN, L"shaders/terrain.obj");
103        }
104
105        //
106        // Save Frequently Accessed Parameter Handles
107        //
108        TexHandleTop = TerrainEffect->GetParameterByName(0, "Top");
109        TexHandleSlope = TerrainEffect->GetParameterByName(0, "Slope");
110        TexHandleBottom = TerrainEffect->GetParameterByName(0, "Bottom");
111        AmbientHandle = TerrainEffect->GetParameterByName(0, "Ambient");
112        SunDirectionHandle = TerrainEffect->GetParameterByName(0, "Sun_Direction");
113        ShaderTechHandle = TerrainEffect->GetTechniqueByName("TerrainShader");
114       
115        //
116        // Set Effect Parameters
117        //
118
119        //
120        // Set texture
121        IDirect3DTexture9* tex = 0;
122        tex = this->myScene->manager->resManager.loadTexture(this->texture0);
123        TerrainEffect->SetTexture(TexHandleTop, tex);
124       
125        tex = 0;
126        tex = this->myScene->manager->resManager.loadTexture(this->texture1);
127        TerrainEffect->SetTexture(TexHandleSlope, tex);
128       
129        tex = 0;
130        tex = this->myScene->manager->resManager.loadTexture(this->texture2);
131        TerrainEffect->SetTexture(TexHandleBottom, tex);
132
133        //set light for shader::
134        Vector temp = this->myScene->getSunDirection();
135        temp.normalize();
136
137        D3DXVECTOR4 lightDirection(-temp.x, -temp.y, -temp.z, 0);
138       
139        TerrainEffect->SetVector(SunDirectionHandle, &lightDirection);
140        TerrainEffect->SetVector(AmbientHandle, &D3DXVECTOR4(0.4f, 0.4f, 0.4f, 0));
141}
142
143float Terrain::getHeight(float x, float z)
144{
145        if(x<0 || z<0 || x>this->getSizeX() || z>this->getSizeZ() )
146                return 0;
147
148        x = x/this->cellSpacing;
149        z = z/this->cellSpacing;
150        int x_int = (int)x;
151        int z_int = (int)z;
152
153        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]);
154        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]);
155        return (height1 + (z - z_int) * (height2 - height1));
156}
157
158float Terrain::getOriginalHeight(float x, float z)
159{
160        if(x<0 || z<0 || x>this->getSizeX() || z>this->getSizeZ() )
161                return 0;
162
163        x = x/this->cellSpacing;
164        z = z/this->cellSpacing;
165        int x_int = (int)x;
166        int z_int = (int)z;
167
168        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]);
169        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]);
170        return (height1 + (z - z_int) * (height2 - height1));
171}
172
173float Terrain::getSizeX() {
174        return (this->numVertsPerRow-1) * this->cellSpacing;   
175}
176
177float Terrain::getSizeZ() {
178        return (this->numVertsPerCol-1) * this->cellSpacing;   
179}
180
181float Terrain::getSlopeX(float x, float z) {
182        if(x<0 || z<0 || x>this->getSizeX() || z>this->getSizeZ() )
183                return 0;
184
185        x = x/this->cellSpacing;
186        z = z/this->cellSpacing;
187        int x_int = (int)x;
188        int z_int = (int)z;
189       
190        return heightmap[(x_int + 1) + z_int*this->numVertsPerCol] - heightmap[x_int + z_int*this->numVertsPerCol];
191}
192
193float Terrain::getSlopeZ(float x, float z) {
194        if(x<0 || z<0 || x>this->getSizeX() || z>this->getSizeZ() )
195                return 0;
196        x = x/this->cellSpacing;
197        z = z/this->cellSpacing;
198        int x_int = (int)x;
199        int z_int = (int)z;
200
201        return heightmap[(x_int) + (z_int+1)*this->numVertsPerCol] - heightmap[x_int + z_int*this->numVertsPerCol];
202}
203
204void Terrain::impact(float x, float z, int powerRadius) {
205        //radius must never be larger than patchSize!
206        if(powerRadius>patchSize)
207                powerRadius = patchSize;
208
209        //round impacts to int
210        int x_int = (int)(((int)(x + 0.5))/this->cellSpacing);
211        int z_int = (int)(((int)(z + 0.5))/this->cellSpacing);
212       
213        //check that the impact is inside the terrain:
214        if (x_int - powerRadius < 0) {
215                x_int = powerRadius;
216                x = x_int * this->cellSpacing;
217        }
218        if (z_int - powerRadius < 0) {
219        z_int = powerRadius;
220                z = z_int * this->cellSpacing;
221        }
222        if (x_int + powerRadius > this->numVertsPerRow-1) {
223        x_int = this->numVertsPerRow - powerRadius -2;
224                x = x_int * this->cellSpacing;
225        }
226        if (z_int + powerRadius > this->numVertsPerCol-1) {
227                z_int = this->numVertsPerCol - powerRadius -2;
228                z = z_int * this->cellSpacing;
229        }
230       
231        float impactheight = this->getOriginalHeight(x, z) + powerRadius*2*this->cellSpacing/3;
232       
233        //calculate patch coordinates
234        int patch_x=(int)x_int/patchSize;
235        int patch_z=(int)z_int/patchSize;
236       
237        //calculate patch number
238        int patchNumber = (numVertsPerCol-1)/patchSize * patch_z + patch_x;
239       
240        //calculate local coordinates (in patch)
241        int local_x = x_int - patch_x * patchSize;
242        int local_z = z_int - patch_z * patchSize;
243       
244        int leftBorder = local_x - powerRadius;
245        int rightBorder = local_x + powerRadius;
246        int topBorder = local_z - powerRadius;
247        int bottomBorder = local_z + powerRadius;
248       
249        //check patches in the middle
250        //update central patch
251        updatePatch(patchNumber, max(leftBorder, 0), max(topBorder, 0), min(rightBorder, patchSize), min(bottomBorder,patchSize), powerRadius, impactheight, (int)x, (int)z, patch_x, patch_z);
252        if(topBorder <= 0) {
253                //top middle patch affected
254                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);
255        }
256        if (bottomBorder >= patchSize) {
257                //bottom middle patch affected
258                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);
259        }
260
261        //check patches on the left
262        if(leftBorder <= 0) {
263                //left patches are affected too
264                //middle left patch affected
265                updatePatch(patchNumber-1, patchSize+leftBorder, max(topBorder, 0), patchSize, min(bottomBorder,patchSize), powerRadius, impactheight, (int)x, (int)z, patch_x-1, patch_z);
266                if(topBorder <= 0) {
267                        //top left patch affected
268                        updatePatch(patchNumber - (numVertsPerCol-1)/patchSize -1, patchSize+leftBorder, patchSize+topBorder, patchSize, patchSize, powerRadius, impactheight, (int)x, (int)z, patch_x-1, patch_z-1);
269                }
270                if (bottomBorder >= patchSize) {
271                        //bottom left patch affected
272                        updatePatch(patchNumber + (numVertsPerCol-1)/patchSize -1, patchSize+leftBorder, 0, patchSize, bottomBorder-patchSize, powerRadius, impactheight, (int)x, (int)z, patch_x-1, patch_z+1);
273                }
274        }
275
276        //check patches on the right
277        if(rightBorder >= patchSize) {
278                //right patches are affected too
279                //middle right patch affected
280                updatePatch(patchNumber+1, 0, max(topBorder, 0), rightBorder-patchSize, min(bottomBorder,patchSize), powerRadius, impactheight, (int)x, (int)z, patch_x+1, patch_z);
281                if(topBorder <= 0) {
282                        //top right patch affected
283                        updatePatch(patchNumber - (numVertsPerCol-1)/patchSize +1, 0, patchSize+topBorder, rightBorder-patchSize, patchSize, powerRadius, impactheight, (int)x, (int)z, patch_x+1, patch_z-1);
284                }
285                if (bottomBorder >= patchSize) {
286                        //bottom right patch affected
287                        updatePatch(patchNumber + (numVertsPerCol-1)/patchSize +1, 0, 0, rightBorder-patchSize, bottomBorder-patchSize, powerRadius, impactheight, (int)x, (int)z, patch_x+1, patch_z+1);
288                }
289        }
290}
291
292void 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) {
293        Vertex* pVertices;
294        LPD3DXPMESH * ppMesh = 0;
295        LPD3DXMESH * pMesh = 0;
296       
297        if(patchNumber<0 || patchNumber>=this->numberOfPatches) {
298                return;
299        }
300       
301        int x_offset = patch_x * patchSize;
302        int z_offset = patch_z * patchSize;
303
304        D3DXCOLOR tempColor;
305        tempColor.r = 0;
306        tempColor.b = 0;
307        tempColor.g = 1;
308
309        if(this->terrainPatches[patchNumber]->isPMesh()) {
310                ppMesh = this->terrainPatches[patchNumber]->getProgressiveMesh();
311                int CurrentFaces = (*ppMesh)->GetNumFaces();
312                (*ppMesh)->SetNumFaces((*ppMesh)->GetMaxFaces());
313
314
315                (*ppMesh)->LockVertexBuffer(D3DLOCK_DISCARD, (void**)&pVertices );
316
317                for (int k = 0; k <= patchSize; k++) {
318                        for(int l = 0; l <= patchSize; l++) {
319                                int CurrentIndex = k*(patchSize+1) + l;
320
321                                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));
322                                //float distance = sqrt(((pVertices[CurrentIndex].x) - globalImpCenterX) * ((pVertices[CurrentIndex].x) - globalImpCenterX) + ((pVertices[CurrentIndex].z) - globalImpCenterZ) * ((pVertices[CurrentIndex].z) - globalImpCenterZ));
323                               
324                                float radQuadrat = powerRadius*this->cellSpacing * powerRadius*this->cellSpacing;
325
326                                if(radQuadrat >= distance) {
327                                        float depth = sqrt(radQuadrat - distance);
328                                        if (pVertices[CurrentIndex].y >= impactheight - depth) {
329                                                //update vertex in buffer
330                                                pVertices[CurrentIndex].y = max(0.55f, impactheight - depth);
331                                                pVertices[CurrentIndex].color = D3DCOLOR_COLORVALUE(tempColor.r,1-tempColor.r-tempColor.b,tempColor.b,0);
332                                                //update heightmap
333                                                heightmap[(z_offset+k) * this->numVertsPerCol + (x_offset+l)] = max(0.55f, impactheight - depth);
334                                        }
335                                }
336                        }
337                }
338
339                (*ppMesh)->SetNumFaces(CurrentFaces);
340        } else {
341                pMesh = this->terrainPatches[patchNumber]->getMesh();
342                (*pMesh)->LockVertexBuffer( D3DLOCK_DISCARD, (void**)&pVertices );
343
344                for (int k = z_top; k <= z_bottom; k++) {
345                        for(int l = x_top; l <= x_bottom; l++) {
346                               
347                                int CurrentIndex = k*(patchSize+1) + l;
348
349                                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));
350                               
351                                float radQuadrat = powerRadius*this->cellSpacing * powerRadius*this->cellSpacing;
352
353                                if(radQuadrat >= distance) {
354                                        float depth = sqrt(radQuadrat - distance);
355                                        if (pVertices[CurrentIndex].y >= impactheight - depth) {
356                                                pVertices[CurrentIndex].color = D3DCOLOR_COLORVALUE(tempColor.r,1-tempColor.r-tempColor.b,tempColor.b,0);
357                                                if(pVertices[CurrentIndex].y > 0.55f) {
358                                                        //update vertex in buffer
359                                                        pVertices[CurrentIndex].y = max(0.55f, impactheight - depth);
360                                                       
361                                                        //update heightmap
362                                                        heightmap[(z_offset+k) * this->numVertsPerCol + (x_offset+l)] = max(0.55f, impactheight - depth);
363                                                }
364                                        }
365                                }
366                        }
367                }
368
369        }
370       
371        if(this->terrainPatches[patchNumber]->isPMesh()) {
372                (*ppMesh)->UnlockVertexBuffer();
373                //(*ppMesh)->SetNumFaces((*ppMesh)->GetMaxFaces()/4);
374        } else {
375                (*pMesh)->UnlockVertexBuffer();
376        }
377
378        //Recalculate PhysicMesh
379        NxActor* actor = this->terrainPatches[patchNumber]->getActor();
380        NxActorDesc* actorDesc = this->terrainPatches[patchNumber]->getActorDescriptor();
381        if(actor->getNbShapes()!=0) {
382                actor->releaseShape(*actor->getShapes()[0]);
383                actorDesc->shapes.popBack();
384        }
385        this->terrainPatches[patchNumber]->generatePhysicMesh(Object3d::COL_HEIGHTFIELD);
386        actor->createShape(this->terrainPatches[patchNumber]->pMeshShapeDesc);
387        this->terrainPatches[patchNumber]->setColDetGroup(UserContactReport::COLGROUP_TERRAIN);
388        actor->getShapes()[0]->setFlag(NX_SF_VISUALIZATION, false);
389}
390
391Vector* Terrain::getNormals() {
392        // this function is needed for the normal calculation of the WHOLE heightmap
393        // therefore a temporary mesh is created, and the normals calculated with
394        // this mesh are copied into a vector array.
395        // this vector array is later used to set the proper normals in the terrain patches
396       
397        // create the array in which the normals are stored:
398        Vector *tempNormals = new Vector[this->numVertices];
399        memset(tempNormals, 0, this->numVertices);
400
401        //creating mesh pointer
402        LPD3DXMESH pMesh;
403       
404        //generate mesh
405        HRESULT hr = D3DXCreateMeshFVF((this->numVertsPerCol-1) * (this->numVertsPerRow-1) * 2,
406                                        numVertices,
407                                        D3DXMESH_DYNAMIC,
408                                        Vertex::FVF_Flags,
409                                        DXUTGetD3DDevice(),
410                                        &pMesh
411        );
412
413        if(hr != S_OK) {
414                this->myScene->manager->printToConsole("error occured during mesh initialization!");
415        }
416       
417        //vertices array:
418        Vertex* pVertices;
419        int count = 0;
420       
421        // fill the vertices:
422        int StartIndex = 0;
423        pMesh->LockVertexBuffer( 0, (void**)&pVertices );
424        for (int k = 0; k < this->numVertsPerCol; k++) {
425                for(int l = 0; l < this->numVertsPerRow; l++) {
426                        int CurrentIndex = StartIndex + l;
427                        pVertices[count++] = Vertex(l * cellSpacing, (float)heightmap[CurrentIndex], k * cellSpacing, 0,0,0,0x00000000,0,0);
428                }
429                StartIndex += numVertsPerRow;
430        }
431        pMesh->UnlockVertexBuffer();
432       
433        // fill the indices:
434        int baseIndex = 0;
435        WORD* pIndicesBig = NULL;
436        pMesh->LockIndexBuffer( 0, (void**)&pIndicesBig );
437        {
438                for(int k = 0; k < numVertsPerCol-1; k++)
439                {
440                        for(int l = 0; l < numVertsPerRow-1; l++)
441                        {
442                                pIndicesBig[baseIndex]     =   (WORD)((k+1) * (numVertsPerRow) + l);
443                                pIndicesBig[baseIndex + 1] =   (WORD)(k   * (numVertsPerRow) + l + 1);
444                                pIndicesBig[baseIndex + 2] =    (WORD)(k   * (numVertsPerRow) + l);
445
446                                pIndicesBig[baseIndex + 3] =    (WORD)((k+1) * (numVertsPerRow) + l + 1);
447                                pIndicesBig[baseIndex + 4] =   (WORD)(k   * (numVertsPerRow) + l + 1);
448                                pIndicesBig[baseIndex + 5] =    (WORD)((k+1) * (numVertsPerRow) + l);
449
450                                // next quad
451                                baseIndex += 6;
452                        }
453                }
454        }
455        pMesh->UnlockIndexBuffer();
456       
457        //generate new DWORD array
458        DWORD *adjacencyInfo = new DWORD[pMesh->GetNumFaces() * 3];
459        memset(adjacencyInfo,0,pMesh->GetNumFaces() * 3);
460
461        // Get the adjacency info of the mesh.
462        pMesh->GenerateAdjacency(0.0f, adjacencyInfo);
463
464    // now compute the normals:
465        D3DXComputeNormals(pMesh, adjacencyInfo);
466       
467        // now copy the proper normals into the array:
468        pMesh->LockVertexBuffer( 0, (void**)&pVertices );
469        for(UINT i = 0; i < pMesh->GetNumVertices(); i++) {
470                tempNormals[i].x = pVertices[i].nx;
471                tempNormals[i].y = pVertices[i].ny;
472                tempNormals[i].z = pVertices[i].nz;
473        }
474        pMesh->UnlockVertexBuffer();
475
476        //clean up:
477        delete [] adjacencyInfo;
478        pMesh->Release();
479
480        return tempNormals;
481}
482
483void Terrain::createTerrainPatches() {
484        float min_height = 1000; //needed for blending factors
485        float max_height = 0; //needed for blending factors
486
487        // check & set max height values for multitex
488        for(UINT i = 0; i < this->heightmap.size(); i++) {
489                if (heightmap[i] < min_height) {
490                        min_height = heightmap[i];
491                }
492                if (heightmap[i] > max_height) {
493                        max_height = heightmap[i];
494                }
495        }
496        min_height /= 255;
497        max_height /= 255;
498       
499        //calculate normals
500        normals = getNormals();
501       
502        // create weights array for progressive mesh so no gaps between the patches appear!
503        float *weights = new float[(this->patchSize+1)*(this->patchSize+1)];
504        memset(weights, 0, (this->patchSize+1)*(this->patchSize+1));
505
506        char temp[100];
507        sprintf(temp, "Number of terrain patches: %d", numberOfPatches);
508        this->myScene->manager->printToConsole(temp);
509
510        int currentPatch = 0;
511
512        for (int i = 0; i < (numVertsPerCol-1)/patchSize; i++) {
513                for (int j = 0; j < (numVertsPerRow-1)/patchSize; j++) {
514                        //calculate current patch index
515                        currentPatch = i*(numVertsPerCol-1)/patchSize + j;
516                       
517                        //generate Object3d for current patch and add it to the scene
518                        //Object3d *p = (Object3d *) this->myScene->createNode(this->myScene->NODE_OBJECT3D, *this->myScene->getRoot(), true);
519                        Object3d *p = (Object3d *) this->myScene->createNode(this->myScene->NODE_OBJECT3D, *this->myScene->getRoot(), false);
520                       
521                        //set bounding box to HUGE :)
522                        p->minAABBox.x = minAABBox.y = minAABBox.z = 9999999;
523                        p->maxAABBox.x = maxAABBox.y = maxAABBox.z = -9999999;
524
525                        SPTR<Renderer> renderer(new TerrainRenderer);
526                        renderer->setScene(*this->myScene);
527                        TerrainRenderer *temp = (TerrainRenderer*)renderer.get();
528                        temp->setEffect(this->TerrainEffect);
529                        this->myScene->connectNodeAndRenderer(*p, renderer);
530                       
531                        //set mesh position
532                        //p->setPosition(0.0f, 0.0f, 0.0f);
533                        p->setPosition(j * patchSize * cellSpacing, 0, i * patchSize * cellSpacing);
534
535                        //creating mesh pointer
536                        LPD3DXMESH * pMesh = p->getMesh();
537                       
538                        //generate mesh
539                        HRESULT hr = 0;
540                        hr = D3DXCreateMeshFVF((patchSize * patchSize *2),
541                                                        ((patchSize+1)*(patchSize+1)),
542                                                        D3DXMESH_MANAGED,
543                                                        Vertex::FVF_Flags,
544                                                        DXUTGetD3DDevice(),
545                                                        pMesh
546                        );
547                        if(hr != S_OK) {
548                                this->myScene->manager->printToConsole("error occured during mesh initialization!");
549                        }
550                       
551                        //vertices array:
552                        Vertex* pVertices;
553                        int count = 0;
554                       
555                        //lock vertex buffer
556                        (*pMesh)->LockVertexBuffer( 0, (void**)&pVertices );
557
558                        // fill the vertices:
559                        int StartIndex = i * patchSize * numVertsPerCol + j * patchSize;
560                        for (int k = 0; k <= patchSize; k++) {
561                                for(int l = 0; l <= patchSize; l++) {
562                                        int CurrentIndex = StartIndex + l;
563                                        // set the vertex data
564                                        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);
565                                       
566                                        // check bounding box:
567                                        if (pVertices[count].x < p->minAABBox.x)
568                                                p->minAABBox.x = pVertices[count].x;
569                                        if (pVertices[count].y < p->minAABBox.y)
570                                                p->minAABBox.y = pVertices[count].y;
571                                        if (pVertices[count].z < p->minAABBox.z)
572                                                p->minAABBox.z = pVertices[count].z;
573                                        if (pVertices[count].x > p->maxAABBox.x)
574                                                p->maxAABBox.x = pVertices[count].x;
575                                        if (pVertices[count].y > p->maxAABBox.y)
576                                                p->maxAABBox.y = pVertices[count].y;
577                                        if (pVertices[count].z > p->maxAABBox.z)
578                                                p->maxAABBox.z = pVertices[count].z;
579                                       
580                                        // set the weight
581                                        if (l == 0 || k == 0 || l == patchSize || k == patchSize) {
582                        weights[count] = 1.0f;
583                                        } else {
584                                                weights[count] = 0.0f;
585                                        }
586                                        count++;
587                                }
588                                StartIndex += numVertsPerRow;
589                        }
590
591                        //unlock vertex buffer
592                        (*pMesh)->UnlockVertexBuffer();
593                       
594                        // fill the indices:
595                        WORD* pIndices = NULL;
596                        DWORD* attributeBuffer = NULL; //to define the subsets
597                        int baseIndex = 0;
598                        int attrCount = 0;
599                        (*pMesh)->LockIndexBuffer( 0, (void**)&pIndices );
600                        (*pMesh)->LockAttributeBuffer(0, &attributeBuffer);
601                        (*pMesh)->LockVertexBuffer( 0, (void**)&pVertices );
602                        {
603                                for(int k = 0; k < patchSize; k++)
604                                {
605                                        for(int l = 0; l < patchSize; l++)
606                                        {
607                                                pIndices[baseIndex]     =   (WORD)((k+1) * (patchSize+1) + l);
608                                                pIndices[baseIndex + 1] =   (WORD)(k   * (patchSize+1) + l + 1);
609                                                pIndices[baseIndex + 2] =       (WORD)(k   * (patchSize+1) + l);
610
611                                                //if(pVertices[pIndices[baseIndex]].y == 0 && pVertices[pIndices[baseIndex + 1]].y == 0 && pVertices[pIndices[baseIndex + 2]].y == 0) {
612                                                //      attributeBuffer[attrCount++] = 1;
613                                                //} else {
614                                                        attributeBuffer[attrCount++] = 0;
615                                                //}
616
617                                                pIndices[baseIndex + 3] =       (WORD)((k+1) * (patchSize+1) + l + 1);
618                                                pIndices[baseIndex + 4] =   (WORD)(k   * (patchSize+1) + l + 1);
619                                                pIndices[baseIndex + 5] =       (WORD)((k+1) * (patchSize+1) + l);
620
621                                                //if(pVertices[pIndices[baseIndex + 3]].y == 0 && pVertices[pIndices[baseIndex + 4]].y == 0 && pVertices[pIndices[baseIndex + 5]].y == 0) {
622                                                //      attributeBuffer[attrCount++] = 1;
623                                                //} else {
624                                                        attributeBuffer[attrCount++] = 0;
625                                                //}
626
627                                                // next quad
628                                                baseIndex += 6;
629                                        }
630                                }
631                        }
632                        (*pMesh)->UnlockVertexBuffer();
633                        (*pMesh)->UnlockAttributeBuffer();
634                        (*pMesh)->UnlockIndexBuffer();
635                       
636                        // assign material array:
637                        p->Materials.push_back(standardMats[0]);
638                       
639                        // assign textures:
640                        for (UINT k = 0; k < this->Textures.size(); k++) {
641                                p->Textures.push_back(this->Textures[0]);
642                        }
643                       
644                        // assign colours for multitexturing:
645                        Vector nach_oben (0,1,0);
646                        (*pMesh)->LockVertexBuffer( 0, (void**)&pVertices );
647                        for (int k = 0; k < (patchSize+1); k++) {
648                                for (int l = 0; l < (patchSize+1); l++) {
649                                        int curPatch = k * (patchSize + 1) + l;
650
651                                        D3DXCOLOR tempColor;
652                                       
653                                        Vector vertnormal(pVertices[curPatch].nx, pVertices[curPatch].ny, pVertices[curPatch].nz);
654                                        tempColor.r = (pVertices[curPatch].y / 255 - min_height) * (1 / (max_height-min_height));
655                                        tempColor.b = 1 - tempColor.r;
656                                        tempColor.g = (nach_oben.dotProd(vertnormal));
657
658                                        //versuch das ganze zu verbessern:
659                                        if(tempColor.g < 0.9) {
660                        tempColor.g *= tempColor.g * tempColor.g;
661                                                tempColor.r *= tempColor.g;
662                                                tempColor.b *= tempColor.g;
663                                        } else {
664                                                tempColor.g = 0;
665                                        }
666                                       
667                                        pVertices[curPatch].color = D3DCOLOR_COLORVALUE(tempColor.r,1-tempColor.r-tempColor.b,tempColor.b,0);
668                                }
669                        }
670                        (*pMesh)->UnlockVertexBuffer();
671
672                        // model creation finished, set value to true
673                        p->setModelLoaded(true);
674
675                        //PhysicHeightfield Stuff
676                        p->generatePhysicMesh(p->COL_HEIGHTFIELD);
677                        p->setBehaveAs(p->KINEMATIC);
678                        p->setColDetGroup(UserContactReport::COLGROUP_TERRAIN);
679                        p->getActor()->setSolverIterationCount(2);
680                        p->getActor()->getShapes()[0]->setFlag(NX_SF_VISUALIZATION, false);
681
682                        // convert to progressive mesh
683                        // ich nehm das mal raus, zum zeit sparen beim laden
684                        //p->generateAndUsePMesh(weights);
685
686                        //adding patch to vector
687                        terrainPatches.push_back(p);
688                }
689        }
690        delete [] weights;
691        delete [] normals;
692}
Note: See TracBrowser for help on using the repository browser.