使用了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 }