首页 > 代码库 > openGL+VS2010的例程--城堡模型注释版(三维)

openGL+VS2010的例程--城堡模型注释版(三维)

技术分享

效果图如上:

步骤:略,构成顺序参考下图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 lists107 {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     //WallList189 190     ////////////////////////////////////////////////////////////191 192     WallsListNum = glGenLists(1); // 创建显示列表1个193     glNewList(WallsListNum, GL_COMPILE);194     DrawWall(10.0); // 绘制墙面=1195     glPushMatrix(); // 压栈1196 197     glTranslatef(10.0,0.0,0.0); // 移动到点2198 199     glPushMatrix(); // 压栈2200         glRotatef(270.0,0.0,1.0,0.0);201         DrawWall(10.0); // 绘制墙面=2202     glPopMatrix(); // 出栈2203 204     glTranslatef(0.0,0.0,10.0); // 向前10个单位 // 移动到点3205 206     glPushMatrix(); // 压栈3207         glRotatef(180.0,0.0,1.0,0.0);208         DrawWall(5.0); // 绘制墙面=3209         glRotatef(90.0,0.0,1.0,0.0);210         glTranslatef(0.0,0.0,5.0);211         DrawWall(5.0);  // 绘制墙面=4212     glPopMatrix();// 出栈3213 214     glTranslatef(-5.0,0.0,5.0); // 移动到点4215 216     glPushMatrix(); // 压栈4217         glRotatef(180.0,0.0,1.0,0.0);218         DrawWall(5.0); // 绘制墙面=5219     glPopMatrix(); // 出栈4220 221     //Last and longest piece:222     glPushMatrix(); // 压栈5223         glRotatef(90.0,0.0,1.0,0.0);224         glTranslatef(0.0,0.0,-5.0); // // 移动到点5225         DrawWall(6.0);  // // 绘制墙面=7226         //the "door"227             glTranslatef(6.0,0.0,0.0);228              // 绘制墙面=8229             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.0234                 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();// 压栈6241                 glTranslatef(0.0,WallHeight,0.0);242                 DrawHigherWallPart(i); // 绘制城墙的顶部243             glPopMatrix();  // 出栈6244         245         glTranslatef(3.0,0.0,0.0);246         DrawWall(6.0);// 绘制墙面=9247     glPopMatrix(); // 出栈5248     249     glPopMatrix(); // 出栈1250 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); //  编号点=1265         glVertex3f(10.0,0.0,0.0); //  编号点=2266         glVertex3f(10.0,0.0,10.0); //  编号点=3267         glVertex3f(5.0,0.0,15.0); //  编号点=4268         glVertex3f(0.0,0.0,15.0); //  编号点=5269         glVertex3f(0.0,0.0,0.0);//  编号点=1270     glEnd();271 272 273     //Turn two sided lighting on for the walls274     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); //  目前点=1283     284     glTranslatef(10.0,0.0,0.0) ; // 移动到点=2285     glCallList(TowerListNum);286 287     glTranslatef(0.0,0.0,10.0); // 移动到点=3288     glCallList(TowerListNum);289 290     glTranslatef(-5.0,0.0,5.0); // 移动到点=4291     glCallList(TowerListNum);292 293     glTranslatef(-5.0,0.0,0.0); // 移动到点=5294     glCallList(TowerListNum);295 296     glFlush();            //Finish rendering297     glutSwapBuffers();    //Swap the buffers ->make the result of rendering visible298 }299 void Reshape(int x, int y)300 {301     if (y == 0 || x == 0) return;  //Nothing is visible then, so return302     //Set a new projection matrix303     glMatrixMode(GL_PROJECTION);  // 投影模式304     glLoadIdentity();305     //Angle of view:40 degrees306     //Near clipping plane distance: 0.5307     //Far clipping plane distance: 20.0308     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:    //ESC317         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/

 

openGL+VS2010的例程--城堡模型注释版(三维)