OpenGL地形建模

使用了OpenGL 3.0以及freeglut进行的C++编程,地形数据读取于一个DEM模型

地形效果如下,使用了基本的三角形进行绘图,外加一点简单的光照。贴图没有搞上,正在研究

第一次用OpenGL编程,还有很多地方需要提高,源码见后

  1 #include <iostream>
  2 #include <fstream>
  3 #include <string>
  4 #include <sstream>
  5 #include <soil.h>
  6 
  7 using namespace std;
  8 
  9 #include <gl/freeglut.h>
 10 //#include <gl/glaux.h>
 11 
 12 #pragma comment(lib, "soil.lib")
 13 
 14 #define C 2701
 15 #define R 1801
 16 #define CELLSIZE 50
 17 
 18 #define W 256
 19 #define H 256
 20 
 21 //=========================================3-1 P.80
 22 
 23 static GLfloat spin = 0;
 24 static GLfloat spin_x = 0;
 25 static GLfloat spin_y = 0;
 26 static GLfloat old_x = 0;
 27 static GLfloat old_y = 0;
 28 
 29 static GLfloat camerap[3] = {0, 1000, 0};
 30 static GLfloat cameras[3] = {5000, 0, 0};
 31 
 32 static int datas [R][C];
 33 static float vectors [(R - 1) * 2][C - 1][3];//The [3] in the last is for x, y and z
 34 static float normals [R][C][3];
 35 
 36 static GLuint texName;
 37 //static GLubyte grassImage [H][W][4];
 38 
 39 void init (void)
 40 {
 41     //Light
 42     GLfloat mat_specular[] = {1, 1, 1, 0};
 43     GLfloat mat_shininess[] = {1000};
 44     GLfloat light_position[] = {5000, 5000, 5000, 0};
 45     GLfloat a_light[] = {1.0f, 1.0f, 1.0f, 1};
 46     GLfloat lmodel_ambient[] = {0.8, 0.8, 0.8, 1};
 47 
 48     glClearColor(1, 1, 1, 0);
 49     glShadeModel(GL_SMOOTH);//----------------
 50     glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess);
 51     glLightfv(GL_LIGHT0, GL_POSITION, light_position);
 52     glLightfv(GL_LIGHT0, GL_DIFFUSE, a_light);
 53     glLightfv(GL_LIGHT0, GL_SPECULAR, a_light);
 54     glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient);
 55 
 56     glEnable(GL_LIGHTING);
 57     glEnable(GL_LIGHT0);
 58     glEnable(GL_DEPTH_TEST);
 59     glShadeModel(GL_FLAT);
 60     
 61     //Load terrain data
 62     char str[C * 4 + 1];
 63     string sdatas;
 64     ifstream terrainFile(".\\res\\dem.asc");
 65     if(!terrainFile)
 66     {
 67         cerr<<"File is not opened."<<endl;
 68     }
 69     cout<<"Terrain file is opened."<<endl<<endl;
 70     for (int i = 1; i <= 13; i++)
 71     {
 72         terrainFile.getline(str, C * 4 + 1);
 73         cout<<str<<endl;
 74     }
 75     cout<<endl<<"Loading terrain data...";
 76     for (int i = 0; i < R; i++)
 77     {
 78         terrainFile.getline(str, C * 4 + 1);
 79         sdatas = str;
 80         istringstream datastream(sdatas);
 81         for (int j = 0; j < C; j++)
 82         {
 83             datastream>>datas[i][j];
 84             //cout<<datas[i][j]<<" ";//just for testing
 85         }
 86     }
 87     cout<<endl<<"Terrain data is loaded."<<endl;
 88     
 89     cout<<endl<<"Setting triangle normal vectors...";
 90     int uy, vy;
 91     for (int i = 0; i < (R - 1) * 2; i++)
 92     {
 93         if (i % 2 == 0)
 94         {
 95             for (int j = 0; j < C - 1; j++)
 96             {
 97                 uy = datas[i / 2][j] - datas[i / 2][j + 1];
 98                 vy = datas[(i / 2) + 1][j] - datas[i / 2][j];
 99                 vectors[i][j][0] = uy;//
100                 vectors[i][j][1] = 1;//
101                 vectors[i][j][2] = -vy;//
102             }
103         }
104         else
105         {
106             for (int j = 0; j < C - 1; j++)
107             {
108                 uy = datas[(i / 2) + 1][j + 1] - datas[(i / 2) + 1][j];
109                 vy = datas[i / 2][j + 1] - datas[(i / 2) + 1][j + 1];
110                 vectors[i][j][0] = -uy;//
111                 vectors[i][j][1] = 1;//
112                 vectors[i][j][2] = vy;//
113             }
114         }
115     }
116     cout<<endl<<"Triangle normal vectors set."<<endl;
117 
118     cout<<endl<<"Setting vertex normal vectors...";
119 
120     //4 vertexs of the matrix, which need 1 or 2 triangles to define the normal
121     //Left top
122     normals[0][0][0] = vectors[0][0][0];
123     normals[0][0][1] = vectors[0][0][1];
124     normals[0][0][2] = vectors[0][0][2];
125     //Right bottom
126     normals[R - 1][C - 1][0] = vectors[(R - 1) * 2 - 1][C - 2][0];
127     normals[R - 1][C - 1][1] = vectors[(R - 1) * 2 - 1][C - 2][1];
128     normals[R - 1][C - 1][2] = vectors[(R - 1) * 2 - 1][C - 2][2];
129     //Left bottom
130     normals[R - 1][0][0] = (vectors[(R - 1) * 2 - 2][0][0] + vectors[(R - 1) * 2 - 1][0][0]) / 2;
131     normals[R - 1][0][1] = (vectors[(R - 1) * 2 - 2][0][1] + vectors[(R - 1) * 2 - 1][0][1]) / 2;
132     normals[R - 1][0][2] = (vectors[(R - 1) * 2 - 2][0][2] + vectors[(R - 1) * 2 - 1][0][2]) / 2;
133     //Right top
134     normals[0][0][0] = (vectors[0][C - 2][0] + vectors[1][C - 2][0]) / 2;
135     normals[0][0][0] = (vectors[1][C - 2][0] + vectors[1][C - 2][1]) / 2;
136     normals[0][0][0] = (vectors[2][C - 2][0] + vectors[1][C - 2][2]) / 2;
137 
138     //4 edges of the matrix, which need 4 triangles to define the normal
139     //Top
140     for (int c = 1; c < C - 1; c++)
141     {
142         normals[0][c][0] = (vectors[0][c - 1][0]
143                             + vectors[1][c - 1][0] 
144                             + vectors[0][c][0] 
145                             + vectors[1][c][0]) / 4;
146         normals[0][c][1] = (vectors[0][c - 1][1] 
147                             + vectors[1][c - 1][1] 
148                             + vectors[0][c][1] 
149                             + vectors[1][c][1]) / 4;
150         normals[0][c][2] = (vectors[0][c - 1][2] 
151                             + vectors[1][c - 1][2] 
152                             + vectors[0][c][2] 
153                             + vectors[1][c][2]) / 4;
154     }
155     //Bottom
156     for (int c = 1; c < C - 1; c++)
157     {
158         normals[R - 1][c][0] = (vectors[(R - 1) * 2 - 1][c - 1][0] 
159                                 + vectors[(R - 1) * 2 - 2][c - 1][0] 
160                                 + vectors[(R - 1) * 2 - 1][c][0]
161                                 + vectors[(R - 1) * 2 - 2][c][0]) / 4;
162         normals[R - 1][c][1] = (vectors[(R - 1) * 2 - 1][c - 1][1] 
163                                 + vectors[(R - 1) * 2 - 2][c - 1][1] 
164                                 + vectors[(R - 1) * 2 - 1][c][1] 
165                                 + vectors[(R - 1) * 2 - 2][c][1]) / 4;
166         normals[R - 1][c][2] = (vectors[(R - 1) * 2 - 1][c - 1][2] 
167                                 + vectors[(R - 1) * 2 - 2][c - 1][2] 
168                                 + vectors[(R - 1) * 2 - 1][c][2] 
169                                 + vectors[(R - 1) * 2 - 2][c][2]) / 4;
170     }
171     //Left
172     for (int r = 1; r < R - 1; r++)
173     {
174         normals[r][0][0] = (vectors[r * 2 - 2][0][0]
175                             + vectors[r * 2 - 1][0][0]
176                             + vectors[r * 2][0][0]
177                             + vectors[r * 2 + 1][0][0]) / 4;
178         normals[r][0][1] = (vectors[r * 2 - 2][0][1]
179                             + vectors[r * 2 - 1][0][1]
180                             + vectors[r * 2][0][1]
181                             + vectors[r * 2 + 1][0][1]) / 4;
182         normals[r][0][2] = (vectors[r * 2 - 2][0][2]
183                             + vectors[r * 2 - 1][0][2]
184                             + vectors[r * 2][0][2]
185                             + vectors[r * 2 + 1][0][2]) / 4;
186     }
187     //Right
188     for (int r = 1; r < R - 1; r++)
189     {
190         normals[r][0][0] = (vectors[r * 2 - 2][C - 2][0]
191                             + vectors[r * 2 - 1][C - 2][0]
192                             + vectors[r * 2][C - 2][0]
193                             + vectors[r * 2 + 1][C - 2][0]) / 4;
194         normals[r][0][1] = (vectors[r * 2 - 2][C - 2][1]
195                             + vectors[r * 2 - 1][C - 2][1]
196                             + vectors[r * 2][C - 2][1]
197                             + vectors[r * 2 + 1][C - 2][1]) / 4;
198         normals[r][0][2] = (vectors[r * 2 - 2][C - 2][2]
199                             + vectors[r * 2 - 1][C - 2][2]
200                             + vectors[r * 2][C - 2][2]
201                             + vectors[r * 2 + 1][C - 2][2]) / 4;
202     }
203 
204     //The rest of the martix, 6 triangles are needed for each
205     for (int r = 1; r < R - 1; r++)
206     {
207         for (int c = 1; c < C - 1; c++)
208         {
209             normals[r][c][0] = (vectors[r * 2][c][0]
210                                 + vectors[r * 2 - 1][c - 1][0]
211                                 + vectors[r * 2 - 1][c][0]
212                                 + vectors[r * 2][c - 1][0]
213                                 + vectors[r * 2][c][0]
214                                 + vectors[r * 2 + 1][c - 1][0]) / 6;
215             normals[r][c][1] = (vectors[r * 2][c][1]
216                                 + vectors[r * 2 - 1][c - 1][1]
217                                 + vectors[r * 2 - 1][c][1]
218                                 + vectors[r * 2][c - 1][1]
219                                 + vectors[r * 2][c][1]
220                                 + vectors[r * 2 + 1][c - 1][1]) / 6;
221             normals[r][c][2] = (vectors[r * 2][c][2]
222                                 + vectors[r * 2 - 1][c - 1][2]
223                                 + vectors[r * 2 - 1][c][2]
224                                 + vectors[r * 2][c - 1][2]
225                                 + vectors[r * 2][c][2]
226                                 + vectors[r * 2 + 1][c - 1][2]) / 6;
227         }
228     }
229     cout<<endl<<"Vertex normal vectors set."<<endl;
230 
231     //Enable normalize vector
232     glEnable(GL_NORMALIZE);
233 
234     //Load Texture
235     int width, height;
236     unsigned char* image = SOIL_load_image(".\\res\\terrain.bmp", &width, &height, 0, SOIL_LOAD_RGBA);
237     glGenTextures(1, &texName);
238     glBindTexture(GL_TEXTURE_2D, texName);
239     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
240     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
241     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
242     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
243     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, image);
244     glEnable(GL_TEXTURE_2D);
245 }
246 
247 /*
248 void spindisplay (void)
249 {
250     
251     glutPostRedisplay();
252 }
253 */
254 
255 void processMouse(int button, int state, int x, int y)  
256 {  
257     if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN)  
258     {  
259         old_x = x; 
260         old_y = y;  
261     }
262 }  
263 
264 void onMouseMove(int x, int y)  
265 {  
266     spin_x += y - old_y;
267     spin_y += x - old_x;
268     spin = sqrt(spin_x*spin_x + spin_y*spin_y);
269     if (spin > 360)
270     {
271         spin -= 360;
272     }
273 
274     glutPostRedisplay();  
275 
276     old_x = x;  
277     old_y = y;  
278 }  
279 
280 void onKeyboardType(unsigned char key, int x, int y)
281 {
282     if (key == 'r' || key == 'R')
283     {
284         spin_x = 10;
285         spin_y = 0;
286         spin = 0;
287         glutPostRedisplay();  
288     }
289 
290     if (key == 'w' || key == 'W')
291     {
292         camerap[0] += 1000;
293         glutPostRedisplay();  
294     }
295     if (key == 's' || key == 'S')
296     {
297         camerap[0] -= 1000;
298         glutPostRedisplay();  
299     }
300     if (key == 'a' || key == 'A')
301     {
302         camerap[2] -= 1000;
303         glutPostRedisplay();  
304     }
305     if (key == 'd' || key == 'D')
306     {
307         camerap[2] += 1000;
308         glutPostRedisplay();  
309     }
310 }
311 
312 void display (void)
313 {
314     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
315     glColor3f(1, 0.25, 0.25);
316     glLoadIdentity();
317 
318     //Moving camera
319     gluLookAt(camerap[0], camerap[1], camerap[2], 5000 + camerap[0], 0 + camerap[1], 0 + camerap[2], 0, 1, 0);
320     glScalef(1, 1, 1);
321     glRotatef(spin, spin_x, spin_y, 0);
322 
323     //Drawing loop
324     for (int r = 0; r < R - 1; r++)
325     {
326         glBegin(GL_TRIANGLE_STRIP);
327             for (int c = 0; c < C - 1; c++)
328             {
329                 //Normal Vector
330                 glNormal3f(normals[r][c][0], normals[r][c][1], normals[r][c][2]);
331                 //glTexCoord2d(c/C, 1 - r / R);
332                 glVertex3f(c * 50,datas[r][c],r * 50);
333                 
334                 //Normal Vector
335                 glNormal3f(normals[r + 1][c][0], normals[r][c][1], normals[r][c][2]);
336                 //glTexCoord2d(c/C, 1 - (r + 1) / R);
337                 glVertex3f(c * 50,datas[r + 1][c],r * 50 + 50);
338             }
339         glEnd();
340     }
341     glFlush();
342 }
343 
344 void reshape(int w, int h)
345 {
346     glViewport(0, 0, (GLsizei)w, (GLsizei)h);
347     glMatrixMode(GL_PROJECTION);
348     glLoadIdentity();
349     //glFrustum(-1, 1, -1, 1, 1.5, 20);
350     gluPerspective(60, 1, 1, 99999);
351     glMatrixMode(GL_MODELVIEW);
352 }
353 
354 int main (int argc, char** argv)
355 {
356     glutInit(&argc,argv);
357     glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH);
358     glutInitWindowSize(1280, 720);
359     glutInitWindowPosition(100, 100);
360     glutCreateWindow(argv[0]);
361     init();
362     glutDisplayFunc(display);
363     //glutIdleFunc(spindisplay);
364     glutReshapeFunc(reshape);
365     glutMotionFunc(onMouseMove);
366     glutMouseFunc(processMouse);
367     glutKeyboardFunc(onKeyboardType);
368     glutMainLoop();
369     return 0;
370 }
原文地址:https://www.cnblogs.com/yuki8819/p/5245965.html