基于opengl的三维场景漫游实现_第1页
基于opengl的三维场景漫游实现_第2页
基于opengl的三维场景漫游实现_第3页
基于opengl的三维场景漫游实现_第4页
基于opengl的三维场景漫游实现_第5页
已阅读5页,还剩5页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、基于opengl的三维场景漫游实现摘要: 本课题是关于opengl三维场景的实现,要求能够实现人机交互,具有缩放、旋转等基本的功能。利用opengl创建三维模型的原理,本课题在理解opengl创建图形元的基础上,实现了简单三维场景模型的建立。通过建立全局Camera,实现了对场景全方位的观测,同时能够及时响应键盘和鼠标的操作。在此基础上,利用天空盒子和全局地形的方法,实现了三维场景的基本框架,能够在虚拟场景中任意角度的漫游。通过纹理贴图的方法,实现场景的创建,并对场景内部的事物进行碰撞检测,来实现简单的三维场景漫游。关键词:三维建模; 全局Camera; 场景漫游; 纹理贴图; 碰撞检测目录1

2、 课题论述11.1选题背景简介11.2系统开发平台及运行环境11.2.1 开发环境的搭建11.2.2 opengl绘图机制12课题实现的关键技术22.1 场景建模22.2 场景渲染22.3 纹理映射22.4 碰撞检测33漫游场景的实现43.1 全局Camera的创建43.2 地形和天空的绘制53.3场景的绘制63.4纹理和字体类的设计74 总结85 程序使用方法介绍8 1 课题论述1.1选题背景简介 随着科技的发展,人们对视觉的需求也越来越高,这正好也促发了计算机图形学的快速发展:从简单的平面图形到3D空间的立体图形空间的一个转变,为opengl提供了广阔的应用和开发前景。随着opengl的越

3、来越成熟,在各个领域的应用也变得广泛起来。从计算机、多媒体、影视到医学、工业等领域。Opengl开发的重心也有所转变,从普通的三维场景的建立,到现在的大型复杂场景的三维信息生成、实时三维场景光影效果的模拟和实时三维场景的内存使用控制,opengl的发展越来越成熟。 正是基于opengl目前广泛的应用,本课题从opengl基本的图形元的创建、渲染、视角的转换等方面,选择一些opengl的基本操作,实现简单的三维场景空间的漫游,促进对opengl进一步的了解,也为以后进一步的开发做准备。1.2系统开发平台及运行环境 本设计是基于Opengl 1.0在windows7操作系统下使用Visual C+

4、6.0集成开发环境开发并调试,设计中使用了基于Win Application的架构。1.2.1 开发环境的搭建本设计是在Visual C+ 6.0下使用Opengl1.0库开发的,开发环境搭建步骤详细如下:(1)安装Visual C+ 6.0。(2)配置Opengl1.0由于Visual C+ 6.0本身带有安装好的opengl1.0版本,所以一些头文件和bin路径的设置就不必要做了。但自带的opengl1.0 没有包含 glut函数库,所以需要下载glut函数库,并正确的设置include和bin的路径,并把dll文件放到system32下。1.2.2 opengl绘图机制 在Windows

5、环境的绘图机制下使用图形设备接口GDI作图要通过设备上下文调用相应的函数,用opengl作图也是这样。Opengl通过“渲染上下文”即RC完成对三维图形的绘制。Windows下的设备上下文和窗口都支持“文图格式”属性,和RC在位图结构方面是一致的。因此只要在创建RC的同时与一个DC建立联系,opengl函数就可以通过对应的DC绘制到相应的显示设备上面。2课题实现的关键技术2.1 场景建模 场景的建模能够直接的展示出场景的 三维特性,也是影响三维可视化功能的关键。在本课题中,我主要完成了一下几个场景的建模。 首先是地形的建模,在地形的建模中,采用了四边形近视模型和纹理贴图的方式来完成。在xoz平

6、面,建立的是一个46*46的网格模型,其中每个方格的大小大约为7个坐标。在y方向,通过读取位图信息的方式,建立的随机高度的模型。其中,地形中心部分为平面,用于建立一些基本的场景,而地形的边界部分,用位图数据随机读取,生成一圈环绕的小山,把整个场景环绕在山围之中。房子模型的建立是通过opengl简单的图形元建立,首先建立房子的四周,即四个围墙,用四个平面图形建立,然后屋顶通过两个四边形和两个三角形进行建模,实现三维房屋的构建。天空的建立有很多方法,基本的有两种:一种是天空盒法,另一种是天空球法。天空盒是有一个长方体,在它的各个面上贴有天空的图片组成。天空球是有一个球体,在它的表面贴上天空的纹理组

7、成。天空球相对于天空盒子较简单,因为它只需要一张纹理,但为了显示效果的真实性,本课题采用的是天空盒子的方法,建立六个天空的面,然后选取合适的天空图片进行贴图。由于六个面的链接处会出现一条线,为了实现天空的无缝连接,需要设置纹理的一些属性,来达到天空的无缝连接。2.2 场景渲染场景的渲染对于三维空间来说也是十分最要的,因为这直接决定着场景的真实性。本课题主要利用了纹理映射场景进行渲染。纹理映射是把纹理空间中的纹理像素映射到屏幕空间中的像素的过程,利用纹理映射,可以使三维的世界显得更加的逼真。本课题中主要对地形、天空、房子等进行了纹理的渲染,同时利用鼠标来旋转摄像机,相当于对物体进行了三维空间的旋

8、转,来更好的观测场景的效果。2.3 纹理映射 纹理映射技术的原理是通过把纹理空间坐标与物体空间坐标的每一点建立关联,实现把二维的纹理图像映射到三维的物体表面,从而呈现出真实的视觉效果。 纹理映射操作包括启用及载入纹理,指定纹理坐标,设置纹理的参数,使用纹理对象等方面。Opengl中规定纹理贴图在RGBA模式下。本文启用了opengl中的纹理映射技术来对三维场景中的地形、天空和房子进行纹理的渲染,实现的大体过程如下:(1) 首先要创建纹理对象并且为此对像指定纹理。调用glGenTexture()函数创建纹理对象,使用一个正整数对纹理对象进行编号,并把相应的对象存储到指定的数组中。最后调用glBi

9、ndTexture()函数实现把生成的纹理名字绑定到对应的目标纹理上。(2) 控制滤波的方式Opengl在图像的时候,有可能显示的图像比原始的要大,也有可能比原始的图像要小,所以要采用控制滤波的方式,对其进行适当的放大和缩小。本课题采用的是GL_LINEAR方式,这样纹理总是以平滑的方式来显示。(3) 启用纹理并载入纹理的数据首先要启用纹理,通过glEnable(GL_TEXTURE_2D)来启用二维的纹理,并通过glBindTexture()和glTexImage2D()来绑定纹理数据。由于贴纹理的时候要明确纹理与映射物体的映射关系,所以通过函数glTexCoord2f()来进行绑定。2.4

10、 碰撞检测 碰撞检测技术主要是对场景内部的物体进行的,由于场景都是自己通过三维图形建立的,而随着在场景内部全局Camera的移动,相当于观察者在场景中进行漫游。当观察者移动到一些场景内部时,如果没有碰撞检测,就会直接穿过物体,不符合实际的情况,所以需要引入碰撞检测技术。碰撞检测技术有很多中,本课题采用的是基于盒子的碰撞检测原理,即在被检测物体的一定范围之内,假设存在一个盒子把物体包围住,当观察者移动到盒子的范围边界时,就停止一定,然后根据Camera的角度,进行偏移。本课题场景比较简单,主要是有山和房子组成,所以碰撞检测只做了山和房子的检测。对于山的检测比较简单,利用盒子原理,在山的内部边界部

11、分,设置一个四方体边界,当相机移动到边界的时候,就停止移动,然后根据角度左右或则前后移动,防止穿过环绕山。而对于房子的检测,就要分为好几部分,墙面的检测,门的检测。其中在房子内部和外部的边界部分都要做边缘的检测,使从外部进入和里面出来都不能穿过墙面和门。其实现方法也是在墙面和门的附近很小的距离设置检测边界,当到达边界时,即碰撞到了物体,不能越过边界,从而达到碰撞检测并不穿过物体的目的。3漫游场景的实现 3.1 全局Camera的创建由于需要在虚拟场景中实现漫游,如果只是简单的控制坐标轴的旋转,不能够对场景中的物体进行全方位的观察,因此引入了全局Camera,通过键盘的方向键和鼠标的移动,来控制

12、Camera移动的方向和角度,实现场景的漫游。场景中大量的旋转和平移,如果没有相机来控制的话,程序会显得杂乱。因此。本课题首先创建了Camera来实现对ViewMatrix矩阵和ProjectMatrix矩阵的管理。通俗的说,就是由相机来维护整个场景的平移、旋转等矩阵换算,还有远近裁剪面的矩阵,这样大量复杂计算全都在相机这样一个实体类中得以处理,使用者只需要调用相机的外部接口来满足自己的视角,相机内部处理矩阵计算,最终传递给OpenGL对应的Matrix,从而支撑起整个场景的视觉效果。在程序设计中,首先创建了Camera类,包含一些基本的处理函数,关键的函数部分如下:void setCamer

13、a(float positionX, float positionY, float positionZ, float viewX, float viewY, float viewZ, float upVectorX, float upVectorY, float upVectorZ);void rotateView(float angle, float X, float Y, float Z); /* 旋转摄像机方向 */void setViewByMouse(); /* 根据鼠标设置摄像机观察方向 */void yawCamera(float speed); /* 左右摄像机移动 */voi

14、d moveCamera(float speed); /* 前后移动摄像机 */ void setLook(); /* 放置摄像机 */void checkForMovement(); /*检查时候移动*/void CheckedgeCollision(Vector3f oldPos,Vector3f oldView); /*碰撞检测*/首先需要调用setCamera(),初始化相机开始的位置,在本程序中,相机的初始位置设定在场景的中心,方便后边的碰撞检测。然后通过键盘或则鼠标的相应事件,调用相应的函数,判断是要向哪个方向一定。程序中设定“W、S、A、D、Shift”以及键盘上的方向键为相机移

15、动和加速的响应键,当方向键被按下时,调用yawCamera() 函数和moveCamera()函数,获取移动的方向,保存相应的值。同时移动鼠标,调用setViewByMouse()函数,通过计算鼠标移动的角度,获取Camera要旋转的视角。最后调用checkForMovement()函数,检查键盘和鼠标是否移动,如果移动,把上述获取的值赋予Camera,移动相机,实现漫游的效果。对于场景内部的物体,需要做碰撞检测来达到真实性,所以本程序采用了包围盒子的方法,在被检测物体一定小的范围内,设置检测区域,当相机移动到检测区域的边界时,在checkForMovement()函数中调用Checkedge

16、Collision()函数,做出判断,看是否碰撞到检测边界,如果是,则停止移动,防止穿过被检测物。3.2 地形和天空的绘制实现了全局Camera后,接下来就要绘制基本的框架:地形和天空。对于地形,本程序分为两部分:一部分是高低不平的环绕山,另一部分是平地,用于建造房子等场景。对于天空的绘制,采用了天空盒子的思想,即绘制一个长方体,把所有的场景包含进来。本程序中,设计了一个SkyBox类,用于绘制地形和天空,具体的机构如下:class SkyBoxpublic: SkyBox(); SkyBox(); void CreateSkyBox(); /天空包围盒 void DrawGround();

17、/绘制地面并纹理贴图void Init(); /初始化地形 Vector3f m_TerrainCoordm_TerrainSize*m_TerrainSize; /网格坐标数据void InitTerrainData(float height); /初始化地形数据 void DrawGrid(int minrow,int maxrow,int mincol,int maxcol);private:GLuint m_Skybox6; GLuint m_Groundtexture2; AUX_RGBImageRec *m_TerrainImage; Texture m_Texture;对于地形的

18、划分,程序采用了46*46个小网格的方法来绘制,存储在m_TerrainCoord 数据中, 对于地形的高度部分,由于高度不统一,所以程序通过调用auxDIBImageLoad()函数,读取一张位图的RGB数据信息,来随机的分配高度,并通过InitTerrainData(float height)函数,初始化纹理的信息。当所有的数据都初始以后,调用DrawGround()函数,绘制地形。对于天空的绘制,首先设置天空盒子的长、宽、高以及绘制原点的坐标,然后调用CreateSkyBox()函数进行绘制。其中,为了实现每个面的链接出没有缝隙,在CreateSkyBox()函数中通过glTexPara

19、meteri()函数设置纹理的参数信息,这样就能够实现无缝的链接。3.3场景的绘制地形和天空的基本框架绘制完成以后,就是场景内部物体的绘制。在本程序中,场景比较简单,只绘制了房子和环绕山。其中环绕山在绘制地形的时候已经实现,所以只需要实现房子场景。对于房子的绘制,程序分为四部分:四个墙面、两个斜的屋顶、两个上部的三角墙面和门,通过House类,实现基本的绘制。基本的结构如下:class Housepublic: House();House();void Init();void DrawHouse(); /绘制房子void DrawSurface(); /绘制墙面void DrawDoor();

20、 /绘制门void DrawRoof(); /绘制斜屋顶void DrawRoofOb(); /绘制直屋顶bool open ;private:Texture m_Texture;GLuint m_WallTexture4;房子的绘制比较简单,主要绘制一些基本的线元和小方格,然后绑定纹理的信息。首先是调用Init()函数,初始化房子的纹理信息,然后调用各个绘制函数,实现房子的绘制。3.4纹理和字体类的设计 程序中对于纹理和显示字体的部分,也分别设计了Texture类和Font类,来实现对纹理和字体的调用。具体的结构如下:纹理类:class Texturepublic: bool LoadTexture(char *filename, GLuint &texture); /生成一个纹理,并用texture邦定 bool LoadAlphaTexture(char *filename,char *alphafilename, GLuint &texture,unsigned char compare);void Readstr(FILE *f,char *string); /读取文件中的数据字体类:class Fontpublic: Font(); Font(); bool Ini

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论