《地形模型的三维可视化》程序设计一、题目请用OpenGL图形库,编制程序实现地形模型的三维可视化,并进行地形模型的纹理设置,并可以通过键盘进行交互操作(移动和旋转)。
(注:给定的地形模型数据是已经建好的不规则三角网。
)二、提交资料1.程序的详细步骤和所有相关数据;步骤:①录入三角形数据②获得地形的范围③绘制三角网④设置纹理坐标⑤计算参考点的位置⑥移动相关数据文件:数据文件DHS.dat三角网文件DHS.tri图片文件TERRAIN.BMP2. 程序清单(包括程序说明);#include "stdafx.h"#include <windows.h>#include <GL/gl.h>#include <GL/glu.h>#include <GL/glaux.h>#include <fstream.h>#include <math.h>void CALLBACK elbowAdd (void);void CALLBACK elbowSubtract (void);void CALLBACK shoulderAdd (void);void CALLBACK shoulderSubtract (void);//点结构定义typedef struct{long id;double x;double y;}POINTXYZ;//三角形结构定义typedef struct{long id; //三角形号long p[3]; //三角形三个顶点的序号long xl[3]; //拓扑关系}TRIANGLE;//顶点变量POINTXYZ *pPt;//三角形变量TRIANGLE *pTri;//顶点总数int iTotalNum;//三角形总数int iTotalTriNum;//外围结构typedef struct vrtagBOX{double minx;double miny;double minz;double maxx;double maxy;double maxz;}vrBOX;//外围结构vrBOX _box;unsigned int m_nID; //存储纹理的索引号int m_nWidth; //纹理图片的宽度int m_nHeight; //纹理图片的高度float (*_ptexture)[2]; //存储三角网的纹理数据//视点参考点的偏移量double lookx, looky, lookz;//移动的速度float _speed;//垂直方向视点和所要看实体的间的距离//视点的位置double _eyeposition[3];//参考点的位置double _referencepoint[3];//鼠标位移与象素之比的分母,即象素数int _Pixels;//设置纹理坐标void SetTextureCoord();//读取纹理数据bool LoadTriangleBMP( LPSTR szFileNameD);//向前移动void Move(bool is_forward);//获得鼠标在x,y方向的相对位移量bool Rotate(int dx, int dy);//计算视点与参考点的位置void _CalcuEyePositionAndReferencePoint(int type,float amount);void myinit(void);//读取点坐标、三角形数据void ReadData();void Render();//获得外围void SetBOX();void CALLBACK myReshape(GLsizei w, GLsizei h);void CALLBACK display(void);//读取纹理数据bool LoadTriangleBMP(char* szFileName){AUX_RGBImageRec *pBitmap = NULL;if(!szFileName) return false;//装载数据并存储pBitmap = auxDIBImageLoad(szFileName);if(pBitmap == NULL) return false;glGenTextures(1, &m_nID);// 绑定纹理到纹理数组,并进行初始化。
glBindTexture(GL_TEXTURE_2D, m_nID);//控制纹理,映射到片元(fragment)时怎样对待纹理。
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);//定义二维纹理glTexImage2D(GL_TEXTURE_2D, 0, 3, pBitmap->sizeX, pBitmap->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, pBitmap->data);m_nWidth = pBitmap->sizeX;m_nHeight = pBitmap->sizeY;if (pBitmap) delete pBitmap;return true;}int main(int argc, char* argv[]){/* 设置双缓存和RGBA颜色模式*/auxInitDisplayMode (AUX_DOUBLE|AUX_RGBA);auxInitPosition (0, 0, 1600, 800);auxInitWindow ("作业");myinit();auxReshapeFunc (myReshape);auxKeyFunc (AUX_LEFT, shoulderSubtract);auxKeyFunc (AUX_RIGHT, shoulderAdd);auxKeyFunc (AUX_UP, elbowAdd);auxKeyFunc (AUX_DOWN, elbowSubtract);auxMainLoop(display);return 0;}void CALLBACK elbowAdd (void){Move(true);}void CALLBACK elbowSubtract (void){Move(false);}void CALLBACK shoulderAdd (void){Rotate(50,0);}void CALLBACK shoulderSubtract (void){Rotate(-50,0);}//读取点坐标、三角形数据void ReadData(){ifstream ifile("f:\\qq\\DHS.dat");ifile >> iTotalNum;pPt =new POINTXYZ[iTotalNum];//循环读入定顶点坐标数据;for (int i=0;i<iTotalNum;i++){ifile >>pPt[i].id >> pPt[i].x >>pPt[i].y >> pPt[i].z;}ifile.close();ifstream ifile2("f:\\qq\\DHS.tri");ifile2 >> iTotalTriNum;pTri =new TRIANGLE[iTotalTriNum];//循环读入定顶点坐标数据;for ( i=0;i<iTotalTriNum;i++){ifile2 >>pTri[i].id >> pTri[i].p[0] >>pTri[i].p[1] >> pTri[i].p[2]; }ifile2.close();SetBOX();}//功能:获得地形的范围void SetBOX(){_box.minx = 9900000;_box.miny = 9900000;_box.minz = 9900000;_box.maxx = -9900000;_box.maxy = -9900000;_box.maxz = -9900000;//对所有的顶点循环for (int i = 0; i < iTotalNum; i++){if(_box.minx > pPt[i].x) _box.minx = pPt[i].x;if(_box.miny > pPt[i].y) _box.miny = pPt[i].y;if(_box.minz > pPt[i].z) _box.minz = pPt[i].z;if(_box.maxx < pPt[i].x) _box.maxx = pPt[i].x;if(_box.maxz < pPt[i].z) _box.maxz = pPt[i].z;}}void myinit(void){//读取点坐标、三角形数据ReadData();char *_bmpfilename; //纹理图片的文件名_bmpfilename="f:\\qq\\TERRAIN.BMP"; //terrain.bmp"; //suban_1.bmp"; //读取纹理数据LoadTriangleBMP(_bmpfilename);//计算纹理坐标SetTextureCoord();//设置视点的一些初始参数lookx = 5.0f;looky = 0.0f;lookz = 0.0f;_Pixels= 3000;_height=2.50;_speed= 5.0f;_eyeposition[0] = _box.minx -300;_eyeposition[1] = _box.miny -300;_eyeposition[2] = _box.maxz+50;_referencepoint[0] = _box.maxx;_referencepoint[1] = _box.maxy;_referencepoint[2] = _box.minz;}void CALLBACK myReshape(GLsizei w, GLsizei h){glViewport(0, 0, w, h);glMatrixMode(GL_PROJECTION);glLoadIdentity();gluPerspective(60.0, 1.0*(GLfloat)w/(GLfloat)h, 1.0, 90000.0);glMatrixMode(GL_MODELVIEW);glLoadIdentity();}{glClearColor(1.0,1.0,1.0,0.0);glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);glPushMatrix();//投影变换gluLookAt(_eyeposition[0] , _eyeposition[1] , _eyeposition[2],_referencepoint[0], _referencepoint[1] , _referencepoint[2], 0,0,1);glPushMatrix();glTranslated (_box.maxx+300 ,_box.maxy+100 , _box.maxz+300);glColor3f (1.0, 0.0, 0.0);auxSolidSphere (50.0);glPopMatrix ();GLfloat mat_ambient[]= { 1.0, 1.0, 1.0, 1.0 };GLfloat mat_diffuse[]= { 1.0, 1.0, 1.0, 1.0 };GLfloat mat_specular[] = { 1.0, 1.0, 1.0, 1.0 };GLfloat mat_shininess[] = { 50.0 };GLfloat light0_diffuse[]= { 1.0, 1.0, 1.0, 1.0};//定义光源的位置GLfloat light0_position[] = { _box.maxx,_box.maxy, _box.maxz-800, 1.0 };GLfloat light1_ambient[]= { 1.0, 0.0,0.0, 1.0 };GLfloat light1_diffuse[]= { 1.0, 0.0, 0.0, 1.0 };GLfloat light1_specular[] = { 1.0, 0.0, 0.0, 1.0 };GLfloat light1_position[] = { (_box.minx +_box.maxx)/2.0 ,(_box.miny +_box.maxy)/2.0 , _box.maxz+500, 1.0 };GLfloat spot_direction[] = { 0.0, 0.0, -1.0 };glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient);glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse);glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);glMaterialfv(GL_FRONT, GL_SHININESS,mat_shininess);glLightfv(GL_LIGHT0, GL_AMBIENT, light0_diffuse);glLightfv(GL_LIGHT0, GL_DIFFUSE, light0_diffuse);glLightfv(GL_LIGHT0, GL_POSITION,light0_position);glLightfv(GL_LIGHT1, GL_AMBIENT, light1_ambient);glLightfv(GL_LIGHT1, GL_DIFFUSE, light1_diffuse);glLightfv(GL_LIGHT1, GL_SPECULAR,light1_specular);glLightfv(GL_LIGHT1, GL_POSITION,light1_position);glLightf (GL_LIGHT1, GL_SPOT_CUTOFF, 10.0);glLightfv(GL_LIGHT1, GL_SPOT_DIRECTION,spot_direction);glEnable(GL_LIGHT0);glDepthFunc(GL_LESS);glEnable(GL_DEPTH_TEST);//启动光照glEnable(GL_LIGHTING);//绘制地面模型Render();glDisable(GL_LIGHTING);glPopMatrix();glFlush();auxSwapBuffers();}//功能:绘制三角网void Render(){glBindTexture(GL_TEXTURE_2D, m_nID);glEnable(GL_TEXTURE_2D);//画三角形线面glBegin(GL_POLYGON); //GL_LINE_LOOP);//for( int i = 0; i < iTotalTriNum; i++){glTexCoord2f(_ptexture[pTri[i].p[0]][0], _ptexture[pTri[i].p[0]][1] );glVertex3f(pPt[pTri[i].p[0]].x, pPt[pTri[i].p[0]].y, pPt[pTri[i].p[0]].z);glTexCoord2f(_ptexture[pTri[i].p[1]][0], _ptexture[pTri[i].p[1]][1] );glVertex3f(pPt[pTri[i].p[1]].x, pPt[pTri[i].p[1]].y, pPt[pTri[i].p[1]].z);glTexCoord2f(_ptexture[pTri[i].p[2]][0], _ptexture[pTri[i].p[2]][1] );glVertex3f(pPt[pTri[i].p[2]].x, pPt[pTri[i].p[2]].y, pPt[pTri[i].p[2]].z); }glEnd();glDisable(GL_TEXTURE_2D);}//设置纹理坐标void SetTextureCoord(){_ptexture = new float[iTotalNum][2];float _min_max = fabs(_box.maxx -_box.minx);float _min_maxy = fabs(_box.maxy-_box.miny);for (int i = 0; i < iTotalNum; i++){_ptexture[i][0] = (pPt[i].x-_box.minx)/_min_max;}//计算视点的位置和参考点的位置void _CalcuEyePositionAndReferencePoint(int type,float amount) {float a;double _h;switch(type){//向前移动就执行这步case 1:_eyeposition[0] += lookx * amount;_eyeposition[1] += looky * amount;break;//水平面内旋转就执行这步case 2:lookx = lookx*cos(amount) + looky*sin(amount);looky = looky*cos(amount) - lookx*sin(amount);a = 1/sqrt(lookx*lookx + looky*looky);lookx *= a;looky *= a;break;}//计算参考点的位置_referencepoint[0] = _eyeposition[0] + lookx;_referencepoint[1] = _eyeposition[1] + looky;_referencepoint[2] = _eyeposition[2] + lookz;}//向前移动void Move(bool is_forward){//使视点向前移动if(is_forward){_CalcuEyePositionAndReferencePoint(1, _speed);}else{_CalcuEyePositionAndReferencePoint(1, - _speed);//获得鼠标在x,y方向的相对位移量bool Rotate(int dx, int dy){//调用_CalcuEyePositionAndReferencePoint()函数完成旋转操作_CalcuEyePositionAndReferencePoint(2, ((float)dx/ _Pixels));return true;}3.程序运行结果。