1、学 院班 级学 号姓 名摘要设计是基于 opengl 的 windows 地形显示系统,从地形高度图中读取相应信息,使用 opengl 针对不同的地形进行绘制。并可以根据键盘输入调节摄像头位置和视角,达到动态效果。Email: 2目录1 摘要 .31.1 设计题目 31.2 设计内容 31.3 开发工具 31.4 应用平台 32 详细设计 .32.1 程序结构 32.2 主要功能 32.3 函数实现 32.4 开发日志 43 程序调试及运行 .43.1 程序运行结果 43.2 程序使用说明 43.3 程序开发总结 44 附件(源程序) .4Email: 31 摘要1.1 设计题目基于 open
2、gl 的 windows 地形显示系统1.2 设计内容从地形高度图中读取相应信息,使用 opengl 针对不同的地形进行绘制。并可以根据键盘输入调节摄像头位置和视角,达到动态效果1.3 开发工具VC6.01.4 应用平台Windows 2000/XP/Vista 32 位2 详细设计2.1 程序结构LoadPicRshapeDrawSceneInitKey funcEmail: 4主要函数功能介绍:Loadpic 参数:无功能:将 terrain.dat 的高度信息读取到缓存中,并绑定至 texture_2d 中,设置好相应的 WRAP ,FILTER等参数。Init参数:无功能:清屏。设置
3、depth 参数。设置 shademode。设置雾效果。设置 modelview proj viewport 参数。Reshape参数:无功能: 设置 modelview,projection,viewport 参数。Drawscene参数:无功能:清屏。计算摄像头坐标。绘制地形。Swapbuffer。打印 fps。Key:参数:无功能:根据键盘输入进行相应的 opengl 参数设置。Special参数:无功能:这对 SPECIAL KEEY INPUT 设置视角。2.2 主要功能本次大作业采用 opengl 作为图形绘制接口,在 window 平台上实现了一个基本的地形绘制系统。主要包括以下
4、几个主要环节:1. 系统初始化。此部分分两个步骤:A) 从 terrain.dat 高度文件中读取需要绘制的地形的各个坐标高度值。将该地形缓存绑定至GL_TEXTURE_2D 纹理中,然后对此纹理的 WRAP FILTER ENV_MODE 进行相应的设置B) 初始化其他参数。包括 clearcolor, 雾参数,alpha 混合。然后进行modelview,projection,viewport 坐标变换的矩阵进行初次设置。2. 输入响应。包括一般键盘输入和方向键输入。A) 一般键盘输入。主要控制摄像头的速度,是否启用雾效果。设置 fillmode。设置 cullmode。Email: 5B
5、) 方向键输入。属于特殊键位处理。可以修改摄像头的俯仰角度。3. 地形绘制。该环节功能最多。包括:A) 使能 GL_TEXTURE_2D。清屏。保存现场矩阵。B) 计算摄像头位置。C) 计算地形颜色。主要是根据高度信息进行相应的高度-颜色映射。D) 交换前后 buffer。E) 计算 fps 并显示。2.3 函数实现(1)系统初始化函数:Loadpic:使用文件操作打开 terrain.dat 高度文件。将高度信息读取到 terrain数组中。fread(bufferter,256 * 256, 1, FilePic);利用 calccolor 函数将高度信息转换为颜色信息。calccolor
6、(GLfloat) bufferteri, terraincolori);将颜色信息传送给 GL_TEXTURE_2D。gluBuild2DMipmaps(GL_TEXTURE_2D, 1, 256, 256, GL_LUMINANCE,GL_UNSIGNED_BYTE,(GLvoid *) (init:设置 default color 和 depth。glClearColor(fogcolor0, fogcolor1, fogcolor2, fogcolor3);glClearDepth(1.0);使能 depth test。glEnable(GL_DEPTH_TEST);设置雾参数。glE
7、nable(GL_FOG);glFogi(GL_FOG_MODE, GL_EXP2);glFogfv(GL_FOG_COLOR, fogcolor);glFogf(GL_FOG_DENSITY, 0.0007);设置各个矩阵。reshape(scrwidth, scrheight);Email: 6calccolor:将高度分成多个区间进行颜色映射。if (height = 0.9) 。 。 。 。if (height = 0.7) 。 。 。 。if (height = 0.6) 。 。 。 。if (height = 0.5) 。 。 。 。如果 height0.5c0 = color30
8、;c1 = color31;c2 = color32;(2)键盘相应函数Special:根据 GLUT_KEY 的不同,增加或者减少摄像头的视角。switch (k) case GLUT_KEY_LEFT:alpha += 2.0;break;case GLUT_KEY_RIGHT:alpha -= 2.0;break;case GLUT_KEY_DOWN:beta -= 2.0;break;case GLUT_KEY_UP:beta += 2.0;break;Key:根据普通输入,改变相应的值。改变速度:case a:Email: 7v += 50.;break;case z:v -= 50
9、.;break;改变 polymode:case p:if (poutline) glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);poutline = 0;else glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);poutline = 1;break;改变雾:case f:fog = (!fog);break;(3)绘制地形Calcposobs:根据摄像头移动速度计算此刻摄像头的位置和方向。摄像头方向计算:dir0 = sin(alpha * M_PI / 180.0);dir2 = cos(alpha * M_PI /
10、180.0) * sin(beta * M_PI / 180.0);dir1 = cos(beta * M_PI / 180.0);摄像头位置计算:obs0 += v * dir0 * dt;obs1 += v * dir1 * dt;obs2 += v * dir2 * dt;drawterrain:绘制地形。glBegin(GL_TRIANGLE_STRIP);glColor3fv(terraincoloridx);glTexCoord2f(ox + i) / 8.0, (oy + h) / 8.0);glVertex3f(j, terrainidx, k);glEnd();reshape
11、:Email: 8重新设置 modelview, projection, viewport 矩阵参数。scrwidth = width;scrheight = height;glViewport(0, 0, (GLint) width, (GLint) height);glMatrixMode(GL_PROJECTION);glLoadIdentity();gluPerspective(50.0, (GLfloat) width / (GLfloat) height),lenghtXmnt * stepYmnt * 0.01, lenghtXmnt * stepYmnt * 0.7);glMa
12、trixMode(GL_MODELVIEW);glLoadIdentity();drawscene:前面几个函数的组合。calcposobs();gluLookAt(obs0, obs1, obs2,obs0 + dir0, obs1 + dir1, obs2 + dir2,0.0, 1.0, 0.0);drawterrain();reshape(scrwidth, scrheight);glutSwapBuffers();fps calculation2.4 开发日志调试基本没有遇到问题。只是添加 opengl 的库有点问题。Email: 93 程序调试及运行3.1 程序运行结果说明:左边窗
13、口是帧率。右边窗口是经过高度-颜色映射出来的地形图。3.2 程序使用说明方向控制。可以通过上下左右方向键控制摄像头的视角朝向。速度控制:A 键增加摄像头移动速度。 Z 键减小摄像头移动速度。3.3 程序开发总结通过这次编程,明白热爱一样东西就要去追寻,不管遇到什么困难,漫天繁星,斩断退路。一路向前。Email: 104 附件(源程序)/* This program is under the GNU GPL.* Use at your own risk.* written by David Bucciarelli (tech.hmwplus.it)* Humanware s.r.l.* base
14、d on a Mikael SkiZoWalkers (MoDEL) / France (SkizoHol.Fr) demo*/#include /#include #include “stdio.h“#include #include /#include /#include /#include /#include #include #include #define _CRT_SECURE_NO_WARNINGS#ifdef WIN32#include #endif/#include /using namespace std;#include #ifndef M_PI#define M_PI
15、3.14159265#endif#define heightMnt 450#define lenghtXmnt 62Email: 11#define lenghtYmnt 62#define stepXmnt 96.0#define stepYmnt 96.0#define WIDTH 640#define HEIGHT 480static GLint T0 = 0;static GLint Frames = 0;#define TSCALE 4#define FOV 85static GLfloat terrain256 * 256;static GLfloat terraincolor25
16、6 * 2563;static int win = 0;static int fog = 1;static int bfcull = 1;static int usetex = 1;static int poutline = 0;static int help = 1;static int joyavailable = 0;static int joyactive = 0;static float ModZMnt;static long GlobalMnt = 0;static int scrwidth = WIDTH;static int scrheight = HEIGHT;#define
17、 OBSSTARTX 992.0#define OBSSTARTY 103.0static float obs3 = OBSSTARTX, heightMnt * 1.3, OBSSTARTY ;static float dir3, v12, v22;static float v = 900.0;static float alpha = 75.0;static float beta = 90.0;Email: 12static voidcalcposobs(void)float alpha1, alpha2;static double t0 = -1.;double dt, t = glutG
18、et(GLUT_ELAPSED_TIME) / 1000.0;if (t0 -1.0e-5)dir0 = 0;if (dir1 -1.0e-5)dir1 = 0;if (dir2 -1.0e-5)dir2 = 0;alpha1 = alpha + FOV / 2.0;v10 = sin(alpha1 * M_PI / 180.0);v11 = cos(alpha1 * M_PI / 180.0);alpha2 = alpha - FOV / 2.0;v20 = sin(alpha2 * M_PI / 180.0);v21 = cos(alpha2 * M_PI / 180.0);obs0 +=
19、 v * dir0 * dt;obs1 += v * dir1 * dt;obs2 += v * dir2 * dt;if (obs1 (lenghtXmnt * stepXmnt) / 2) |(t1 0.0) *end = (lenghtXmnt * stepXmnt) / 2;return 1;elsereturn 0;else if (t2 x2) tmp = x1;x1 = x2;x2 = tmp;x1 -= stepXmnt;if (x1 (lenghtXmnt * stepXmnt) / 2)x2 = (lenghtXmnt * stepXmnt) / 2;Email: 15*s
20、tart = (int) (x1 / stepXmnt) * stepXmnt;*end = (int) (x2 / stepXmnt) * stepXmnt;return 1;static voidprintstring(void *font, char *string)int len, i;len = (int) strlen(string);for (i = 0; i = 2000) GLfloat seconds = (t - T0) / 1000.0;GLfloat fps = Frames / seconds;sprintf(frbuf, “Frame rate: %f“, fps
21、);printf(“%sn“, frbuf);T0 = t;Frames = 0;static voidkey(unsigned char k, int x, int y)switch (k) case 27:exit(0);break;case a:v += 50.;break;case z:v -= 50.;break;case p:if (poutline) glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);poutline = 0;else glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);poutline = 1;E
22、mail: 19break;case f:fog = (!fog);break;case t:usetex = (!usetex);break;case b:if (bfcull) glDisable(GL_CULL_FACE);bfcull = 0;else glEnable(GL_CULL_FACE);bfcull = 1;break;#ifdef XMESAcase :XMesaSetFXmode(fullscreen ? XMESA_FX_FULLSCREEN : XMESA_FX_WINDOW);fullscreen = (!fullscreen);break;#endifstati
23、c voidspecial(int k, int x, int y)switch (k) case GLUT_KEY_LEFT:alpha += 2.0;break;case GLUT_KEY_RIGHT:alpha -= 2.0;break;case GLUT_KEY_DOWN:beta -= 2.0;break;case GLUT_KEY_UP:beta += 2.0;break;Email: 20static voidcalccolor(GLfloat height, GLfloat c3)GLfloat color43 = 1.0, 1.0, 1.0,0.0, 0.8, 0.0,1.0
24、, 1.0, 0.3,0.0, 0.0, 0.8;GLfloat fact;height = height * (1.0 / 255.0);if (height = 0.9) c0 = color00;c1 = color01;c2 = color02;return;if (height = 0.7) fact = (height - 0.7) * 5.0;c0 = fact * color00 + (1.0 - fact) * color10;c1 = fact * color01 + (1.0 - fact) * color11;c2 = fact * color02 + (1.0 - f
25、act) * color12;return;if (height = 0.6) fact = (height - 0.6) * 10.0;c0 = fact * color10 + (1.0 - fact) * color20;c1 = fact * color11 + (1.0 - fact) * color21;c2 = fact * color12 + (1.0 - fact) * color22;return;if (height = 0.5) fact = (height - 0.5) * 10.0;c0 = fact * color20 + (1.0 - fact) * color
26、30;Email: 21c1 = fact * color21 + (1.0 - fact) * color31;c2 = fact * color22 + (1.0 - fact) * color32;return;c0 = color30;c1 = color31;c2 = color32;voidloadpic(void)GLubyte bufferter256 * 256, terrainpic256 * 256;FILE *FilePic;int i, tmp;GLenum gluerr;size_t result;if (FilePic = fopen(“terrain.dat“,
27、 “r“) = 0) fprintf(stderr, “Error loading terrain.datn“);exit(-1);result = fread(bufferter,256 * 256, 1, FilePic);assert(result = 1);fclose(FilePic);for (i = 0; i 255) ? 255 : tmp;glPixelStorei(GL_UNPACK_ALIGNMENT, 1);if (gluerr = gluBuild2DMipmaps(GL_TEXTURE_2D, 1, 256, 256, GL_LUMINANCE,GL_UNSIGNE
28、D_BYTE,(GLvoid *) (exit(-1);Email: 22glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR);glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR
29、);glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);glEnable(GL_TEXTURE_2D);static voidinit(void)float fogcolor4 = 0.6, 0.7, 0.7, 1.0 ;glClearColor(fogcolor0, fogcolor1, fogcolor2, fogcolor3);glClearDepth(1.0);glDepthFunc(GL_LEQUAL);glShadeModel(GL_SMOOTH);glEnable(GL_DEPTH_TEST);glEnable(
30、GL_CULL_FACE);glDisable(GL_BLEND);glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);glEnable(GL_FOG);glFogi(GL_FOG_MODE, GL_EXP2);glFogfv(GL_FOG_COLOR, fogcolor);glFogf(GL_FOG_DENSITY, 0.0007);#ifdef FXglHint(GL_FOG_HINT, GL_NICEST);#endifreshape(scrwidth, scrheight);intmain(int ac, char *av)Email:
31、23glutInitWindowSize(WIDTH, HEIGHT);glutInit(glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE);if (!(win = glutCreateWindow(“Terrain“) fprintf(stderr, “Error, couldnt open windown“);return -1;ModZMnt = 0.0f;loadpic();init();#ifndef FXglDisable(GL_TEXTURE_2D);usetex = 0;#endifglutReshapeFunc(reshape);glutDisplayFunc(drawscene);glutKeyboardFunc(key);glutSpecialFunc(special);glutIdleFunc(drawscene);glutMainLoop();return 0;