标签:
效果图如上:
步骤:略,构成顺序参考下图1、2。
图1 城墙构成顺序说明图:
图2 塔楼构成说明图:略
实现代码如下:
main.cpp
1 /********************************************************************** 2 3 Castle - using Display Lists 4 5 June, 12th, 2000 6 7 This tutorial was written by Philipp Crocoll 8 Contact: 9 philipp.crocoll@web.de 10 www.codecolony.de 11 12 Every comment would be appreciated. 13 14 If you want to use parts of any code of mine: 15 let me know and 16 use it! 17 ********************************************************************** 18 ESC: exit 19 20 CAMERA movement: 21 w : forwards 22 s : backwards 23 a : turn left 24 d : turn right 25 x : turn up 26 y : turn down 27 v : strafe right 28 c : strafe left 29 r : move up 30 f : move down 31 32 **********************************************************************/ 33 34 35 #include <GL\glut.h> //includes gl.h and glu.h 36 #include <math.h> //sine and cosine functions 37 #include "camera.h" 38 #include <windows.h> 39 #define PI 3.1415265359 40 41 static GLfloat MatSpec[] = {1.0,1.0,1.0,1.0}; 42 static GLfloat MatShininess[] = {45.0}; 43 static GLfloat LightPos[] = {-2.0,1.5,1.0,0.0}; 44 static GLfloat ModelAmb[] = {0.5,0.5,0.5,0.0}; 45 46 47 CCamera Camera; 48 49 GLint TowerListNum,WallsListNum; //Numbers of the display lists 50 GLint WallsList; 51 //Tower properties: 52 int NumOfEdges = 12; // 塔身弯曲的精细度 53 GLfloat LowerHeight =3.0; // 塔顶圆台的最小半径 54 GLfloat HigherHeight = 3.5; // 塔顶圆台的最大半径 55 GLfloat HR = 1.3; //Radius of the highest part // 塔顶的半径 56 57 //Wall properties: 58 GLfloat WallElementSize = 0.4; // 城墙的突出部分的长度 59 GLfloat WallHeight = 2.0; // 城墙的高度 60 61 // 画出更高的墙部分--突出的墙垣 62 void DrawHigherWallPart(int NumElements) 63 /*Draws a wall part like this: 64 ___ ___ ___ 65 | | | | | | 66 |___| |___| |___| 67 and so on 68 such an element is squareshaped and has the height/width WallElementSize*/ 69 { 70 glBegin(GL_QUADS); 71 for (int i = 0; i < NumElements; i++) 72 { 73 glNormal3f(0.0,0.0,-1.0); 74 glVertex3f(i*2.0 * WallElementSize, 0.0, 0.0); 75 glVertex3f(i*2.0 * WallElementSize, WallElementSize, 0.0); 76 glVertex3f((i*2.0+1.0) * WallElementSize, WallElementSize, 0.0); 77 glVertex3f((i*2.0+1.0) * WallElementSize, 0.0, 0.0); 78 79 } 80 81 glEnd(); 82 83 } 84 85 // 画出墙体的部分 86 void DrawWall(GLfloat Length) 87 { 88 glBegin(GL_QUADS); 89 glNormal3f(0.0,0.0,-1.0); // 设置法向量 90 glVertex3f(0.0,0.0,0.0); 91 glVertex3f(0.0,WallHeight,0.0); 92 glVertex3f(Length,WallHeight,0.0); 93 glVertex3f(Length,0.0,0.0); 94 glEnd(); 95 // 画出城墙的突出部分。 96 int i = (int)(Length / WallElementSize / 2); 97 if (i * WallElementSize > Length) i--; 98 glPushMatrix(); 99 glTranslatef(0.0,WallHeight,0.0); 100 DrawHigherWallPart(i); 101 glPopMatrix(); 102 } 103 104 105 106 void Init(void) //used to create the display lists 107 { 108 TowerListNum = glGenLists(1); // 会生成一组连续的空的显示列表 109 GLfloat x,z; 110 int i=0; 111 GLfloat NVectY; //y component for the NVects of the higher part // y分量的NVects更高的一部分 112 113 glNewList(TowerListNum, GL_COMPILE); // 用于创建和替换一个显示列表函数原型 114 glBegin(GL_QUADS); // 四边形 115 //Create the lower part of the tower: // 创建塔身的圆柱形部分 116 for (i = 0; i < NumOfEdges-1; i++) 117 { 118 x = cos((float)i/(float)NumOfEdges * PI * 2.0); 119 z = sin((float)i/(float)NumOfEdges * PI * 2.0); 120 glNormal3f(x,0.0,z); 121 glVertex3f(x,LowerHeight,z); 122 //same x,z and NVect: 123 glVertex3f(x,0.0,z); 124 125 x = cos((float)(i+1)/(float)NumOfEdges * PI * 2.0); 126 z = sin((float)(i+1)/(float)NumOfEdges * PI * 2.0); 127 glNormal3f(x,0.0,z); 128 glVertex3f(x,0.0,z); 129 //same x,z and NVect: 130 glVertex3f(x,LowerHeight,z); 131 } 132 // 塔身侧面的连接处 133 x = cos((float)i/(float)NumOfEdges * PI * 2.0); 134 z = sin((float)i/(float)NumOfEdges * PI * 2.0); 135 glNormal3f(x,0.0,z); 136 glVertex3f(x,LowerHeight,z); 137 //same x,z and NVect: 138 glVertex3f(x,0.0,z); 139 x = cos(1.0/(float)NumOfEdges * PI * 2.0); 140 z = sin(1.0/(float)NumOfEdges * PI * 2.0); 141 glNormal3f(x,0.0,z); 142 glVertex3f(x,0.0,z); 143 //same x,z and NVect: 144 glVertex3f(x,LowerHeight,z); 145 146 147 //Create the higher part: // 创建塔顶的倒梯形部分。 148 149 //The y component is the same for all NVects, so we can calculate it here: 150 // 对所有NVects y分量是一样的,所以在这里我们可以计算: 151 NVectY = (HR-1.0) / (LowerHeight - HigherHeight) * (HR-1.0); // = (1.3-1.0)/(3.5-3.0)*(1.3-1.0) 152 153 for (i = 0; i < NumOfEdges-1; i++) 154 { 155 x = cos((float)i/(float)NumOfEdges * PI * 2.0); 156 z = sin((float)i/(float)NumOfEdges * PI * 2.0); 157 glNormal3f(x,NVectY,z); 158 glVertex3f(x*HR,HigherHeight,z*HR); 159 //same x,z and NVect: 160 glVertex3f(x,LowerHeight,z); 161 162 x = cos((float)(i+1)/(float)NumOfEdges * PI * 2.0); 163 z = sin((float)(i+1)/(float)NumOfEdges * PI * 2.0); 164 glNormal3f(x,NVectY,z); 165 glVertex3f(x,LowerHeight,z); 166 //same x,z and NVect: 167 glVertex3f(x*HR,HigherHeight,z*HR); 168 } 169 // 塔顶侧面的连接处 170 x = cos((float)i/(float)NumOfEdges * PI * 2.0); 171 z = sin((float)i/(float)NumOfEdges * PI * 2.0); 172 glNormal3f(x,NVectY,z); 173 glVertex3f(x*HR,HigherHeight,z*HR); 174 //same x,z and NVect: 175 glVertex3f(x,LowerHeight,z); 176 x = cos(1.0/(float)NumOfEdges * PI * 2.0); 177 z = sin(1.0/(float)NumOfEdges * PI * 2.0); 178 glNormal3f(x,NVectY,z); 179 glVertex3f(x,LowerHeight,z); 180 //same x,z and NVect: 181 glVertex3f(x*HR,HigherHeight,z*HR); 182 183 glEnd(); 184 glEndList(); 185 186 //////////////////////////////////////////////////////////// 187 188 //WallList 189 190 //////////////////////////////////////////////////////////// 191 192 WallsListNum = glGenLists(1); // 创建显示列表1个 193 glNewList(WallsListNum, GL_COMPILE); 194 DrawWall(10.0); // 绘制墙面=1 195 glPushMatrix(); // 压栈1 196 197 glTranslatef(10.0,0.0,0.0); // 移动到点2 198 199 glPushMatrix(); // 压栈2 200 glRotatef(270.0,0.0,1.0,0.0); 201 DrawWall(10.0); // 绘制墙面=2 202 glPopMatrix(); // 出栈2 203 204 glTranslatef(0.0,0.0,10.0); // 向前10个单位 // 移动到点3 205 206 glPushMatrix(); // 压栈3 207 glRotatef(180.0,0.0,1.0,0.0); 208 DrawWall(5.0); // 绘制墙面=3 209 glRotatef(90.0,0.0,1.0,0.0); 210 glTranslatef(0.0,0.0,5.0); 211 DrawWall(5.0); // 绘制墙面=4 212 glPopMatrix();// 出栈3 213 214 glTranslatef(-5.0,0.0,5.0); // 移动到点4 215 216 glPushMatrix(); // 压栈4 217 glRotatef(180.0,0.0,1.0,0.0); 218 DrawWall(5.0); // 绘制墙面=5 219 glPopMatrix(); // 出栈4 220 221 //Last and longest piece: 222 glPushMatrix(); // 压栈5 223 glRotatef(90.0,0.0,1.0,0.0); 224 glTranslatef(0.0,0.0,-5.0); // // 移动到点5 225 DrawWall(6.0); // // 绘制墙面=7 226 //the "door" 227 glTranslatef(6.0,0.0,0.0); 228 // 绘制墙面=8 229 glBegin(GL_QUADS); 230 glNormal3f(0.0,0.0,-1.0); 231 glVertex3f(0.0,WallHeight / 2.0,0.0); 232 glVertex3f(0.0,WallHeight,0.0); 233 glVertex3f(3.0,WallHeight,0.0); // 门的宽度=3.0 234 glVertex3f(3.0,WallHeight / 2.0,0.0); 235 glEnd(); 236 237 i = (int)(3.0 / WallElementSize / 2); 238 if (i * WallElementSize > 3.0) i--; 239 240 glPushMatrix();// 压栈6 241 glTranslatef(0.0,WallHeight,0.0); 242 DrawHigherWallPart(i); // 绘制城墙的顶部 243 glPopMatrix(); // 出栈6 244 245 glTranslatef(3.0,0.0,0.0); 246 DrawWall(6.0);// 绘制墙面=9 247 glPopMatrix(); // 出栈5 248 249 glPopMatrix(); // 出栈1 250 251 glEndList(); 252 } 253 254 void Display(void) 255 { 256 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 257 glLoadIdentity(); 258 Camera.Render(); 259 glLightfv(GL_LIGHT0,GL_POSITION,LightPos); 260 glTranslatef(-7.0,2.0,-7.0); 261 glRotatef(90.0,0.0,1.0,0.0); 262 glBegin(GL_POLYGON); 263 glNormal3f(0.0,1.0,0.0); // 法向量= y轴 264 glVertex3f(0.0,0.0,0.0); // 编号点=1 265 glVertex3f(10.0,0.0,0.0); // 编号点=2 266 glVertex3f(10.0,0.0,10.0); // 编号点=3 267 glVertex3f(5.0,0.0,15.0); // 编号点=4 268 glVertex3f(0.0,0.0,15.0); // 编号点=5 269 glVertex3f(0.0,0.0,0.0);// 编号点=1 270 glEnd(); 271 272 273 //Turn two sided lighting on for the walls 274 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE); 275 276 glCallList(WallsListNum); // 调用城墙的显示列表 277 278 //Disable it again for the towers: // 关闭它,塔楼不使用 279 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE); 280 281 282 glCallList(TowerListNum); // 目前点=1 283 284 glTranslatef(10.0,0.0,0.0) ; // 移动到点=2 285 glCallList(TowerListNum); 286 287 glTranslatef(0.0,0.0,10.0); // 移动到点=3 288 glCallList(TowerListNum); 289 290 glTranslatef(-5.0,0.0,5.0); // 移动到点=4 291 glCallList(TowerListNum); 292 293 glTranslatef(-5.0,0.0,0.0); // 移动到点=5 294 glCallList(TowerListNum); 295 296 glFlush(); //Finish rendering 297 glutSwapBuffers(); //Swap the buffers ->make the result of rendering visible 298 } 299 void Reshape(int x, int y) 300 { 301 if (y == 0 || x == 0) return; //Nothing is visible then, so return 302 //Set a new projection matrix 303 glMatrixMode(GL_PROJECTION); // 投影模式 304 glLoadIdentity(); 305 //Angle of view:40 degrees 306 //Near clipping plane distance: 0.5 307 //Far clipping plane distance: 20.0 308 gluPerspective(40.0,(GLdouble)x/(GLdouble)y,1.0,200.0); // 投影范围。 309 glMatrixMode(GL_MODELVIEW); // 视景模式。 310 glViewport(0,0,x,y); 311 } 312 void KeyDown(unsigned char key, int x, int y) 313 { 314 switch(key) 315 { 316 case 27: //ESC 317 exit(0); 318 break; 319 case ‘a‘: 320 Camera.RotateY(5.0); 321 Display(); 322 break; 323 case ‘d‘: 324 Camera.RotateY(-5.0); 325 Display(); 326 break; 327 case ‘w‘: 328 Camera.MoveForwards( -0.3 ) ; 329 Display(); 330 break; 331 case ‘s‘: 332 Camera.MoveForwards( 0.3 ) ; 333 Display(); 334 break; 335 case ‘x‘: 336 Camera.RotateX(5.0); 337 Display(); 338 break; 339 case ‘y‘: 340 Camera.RotateX(-5.0); 341 Display(); 342 break; 343 case ‘c‘: 344 Camera.StrafeRight(-0.3); 345 Display(); 346 break; 347 case ‘v‘: 348 Camera.StrafeRight(0.3); 349 Display(); 350 break; 351 case ‘f‘: 352 Camera.Move(F3dVector(0.0,-0.3,0.0)); 353 Display(); 354 break; 355 case ‘r‘: 356 Camera.Move(F3dVector(0.0,0.3,0.0)); 357 Display(); 358 break; 359 360 361 } 362 } 363 364 int main(int argc, char **argv) 365 { 366 glutInit(&argc, argv); 367 glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH); 368 glutInitWindowSize(600,600); 369 glutCreateWindow("Castle"); 370 glEnable(GL_DEPTH_TEST); // 深度测试 371 glPolygonMode(GL_FRONT_AND_BACK,GL_FILL); // 设置正反面为线形模式 372 glClearColor(0.0,0.0,0.0,0.0); // 黑色 373 glutDisplayFunc(Display); 374 glutReshapeFunc(Reshape); 375 glutKeyboardFunc(KeyDown); 376 Camera.Move(F3dVector(0.0,5.0,20.0)); // 摄像机的位置。 377 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, MatSpec); // 材质属性中的镜面反射光 378 glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, MatShininess); // //材质属性的镜面反射指数 379 glEnable(GL_LIGHTING); 380 glEnable(GL_LIGHT0); 381 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ModelAmb); // 设置光照模式(全局环境光) 382 Init(); 383 glutMainLoop(); 384 return 0; 385 }
原始代码来源:http://www.codecolony.de/
标签:
原文地址:http://www.cnblogs.com/yuwl26/p/4245659.html