Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/orxonox/branches/nico/src/importer/heightMapTerrain.cc @ 3527

Last change on this file since 3527 was 3392, checked in by bensch, 20 years ago

orxonox/branches/nico: heightmap now able to readin with SDL-image (if found)

File size: 6.7 KB
Line 
1/*
2 *  ldrawparser.cpp
3 *  legotown3d
4 *
5 *  Created by Nico Bernold on 08.01.05.
6 *  Copyright 2005 __MyCompanyName__. All rights reserved.
7 *
8 */
9
10#include "heightMapTerrain.h"
11#include "vector.h"
12#ifdef HAVE_SDL_SDL_IMAGE_H
13#include <SDL/SDL_image.h>
14#endif /* HAVE_SDL_SDL_IMAGE_H */
15
16HeightMapTerrain::HeightMapTerrain()
17{       
18}
19
20HeightMapTerrain::~HeightMapTerrain()
21{
22}
23
24bool HeightMapTerrain::loadBitmap(char* fileName)
25{
26#ifdef HAVE_SDL_SDL_IMAGE_H
27  cout << "Using SDL-image for reading in the File " << fileName <<endl;
28  return this->bitmap = IMG_Load(fileName);
29#else
30  return this->bitmap = SDL_LoadBMP(fileName); 
31#endif /* HAVE_SDL_SDL_IMAGE_H */
32}
33
34bool HeightMapTerrain::createDisplayLists(int width, int height, int levelOfDetail)
35{
36        if (bitmap == NULL) return false;
37       
38        cout << "bitmap-dimensions:             " << bitmap->w << " x " << bitmap->h << endl;
39        cout << "bitmap-pitch:                  " << bitmap->pitch << endl;
40        cout << "bitmap->format->BytesPerPixel: " << (int)bitmap->format->BytesPerPixel << endl;
41        cout << "bitmap->format->BitsPerPixel:  " << (int)bitmap->format->BitsPerPixel << endl;
42         
43        if (bitmap->w % width != 0) return false;
44        if (bitmap->h % height != 0) return false;
45       
46        if (levelOfDetail < 1 || levelOfDetail > 10) return false;
47       
48        int howManyListsWide = bitmap->w / width;
49        int howManyListsHigh = bitmap->h / height;
50       
51        // calculate how many displayLists we'll create
52        displayListCount = howManyListsWide * howManyListsHigh; 
53
54        cout << "lists-information: " << howManyListsWide << " * " << howManyListsHigh << " = " << displayListCount << " display lists." << endl;
55       
56        displayListStart = glGenLists(displayListCount);
57        if (displayListStart == 0)
58        {
59                cout << "could not generate " << displayListCount << " display lists. exiting. " << endl;
60                return false;
61        }
62       
63        cout << displayListCount << " display lists generated. starting at: " << displayListStart << endl;
64
65
66        int i,j;
67       
68        for (i=0; i<howManyListsHigh; i++)
69        {
70                for (j=0; j<howManyListsWide; j++)
71                {
72                        if (readIntoList(j*width,i*height,width,height,levelOfDetail,i*howManyListsHigh + j) == false)
73                        {
74                                cout << "error while generating display lists. exiting. " << endl;
75                                return false;
76                        }
77
78                }
79        }
80       
81        return true;
82}
83
84bool HeightMapTerrain::readIntoList(int left, int top, int width, int height, int levelOfDetail, GLuint displayListNr)
85{
86        cout << "creating list Nr " << displayListNr << endl;
87        cout << "left, top, width, height: " << left << ", " << top << ", " << width << ", " << height << endl; 
88       
89        // y is the height value in OpenGL convention
90        int x,y,z;
91        GLfloat col;
92
93        // used for normal calculations
94        Vector O; // origin: the vertex where i'm standing
95        Vector N,E,S,W,NE,SE,SW,NW; // vectors pointing to north, east, ...
96
97        bool eightTriangles = false;
98       
99       
100        // contains a normal vector for every vertex
101        normals = new Vector[width*height];
102
103        // precalculate all vertex normals for later use in display list generation
104        // many superflous calculations i know...
105        for (z=top; z<top+height; z++)
106        {
107                for (x=left; x<left+width; x++)
108                {
109                        O = Vector(x,getHeightValue(x,z),z);
110
111                        N = Vector(x,getHeightValue(x,z-1),z-1) - O;
112                        E = Vector(x+1,getHeightValue(x+1,z),z) - O;
113                        S = Vector(x,getHeightValue(x,z+1),z+1) - O;
114                        W = Vector(x-1,getHeightValue(x-1,z),z) - O;
115
116                        if (eightTriangles == false)
117                                // calculate the average normal vector by adding up all 4 adjacent triangle normal vectors
118                                normals[(z-top) * height + (x-left)] = N.cross(W) + W.cross(S) + S.cross(E);
119
120                        else
121                        {
122                                NE = Vector(x+1,getHeightValue(x+1,z-1),z-1) - O;
123                                SE = Vector(x+1,getHeightValue(x+1,z+1),z+1) - O;
124                                SW = Vector(x-1,getHeightValue(x-1,z+1),z+1) - O;
125                                NW = Vector(x-1,getHeightValue(x-1,z-1),z-1) - O;
126                                // calculate the average normal vector by adding up all 8 adjacent triangle normal vectors
127                                normals[(z-top) * height + (x-left)] = N.cross(NW) + NW.cross(W) + W.cross(SW) + SW.cross(S) + S.cross(SE) + SE.cross(E) + E.cross(NE) + NE.cross(N);
128                        }
129
130                        // every second vertex is the edge of eightTriangles (the others have only four triangles)
131                        eightTriangles = !eightTriangles;
132                }
133        }
134       
135        cout << "normals precalculated for list " << displayListNr << endl;
136       
137        glNewList(displayListStart + displayListNr,GL_COMPILE);
138        {
139                glBegin(GL_TRIANGLES);
140                {
141                        // don't go through last col and row, because they are already done by second last col&row
142                        for (z = top; z < (top + height) - 1; z++)
143                        {
144                                for (x = left; x < (left + width) - 1; x++)
145                                {
146                                        // draw 2 triangles per (x,z) pair
147                                       
148                                        if (eightTriangles)
149                                        {
150                                                call_glNormal_and_glVertex(x,z,top,left,height);
151                                                call_glNormal_and_glVertex(x,z+1,top,left,height);
152                                                call_glNormal_and_glVertex(x+1,z,top,left,height);
153                                       
154                                                call_glNormal_and_glVertex(x+1,z,top,left,height);
155                                                call_glNormal_and_glVertex(x,z+1,top,left,height);
156                                                call_glNormal_and_glVertex(x+1,z+1,top,left,height);
157                                        }
158                                       
159                                        else
160                                        {
161                                                call_glNormal_and_glVertex(x,z,top,left,height);
162                                                call_glNormal_and_glVertex(x,z+1,top,left,height);
163                                                call_glNormal_and_glVertex(x+1,z+1,top,left,height);
164                                               
165                                                call_glNormal_and_glVertex(x+1,z,top,left,height);
166                                                call_glNormal_and_glVertex(x,z,top,left,height);
167                                                call_glNormal_and_glVertex(x+1,z+1,top,left,height);
168                                        }
169                                       
170                                       
171                                        // use the same trick to change the triangles everytime. once |/| and once |\|
172                                        eightTriangles = !eightTriangles;
173
174                                }
175                        }
176                }
177                glEnd();
178
179        }
180        glEndList();
181
182       
183        delete[] normals;
184       
185        return true;
186}
187
188
189void HeightMapTerrain::call_glNormal_and_glVertex(int x,int z,int top,int left,int height)
190{
191/*
192        GLfloat color[4];           // color parameter for glMaterial
193       
194        int heightVal = getHeightValue(x,z);
195
196        color[0] = 1.0 / 256.0 * heightVal;
197        color[1] = 1.0 / 256.0 * heightVal;
198        color[2] = 1.0 / 256.0 * heightVal;
199        color[3] = 1;  // alpha channel (1 = solid)
200
201        glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, color);
202*/
203        glNormal3f(normals[(z-top) * height + (x-left)].x,normals[(z-top) * height + (x-left)].y,normals[(z-top) * height + (x-left)].z);
204        glVertex3i(x,getHeightValue(x,z),z);
205}
206
207
208GLint HeightMapTerrain::getHeightValue(int x, int z)
209{
210        if (bitmap == NULL) return 0;
211
212        // catch out of image access
213        int X = x % bitmap->w;
214        int Z = z % bitmap->h;
215       
216        /*
217        if (X != x) cout << "x lies outside of image (" << x << "," << z << ")" << endl;
218        if (Z != z) cout << "z lies outside of image (" << x << "," << z << ")" << endl;
219        */
220       
221        // if x or z exeed the image size, return 0 as height value
222        if (X != x || Z != z) return 0;
223       
224       
225        Uint8 index;
226        SDL_Color color;
227       
228        SDL_LockSurface(bitmap);
229
230        index = *((Uint8*)bitmap->pixels + Z * bitmap->pitch + X * bitmap->format->BytesPerPixel);
231        color = bitmap->format->palette->colors[index];
232
233        SDL_UnlockSurface(bitmap);
234       
235        // return the red component, because in a grayscale pic, r,g and b are all the same value
236        return (GLint)color.r;
237}
Note: See TracBrowser for help on using the repository browser.