1、基于opengl的三维场景漫游实现基于OPengl的三维场景漫游实现摘要:本课题是关于OPengl三维场景的实现,要求能够实现人机交互,具有缩放、旋转 等基本的功能。利用opengl创建三维模型的原理,本课题在理解opengl创建图形元的基础上,实现了 简单三维场景模型的建立。通过建立全局Camera,实现了对场景全方位的观测,同时能够 及时响应键盘和鼠标的操作。在此基础上,利用天空盒子和全局地形的方法,实现了三维 场景的基本框架,能够在虚拟场景中任意角度的漫游。通过纹理贴图的方法,实现场景的 创建,并对场景内部的事物进行碰撞检测,来实现简单的三维场景漫游。关键词:三维建模;全局Camera;
2、场景漫游;纹理贴图;碰撞检测1课题论述 11.1选题背景简介 仁1.2系统开发平台及运行环境 1.1.2.1开发环境的搭建 1.1.2.2 OPe ngl 绘图机制 1.2课题实现的关键技术 22.1场景建模 2.2.2场景渲染 2.2.3纹理映射 2.2.4碰撞检测 3.3漫游场景的实现 43.1 全局 Camera的仓U建 4.3.2地形和天空的绘制 5.3.3场景的绘制 6.3.4纹理和字体类的设计 7.4总结 85程序使用方法介绍 81课题论述1.1选题背景简介随着科技的发展,人们对视觉的需求也越来越高,这正好也促发了计算机图形学的快 速发展:从简单的平面图形到 3D空间的立体图形空间
3、的一个转变,为 OPengl提供了广阔 的应用和开发前景。随着OPengl的越来越成熟,在各个领域的应用也变得广泛起来。从计 算机、多媒体、影视到医学、工业等领域。 OPe ngl开发的重心也有所转变,从普通的三维场景的建立,到现在的大型复杂场景的三维信息生成、实时三维场景光影效果的模拟和实 时三维场景的内存使用控制,OPengl的发展越来越成熟。正是基于opengl目前广泛的应用,本课题从opengl基本的图形元的创建、渲染、视角 的转换等方面,选择一些 OPengl的基本操作,实现简单的三维场景空间的漫游,促进对ope ngl进一步的了解,也为以后进一步的开发做准备。1.2系统开发平台及运
4、行环境本设计是基于OPengl 1.0在Windows7操作系统下使用ViSualC+6.0集成开发环境开 发并调试,设计中使用了基于 Win APPIiCation的架构。1.2.1开发环境的搭建本设计是在ViSUalC+ 6.0下使用OPengl1.0库开发的,开发环境搭建步骤详细如下:(1) 安装 ViSUaI C+ 6.0。(2) 配置 OPengl1.0由于ViSUal C+ 6.0本身带有安装好的opengl1.0版本,所以一些头文件和bin路径的 设置就不必要做了。但自带的opengl1.0没有包含glut函数库,所以需要下载glut函数库, 并正确的设置include和bin的
5、路径,并把dll文件放到SyStem32下。1.2.2 OPengl绘图机制在Windows环境的绘图机制下使用图形设备接口 GDl作图要通过设备上下文调用相应的函数,用opengl作图也是这样。OPengl通过 渲染上下文”即RC完成对三维图形的绘 制。Windows下的设备上下文和窗口都支持 文图格式”属性,和RC在位图结构方面是一致的。因此只要在创建RC的同时与一个DC建立联系,opengl函数就可以通过对应的 DC 绘制到相应的显示设备上面。2课题实现的关键技术2.1场景建模场景的建模能够直接的展示出场景的 三维特性,也是影响三维可视化功能的关键。在本课题中,我主要完成了一下几个场景的
6、建模。首先是地形的建模,在地形的建模中,采用了四边形近视模型和纹理贴图的方式来 完成。在XOZ平面,建立的是一个46*46的网格模型,其中每个方格的大小大约为 7个坐 标。在y方向,通过读取位图信息的方式,建立的随机高度的模型。其中,地形中心部分 为平面,用于建立一些基本的场景,而地形的边界部分,用位图数据随机读取,生成一圈 环绕的小山,把整个场景环绕在山围之中。房子模型的建立是通过OPengl简单的图形元建立,首先建立房子的四周,即四个围墙, 用四个平面图形建立,然后屋顶通过两个四边形和两个三角形进行建模,实现三维房屋的 构建。天空的建立有很多方法,基本的有两种:一种是天空盒法,另一种是天空
7、球法。天空 盒是有一个长方体,在它的各个面上贴有天空的图片组成。天空球是有一个球体,在它的 表面贴上天空的纹理组成。天空球相对于天空盒子较简单,因为它只需要一张纹理,但为 了显示效果的真实性,本课题采用的是天空盒子的方法,建立六个天空的面,然后选取合 适的天空图片进行贴图。由于六个面的链接处会出现一条线,为了实现天空的无缝连接, 需要设置纹理的一些属性,来达到天空的无缝连接。2.2场景渲染场景的渲染对于三维空间来说也是十分最要的,因为这直接决定着场景的真实性。本 课题主要利用了纹理映射场景进行渲染。纹理映射是把纹理空间中的纹理像素映射到屏幕空间中的像素的过程,利用纹理映 射,可以使三维的世界显
8、得更加的逼真。本课题中主要对地形、天空、房子等进行了纹理 的渲染,同时利用鼠标来旋转摄像机,相当于对物体进行了三维空间的旋转,来更好的观 测场景的效果。2.3纹理映射纹理映射技术的原理是通过把纹理空间坐标与物体空间坐标的每一点建立关联,实现 把二维的纹理图像映射到三维的物体表面,从而呈现出真实的视觉效果。纹理映射操作包括启用及载入纹理,指定纹理坐标,设置纹理的参数,使用纹理对象 等方面。OPengl中规定纹理贴图在RGBA模式下。本文启用了 OPengl中的纹理映射技术 来对三维场景中的地形、天空和房子进行纹理的渲染,实现的大体过程如下:(1)首先要创建纹理对象并且为此对像指定纹理。调用glG
9、enTexture()函数创建纹理对象,使用一个正整数对纹理对象进行编号, 并 把相应的对象存储到指定的数组中。最后调用 glBi ndTexture()函数实现把生成的 纹理名字绑定到对应的目标纹理上。(2)控制滤波的方式OPe ngl在图像的时候,有可能显示的图像比原始的要大,也有可能比原始的图像 要小,所以要采用控制滤波的方式,对其进行适当的放大和缩小。本课题采用的 是GL_LINEAR方式,这样纹理总是以平滑的方式来显示。(3)启用纹理并载入纹理的数据首先要启用纹理,通过 glEnable(GL_TEXTURE_2D)来启用二维的纹理,并通过 glBindTexture()和glTex
10、lmage2D()来绑定纹理数据。由于贴纹理的时候要明确纹理 与映射物体的映射关系,所以通过函数 glTexCoord2f()来进行绑定。2.4碰撞检测碰撞检测技术主要是对场景内部的物体进行的,由于场景都是自己通过三维图形建立 的,而随着在场景内部全局 Camera的移动,相当于观察者在场景中进行漫游。当观察者 移动到一些场景内部时,如果没有碰撞检测,就会直接穿过物体,不符合实际的情况,所 以需要引入碰撞检测技术。碰撞检测技术有很多中,本课题采用的是基于盒子的碰撞检测原理,即在被检测物体 的一定范围之内,假设存在一个盒子把物体包围住,当观察者移动到盒子的范围边界时, 就停止一定,然后根据 Ca
11、mera的角度,进行偏移。本课题场景比较简单,主要是有山和 房子组成,所以碰撞检测只做了山和房子的检测。对于山的检测比较简单,利用盒子原理,在山的内部边界部分,设置一个四方体边界, 当相机移动到边界的时候,就停止移动,然后根据角度左右或则前后移动,防止穿过环绕 山。而对于房子的检测,就要分为好几部分,墙面的检测,门的检测。其中在房子内部和 外部的边界部分都要做边缘的检测,使从外部进入和里面出来都不能穿过墙面和门。其实 现方法也是在墙面和门的附近很小的距离设置检测边界, 当到达边界时,即碰撞到了物体,不能越过边界,从而达到碰撞检测并不穿过物体的目的。3漫游场景的实现3.1全局Camera的创建由
12、于需要在虚拟场景中实现漫游,如果只是简单的控制坐标轴的旋转,不能够对场景 中的物体进行全方位的观察,因此引入了全局 Camera,通过键盘的方向键和鼠标的移动,来控制Camera移动的方向和角度,实现场景的漫游。场景中大量的旋转和平移,如果没有相机来控制的话,程序会显得杂乱。因此。本课 题首先创建了 Camera来实现对VieWMatriX矩阵和PrOjeCtMatriX矩阵的管理。通俗的说, 就是由相机来维护整个场景的平移、旋转等矩阵换算,还有远近裁剪面的矩阵,这样大量 复杂计算全都在相机这样一个实体类中得以处理,使用者只需要调用相机的外部接口来满 足自己的视角,相机内部处理矩阵计算,最终传
13、递给 OPenGL对应的MatriX ,从而支撑起整个场景的视觉效果。在程序设计中,首先创建了 Camera类,包含一些基本的处理函数,关键的函数部分如下:void SetCamera(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); /* 旋转摄像机方向
14、*/void SetVieWByMOUSe(); /*根据鼠标设置摄像机观察方向 */void yawCamera(float speed); /* 左右摄像机移动 */void moveCamera(float speed); /* 前后移动摄像机 */void SetLook(); /* 放置摄像机 */void CheCkForMovement(); /* 检查时候移动 */void CheCkedgeCOlliSion(Vector3f oldPos,Vector3f oldView); /* 碰撞检测 */首先需要调用SetCamera()初始化相机开始的位置,在本程序中,相机的初始
15、位置设 定在场景的中心,方便后边的碰撞检测。然后通过键盘或则鼠标的相应事件,调用相应的 函数,判断是要向哪个方向一定。程序中设定 “W、S、A、D、Shift”以及键盘上的方向键为相机移动和加速的响应键,当方向键被按下时,调用yawCamera()函数和moveCamera() 函数,获取移动的方向,保存相应的值。同时移动鼠标,调用 SetVieWByMouSe()函数,通过计算鼠标移动的角度,获取 Camera要旋转的视角。最后调用CheCkForMoveme nt()函数,检查键盘和鼠标是否移动,如果移动,把上述获取的值赋予 Camera,移动相机,实现漫游的效果。对于场景内部的物体,需要
16、做碰撞检测来达到真实性,所以本程序采用了包围盒子的 方法,在被检测物体一定小的范围内,设置检测区域,当相机移动到检测区域的边界时, 在CheCkFOrMOVement()函数中调用 CheckedgeCollision()函数,做出判断,看是否碰撞到检 测边界,如果是,则停止移动,防止穿过被检测物。3.2地形和天空的绘制实现了全局Camera后,接下来就要绘制基本的框架:地形和天空。对于地形,本程 序分为两部分:一部分是高低不平的环绕山,另一部分是平地,用于建造房子等场景。对 于天空的绘制,采用了天空盒子的思想,即绘制一个长方体,把所有的场景包含进来。本 程序中,设计了一个SkyBOX类,用于绘制地形和天空,具体的机
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1