《地形模型的三维可视化》程序设计
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
《地形模型的三维可视化》程序设计
一、题目
请用OpenGL图形库,编制程序实现地形模型的三维可视化,并进行地形模型的纹理设置,并可以通过键盘进行交互操作(移动和旋转)。
(注:给定的地形模型数据是已经建好的不规则三角网。
)
二、提交资料
1.程序的详细步骤和所有相关数据;
步骤:①录入三角形数据
②获得地形的范围
③绘制三角网
④设置纹理坐标
⑤计算参考点的位置
⑥移动
相关数据文件:数据文件DHS.dat
三角网文件DHS.tri
图片文件TERRAIN.BMP
2. 程序清单(包括程序说明);
#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.程序运行结果。
11。