三维校园场景

上传人:沈*** 文档编号:67515373 上传时间:2022-03-31 格式:DOC 页数:59 大小:329.50KB
返回 下载 相关 举报
三维校园场景_第1页
第1页 / 共59页
三维校园场景_第2页
第2页 / 共59页
三维校园场景_第3页
第3页 / 共59页
点击查看更多>>
资源描述
辽宁石油化工大学毕业设计 (论文) 用纸前言 三维场景主要应用于楼盘展示、小区规划、广告创意、游戏制作、电影特技等传统方式不好达到效果的领域里。本设计是校园的三维场景制作,通过键盘控制视角的移动,旋转,翻转等动作在三维场景中自由观察各个建筑,能使没来过辽宁石油化工大学的人对我校有身临其境的了解,这与普通的平面图展示相比直观的多。 场景的模型和贴图都是由OpenGL提供,例如要建个楼的模型那么就得先建六个面,让它们构成一个楼的各个面,在用事先处理好的图片贴上去就构成了一个楼,这与真实世界的是一样的,图片要求是垂直拍摄的这样才真实,OpenGL对贴图的材质是有要求的,一般要求位图大小是64*64、128*128、256*256,本文用的位图颜色深度是24位,有大部分为了保证质量用的是256*256,这在程序运行时不至于图片模糊,但程序负担变大了,低于256M内存的PC运行起来会慢一些。在OpenGL 中是用单位长度来表示的,不过只能看到100单位以内的物体,超过这个长度就不在屏幕上显示了,它的长度是用浮点数表示,这样就可以用1.0f表示实际上的1M,也可以用0.1f表示1M,也就是说他的比例尺是可以改变的,一个变量P去乘每个点坐标,那么就可以改变P的值而得到比例尺的改变,可视面积就变大拉。OpenGL 是SGI公司开发的一套高性能的图形处理系统,是图形硬件的软件界面,GL即代表图形库(Graphics Library)。通过OpenGL程序员可以创建交互式应用程序,实现具有逼真效果的三维图形图象,从而在要求高度模拟真实世界的诸多领域中都可以大显身手。目录摘要04一、需求分析071.1 基于OpenGL的三维场景设计的意义071.2 基于OpenGL的三维场景设计要解决的主要问题08二、OpenGL图形绘制及纹理贴图092.1 OpenGL数据类型和函数名092.2 OpenGL颜色设置092.3 OpenGL图形绘制102.4 读取位图文件112.5 位图转换成纹理122.6 OpenGL纹理贴图15三、方案设计173.1 技术可行性173.2 方案实现的概要说明17四、具体实现194.1 程序流程图194.2 制作过程204.3 关键技术及解决办法204.3.1基本光照效果204.3.2 使用混合功能实现透明的原理224.3.3 绘制圆柱,圆盘,球体234.3.4 设置路灯开关264.3.5 旋转,翻转274.3.6 移动28五、实现结果分析及总结305.1 键盘控制说明305.2 运行结果截图305.3 运行结果讨论分析31六、结束语33七、致谢34八、参考书目35九、附录36摘要本设计是利用VC+6.0的编译器,C语言的语法,OpenGL的函数库,建立Win32 Application, 实现三维校园场景的建立,主要楼群,地面,路灯,花坛,球场,树木等的建模及贴图,实现用键盘控制视角的自由移动,旋转,翻转。将我校的校园展现在计算机的三维世界中。程序中将每个物体代码写入相应的函数中,这样,在需要该物体的地方只需调用该函数即可。这些函数无须参数,函数内只写绘图的具体代码。指定一个起点,并在绘图之后回到该点,这样做的目的是方便计算物体在场景中的位置。整个场景可以象垒积木一样用绘制物体的函数垒起来。程序运行是以Windows窗口为舞台,所有物体都绘制在画板上,再通过舞台展示画板的某部分或全部,来表示视野的范围。视角的变换是用画板的相对运动来模拟的,键盘控制的也恰恰是画板而并非某个物体。如此,即可实现在三维场景中自由移动,旋转等动作。程序运行效果参见封二、封三。关键词:建模、OpenGL、三维场景AbstractDesign is use VC + + 6.0 compile ware, the grammar of C language, the function storehouse of OpenGL, establish Win32 Application. Realize the establishment of three-dimensional campus site scene, major building crowd are ground , street lamp, flower bed, court, the etc. of trees build mould and paste picture, realization moves with the freedom of keyboard control visual angle , spins , falls out to turn. Display the campus that I check the three-dimensional world in computer in. In program write in every object code corresponding function in, so, in the place that needs this object , need to use this function only. These functions need not parameter, in function write only draw specific code. Designate a starting point , and return to this point after drawing , the purpose of this is to facilitate to calculate the location in object present scene. It is built that entire site scene can use as base toy bricks to draw the function of object. Program operation is so as Windows window is stage, the object owned is drawn on drawing-board , and then demonstrates the certain part of drawing-board through stage or come completely to express the scope of field of vision. Visual angle alternate is analog with the relative sport of drawing-board, what keyboard control is also drawing-board just and is not certain object. As this, realize the freedom in three-dimensional site scene to move , is revolving to wait for movement. Program runs effect to see cover 2、cover 3。Keyword: Build mould, OpenGL,three-dimensional site scene一、需求分析当前,科学可视化、计算机动画是计算机图形学领域内的三大热门研究方向。它们的技术核心都是三维真实感图形。无论是丝丝入扣的机械零件设计,惊心动魄的虚拟战场演习,还是如临其境的3D游戏,各种生动而精妙的图形应用使人目不暇接,计算机似乎为人们打开了一个五彩缤纷的第四维空间,而OpenGL三维图形正是这个“缤纷世界”的制造者之一。也就是说,开发出高性能的三维真实感图形是成功实现科学可视化、计算机动画和虚拟现实的关键!SGI公司在1992年7月发布的OpenGL,作为一个性能优越的图形应用程序设计界面(API),他恰好能实现高性能的三维图形功能,这使得科学计算可视化和仿真可视化技术发展迅速!而可视化系统不仅可以帮助技术人员形象直观地查看仿真结果,而且在一定程度上可以提高设计水平,减少错误的发生。因此计算机图形技术在各行各业和各个领域内得到越来越广泛的应用。有人说,20世纪是计算机多媒体技术发展的世纪,21世纪是虚拟现实飞速发展的世纪。因此,积极推动计算机图形领域的发展将对于我国的经济建设和科学研究具有重要的现实意义!而这一切都基于OpenGL的三维真实感图形生成。1.1、基于OpenGL的三维场景设计的意义三维图形在军事、航天、航空、医学、地质勘探、三维游戏、工业CAD和民用建筑等方面有着十分广泛的应用。它能更好更全面地说明事物、场景,给人一种更直观、更身临其境的感觉。与传统的地图、平面图、图纸相比有着极大的优点,它能使专业人员看的更简洁迅速,清晰明了,也能使非专业人员看的更直观易懂,真实可信。本设计就是做一个校园的三维场景,展现我校的校容校貌。目前、三维场景已经随处可见,如电脑的三维迷宫屏幕保护、楼盘销售演示、广告展示、电影特技、三维游戏世界、虚拟城市、小区规划图等等。三维场景已经伸入到各个角落,因为它确实给我们带来方便快捷,掌握这种技术已经是非常重要的,也是非常必要的。1.2、基于OpenGL的三维场景设计要解决的主要问题利用OpenGL提供的函数绘制一个可以在其中自由移动,旋转的三维场景,三维场景要象真实场景一样可以用三维坐标描述每个点,即使被遮挡的物体或平面也应该存在并能用图片纹理贴图,OpenGL没有提供直接读取图片文件的函数,可以用C语言读取,如读取成功,读取失败或找不到文件等,并加以控制和相应处理。场景中要有光源,点光源或环境光,这些OpenGL已经提供,能使场景中的物体有明暗效果。在场景中移动很旋转并非是对某一个物体操作,而是视全部物体为一个物体称画板,再用OpenGL提供的移动,旋转函数对画板操作,移动画板,视野在画板上也会移动,旋转也是一样,这样便实现在三维场景中的移动和旋转。三维场景的建模,贴图,光照,旋转和移动都解决才能象真实世界的场景一样,本程序是用C语言做主控程序调用OpenGL函数库,实现了三维场景的绘制,光照效果及视野在其中自由移动。二、OpenGL图形绘制及纹理贴图2.1、OpenGL数据类型和函数名OpenGL的库函数命名方式很有规律,了解这种规律后阅读和编写程序都比较容易方便。首先,每个库函数有前缀gl、glu、glx或aux,表示此函数分属于基本库、实用库、X窗口扩充库或辅助库,其后的函数名头字母大写,后缀是参数类型的简写,取i、f,参见下表。例:glVertex2i(2,4);glVertex3f(2.0,4.0,5.0);前缀数据类型相应C类型OpenGL类型i32-bit integerlongGLint,GLsizeif32-bit floating-pointfloatGLfloat,GLclampfd64-bit floating-pointdoubleGLdouble,GLclampdub8-bit unsigned integerunsigned charGLubyte,GLboolean2.2、OpenGL颜色设置几乎所有OpenGL应用目的都是在屏幕窗口内绘制彩色图形,所以颜色在OpenGL编程中占有很重要的地位。这里的颜色与绘画中的颜色概念不一样,它属于RGB颜色空间,只在显示器屏幕上显示。另外,屏幕窗口坐标是以象素为单位,因此组成图形的每个象素都有自己的颜色,而这种颜色值是通过对一系列OpenGL函数命令的处理最终计算出来的。OpenGL颜色模式一共有两个:RGB(RGBA)模式和颜色表模式(Color_Index Mode)。在RGB模式下,所有的颜色定义全用R、G、B三个值来表示,有时也加上Alpha值(与透明度有关),即RGBA模式。在颜色表模式下,每一个象素的颜色是用颜色表中的某个颜色索引值表示,而这个索引值指向了相应的R、G、B值。这样的一个表成为颜色映射(Color Map)。RGBA模式(RGBA Mode),可以用glColor*()来定义当前颜色。函数形式为:void glColor3b s i f d ub us ui( r, g, b);void glColor4b s i f d ub us ui( r, g, b, a);在前一种方式下,a值缺省为1.0,后一种Alpha值由用户自己设定,范围从0.0到1.0。同样,它也可用指针传递参数。另外,函数的第二个后缀的不同使用,其相应的参数值及范围不同,见下表9-1所示。虽然这些参数值不同,但实际上OpenGL已自动将它们映射在0.0到1.0或-1.0或范围之内。因此,灵活使用这些后缀,会给编程带来很大的方便。2.3、OpenGL图形绘制1). 绘制三角形glBegin(GL_TRIANGLES)意味着开始绘制三角形,然后接着写绘图代码,完成后用glEnd()结束绘制。glBegin(GL_TRIANGLES); / 绘制三角形glVertex3f( 0.0f, 1.0f, 0.0f); / 上顶点glVertex3f(-1.0f,-1.0f, 0.0f); / 左下glVertex3f( 1.0f,-1.0f, 0.0f); / 右下glEnd();/ 三角形绘制结束2). 绘制四边形glBegin(GL_QUADS)开始,用glEnd()结束绘制。glBegin(GL_QUADS); / 绘制正方形glVertex3f(-1.0f, 1.0f, 0.0f); / 左上glVertex3f( 1.0f, 1.0f, 0.0f); / 右上glVertex3f( 1.0f,-1.0f, 0.0f); / 左下glVertex3f(-1.0f,-1.0f, 0.0f); / 右下glEnd(); / 正方形绘制结束3). 绘制多边形glBegin(GL_POLYGON)开始, glEnd()结束绘制。glBegin(GL_ POLYGON); / 开始绘制多边形/要绘制的多边形顶点坐标glEnd(); /结束绘制2.4、读取位图文件一般来说,OpenGL中图象的高和宽必须是2的倍数。高和宽最少应该有64个像素,为了保持兼容,不能超过256个像素。所用图像的高和宽必须是64,128,256,否则程序不会成功调用该图片。1).建立一个文件句炳。句炳的作用是确定一个资源使得程序可以接受它。初始化中将句炳设为NULL。AUX_RGBImageRec *LoadBMP(char *Filename)/ 读取位图图象FILE *File=NULL;/ 文件句柄2).下面程序是检测文件名是否正确。有些人使用LoadBMP()时指定调用的文件,所以这里需要检测一下。if (!Filename)/ 确定文件名已给出return NULL;/ 如果文件名未给出则返回NULL3).如果给出了文件名,便检测此文件是否存在。下面一行语句功能是试着打开文件的程序代码File=fopen(Filename,r);/ 检测文件是否存在4).如果文件确实存在就可以将其打开。文件操作完成后用fclose(File)关闭文件。auxDIBImageLoad(Filename)功能是读取文件内容。if (File)/ 文件是否存在?fclose(File);/ 关闭文件return auxDIBImageLoad(Filename); /读取位图并返回一个指针5).如果文件不能打开将返回NULL,这意味着文件不能被读取。后面的程序将用作检测文件是否存在。如果文件不存在将退出程序并显示错误消息。return NULL;/如果调用文件失败则返回NULL2.5、位图转换成纹理1).下面一段代码用于读取bitmap图象数据并将其转换成纹理。int LoadGLTextures()/调用Bitmap并转换成纹理2).设置一个新变量Status。这个变量用于跟踪是否能读取bitmap并建立纹理。Status的默认值是FALSE(表示没有读取和建立)int Status=FALSE;/状态确定3).创建一个图像记录用于存储位图文件。这个记录将得到位图的宽高以及图像数据。AUX_RGBImageRec *TextureImage1;/为纹理创建存储空间4).清除图像记录使其为空。memset(TextureImage,0,sizeof(void *)*1); /将指针设为NULL5).读取位图并将其转换为纹理。TextureImage0=LoadBMP(pic/zuomenwei_000.bmp)将跳转到代码LoadBMP使pic目录下的zuomenwei_000.bmp将被读取,如果一切正常TextureImage0将存储图像数据,Status的值为TRUE,接下来就可以建立纹理了。if (TextureImage0=LoadBMP(pic/zuomenwei_000.bmp)Status=TRUE;/设Status为TRUE6).将图像数据读取到TextureImage0,之后将用这些数据建立纹理glGenTextures(1, &texture0);/创建纹理glBindTexture(GL_TEXTURE_2D, texture0);第一行告诉OpenGL希望创建一个纹理名字(增加数值可调用更多纹理)。第二行告诉OpenGL捆绑纹理名称texture0来形成纹理对象。2D纹理有高和宽。GlBindTexture的主要功能是为纹理数据分配纹理名称。由于这个原因,需要告诉OpenGL在&texture0有存储空间。在创建纹理时,它将存储在&texture0所对应的内存空间。7).建立确切的纹理glTexImage2D(GL_TEXTURE_2D, 0, 3, TextureImage0-sizeX, TextureImage0-sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE,TextureImage0-data);glTexImage2D告诉OpenGL纹理是2D纹理。0代表纹理的细节标准,通常均为0。3代表有几个数据组成,因为图像是由红色,绿色,蓝色数据组成,所以有3个数据项。TextureImage0-sizeX是纹理的宽度。如果知道这个值,直接赋值就可以了。但是计算机会很容易地得出这个值,TextureImage0-sizeY纹理的高度。0是边,通常都是0。GL_RGB告诉OpenGL图像数据是按红色,绿色,蓝色顺序组成的。GL_UNSIGNED_BYTE代表图像数据是由unsigned bytes构成。最后TextureImage0-data告诉OpenGL从那里得到纹理数据。由于这个原因它指向存在TextureImage0所记录的数据。8).下面这两行告诉OpenGL当图像大了时GL_TEXTURE_MIN_FILTER,或将原始纹理在屏幕上伸展开时,还有当纹理在屏幕上比原始纹理小了GL_TEXTURE_MAG_FILTER选择使用什么类型的过滤。为这两种情况可选择使用GL_LINEAR。这会使纹理在一定距离如靠近屏幕时看上去更平滑。使用GL_LINEAR要求处理器/显卡负担更多工作,如果系统较慢可以选择使用GL_NEAREST。纹理通过GL_NEAREST过滤,在其展开时会有块壮效果。也可以试着混合这两种过滤方法。当物体接近时作过滤处理,当物理远离时就没必要做了。代码如下:glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);9).现在要释放掉用于存储位图数据的内存。然后测试位图是否存储在TextureImage0。如果是,再测试是否有数据。如果有数据存储,要进行清除。最后释放图像结构以使任何使用的内存被释放。if (TextureImage0)/纹理是否存在if (TextureImage0-data)/纹理图象是否存在free(TextureImage0-data);/释放纹理图象所占用内存free(TextureImage0);/释放图象结构10).最后返回Status值。如果一切正确,变量Status的值为TRUE。如果有错误发生,Status的值为FALSE。return Status;/返回Status的值2.6、OpenGL纹理贴图如果忘记了允许纹理贴图,对象将成为单一的白色,所以要在void SceneInit函数中添加以下两行代码LoadGLTextures();/跳到处理调用位图并用此位图建立纹理的子程序glEnable(GL_TEXTURE_2D);/纹理被创建,并允许2D纹理贴图这样才能保证图片存在且格式正确的情况下被OpenGL调用。 为了恰当地将纹理贴在矩形上,需要确定纹理的右上角被正确的贴在矩形的右上角位置,纹理的各个角都相应的贴在矩形的角上。例:(-1,1.0) (1,1.0) (0,1)(1,1) 矩形纹理(-1,-1.0) (1,-1.0) (0,0)(1,0)glTexCoord2f的第一个值是X坐标。0.0f是纹理的左边。0.5f是纹理的中间。1.0f是纹理的右边。第二个值是Y坐标。0.0f是纹理的底部。1.0f是纹理的顶部。所以纹理左上坐标X是0.0f,Y是1.0f。矩形的坐标是(-1.0f,1.0f)。glBindTexture(GL_TEXTURE_2D,texture69); /绘制篮球场地板glBegin(GL_QUADS);glTexCoord2f( 0.0f, 0.0f);glVertex3f(-1.0f, -1.0f, 0.0f);glTexCoord2f( 1.0f, 0.0f);glVertex3f(1.0f, -1.0f, 0.0f);glTexCoord2f( 1.0f, 1.0f);glVertex3f(1.0f, 1.0f, 0.0f);glTexCoord2f( 0.0f, 1.0f);glVertex3f(-1.0f, 1.0f, 0.0f);glEnd();三、方案设计3.1、技术可行性可以用VC+6.0编译器C语言调用OpenGL建立Win32 Application,可以做任意的尺寸,任意的分辨率,任意的颜色深度。在空间画多边型,圆柱,圆盘,球体,添加颜色,导入位图,设置纹理贴图,移动坐标原点,旋转坐标系(均由OpenGL函数提供)。 根据已有技术,完全可以利用在空间绘制多边型在用贴图方式在场景中制作出楼房等物体,简单的一个楼房有六个面分别贴上相应的图片,这样楼房就真实地再现于场景中拉。利用函数绘制圆柱,圆盘,球体等绘制路灯等物体。因为OpenGL的坐标是相对的,可以用移动坐标原点来移动一个已经做好的物体,这样可以重用物体了(论文设计中的多个路灯,树木就是用这种方式绘制的)。路面等需要旋转物体后再添加到场景中,可以用旋转函数完成。最后要求用自由的视角观察场景中的物体,我们可以在绘制全部物体之前旋转,翻转,移动画板,再将全部物体绘制在画板上,这样就可以模拟出人物视角在场景中自由移动,旋转,翻转的效果。 设计中使用的贴图,图片可以从实地取材,本文选择的是用数码相机拍摄的方式取得大部分图片,之后用软件处理成需要的图片。校园中的建筑物的实际尺寸无从查找,是以目测,步量,等非精确数据取得,这样可以节省经济支出,又可以取得视觉上的真实感。3.2、方案实现的概要说明 用C语言编制窗口做场景的展示舞台,C语言编制画板来装载用OpenGL绘制的物体,主要要绘制的物体有校门、栅栏、路面、路标、路灯、草地、花坛、树木、排球场、网球场、篮球场、足球场、门球场、教一、教二、教三、行政楼、电教楼、信息工程学院、仪表楼、图书馆、机械楼、外语学院、石化楼、工会、体育馆、体育场看台、星光之家、教师公寓、学生宿舍、食堂、龙源公寓等均可以用绘制多边形加贴图方式完成。场景中用到的光源有点光源和环境光,OpenGL已经提供了相应的函数,场景的旋转和移动OpenGL也提供了函数,至于窗口的设置,键盘操作都由C语言完成。四、程序具体实现开始程序4.1、程序流程图是选择是否全屏否全屏初始化建立窗口舞台否清屏和清除深度缓冲区X轴旋转;Y轴旋转;在XYZ轴移动;绘制物体结束OpenGL接收键盘事件,移动旋转变量循环体底部导入位图是是否结束退出程序4.2、制作过程1)在VC+中建立一个新的项目。2)建立一个新的VC+ Win32 Application。3)选择 An empty project点完成,确定。4)接着要添加源文件之后设置连接OpenGL库文件。在VC+菜单中选择工程-设置。5)选择LINK选项,在“Object/Library Modules”下增加OpenGL所需的库文件。具体是OpenGL32.lib Glu32.lib Glaux.lib。做完这些后点击OK。然后就可以写OpenGL窗口程序了。所有源代码都放在刚刚添加的*.cpp文件里就可以了,附录为部分源文件。4.3、关键技术及解决办法4.3.1 基本光照效果1). 设置用于创建光照的数组本程序有两种不同的光源。第一种光照类型是环境光。环境光是一种并非来自特定方向的光。场景中所有的对象均会被环境光照亮。第二种光照类型称为散射光。散射光是一种由场景中对象的表面所反射的光源的光形成的。对象表面被光线直接照射的地方会非常亮,但其反射到周围光线会比较的暗。这会为3D对象建立一个很好的明暗效果。光源的建立方法与颜色的建立方法是相似的。如果第一个值为1.0f,另两个值为0.0f,所产生的光线的颜色为亮红色。最后一个值是alpha值。2). 为环境光赋值Glfloat LightAmbient=0.5f,0.5f,0.5f,1.0f;/环境光的值上面的代码,将为一个白色的环境光存储一个半亮度的值(0.5f)。由于所有的数值是0.5f,最终得到的光线强度值是在关闭亮度(黑色)和最亮亮度(白色)的一半位置。红绿蓝以相同的值混合将建立一个从黑(0.0f)到白(1.0f)的明暗效果。没有环境光,也没有漫反射光的地方会非常黑。3). 为散射光赋值Glfloat LightDiffuse=1.0f,1.0f,1.0f,1.0f;/散射光的值上面的代码,将为一个超亮的,全亮度的漫反射光赋值。所有的数值是1.0f。这意味着会得到所能达到的最亮的光。照在对象前面亮度很高的漫反射光会产生极佳的效果。4). 存储光照的位置最开始的3个数值与glTranslate的3个数值相同,分别表示X,Y,Z轴上移动的数值量。如果不能确切的看见光,这是由于在显示器屏幕前面的光源是浮动的。如果对象在显示器的屏幕之前,那么光源将在对象之后。如果对象不在显示器的平面出现,那么对象将不会被看到,所以光源在什么位置就不重要了。最后一个数的值为1.0f。这使OpenGL知道指定的坐标是光源的位置。代码如下:Glfloat LightPosition=0.0f,20.0f,2.0f,1.0f;/光照位置5). 设置光照环境光的取值被存在LightAmbient里。存在数组里的数据被使用(半强度的环境光)。代码如下:glLightfv(GL_LIGHT1,GL_AMBIENT,LightAmbient);/设置环境光6). 设置光线数据已给出的漫反射光的取值漫反射光的取值被存在LightDiffuse里。存在数组里的数据将被使用。glLightfv(GL_LIGHT1,GL_DIFFUSE,LightDiffuse);/设置漫反射光7). 设置光源的位置光源的位置存在LightPosition里。存在数组里的数据将被使用。glLightfv(GL_LIGHT1,GL_POSITION,LightPosition);/设置漫反射光8). 最后允许光源数据1这里还没允许GL_LIGHTING,所以还不会看到光。光源已被设置,并定好位置。GlEnable(GL_LIGHT1);/允许光源1这样才可以看到光线。4.3.2 使用混合功能实现透明的原理在OpenGL里简单的透明及一些特殊效果需要依赖某些类型的混合。1). 混合用于混合给出的像素颜色并和已经在屏幕上的像素一同被绘制。颜色如何被混合要基于颜色的alpha值。Alpha是颜色的第四个成分值通常最后定义。可以将alpha想象成物质的透明度。如果alpha值为零那么物质便是完全透明的,alpha值为1则意味着物质完全不透明。2). 修改SceneInit()代码段里的语句第一行作用是用50%alpha值(不透明)将对象的亮度绘制成全亮度。这意味着如果允许混合,对象将拥有50%的透明度。第二行设置混合的类型。(当alpha的值为0.0f时对象将完全透明。值为1.0f时将完全不透明。)glColor4f(1.0f,1.0f,1.0f,0.5f);/全亮度,50%alpha值glBlendFunc(GL_SRC_ALPHA,GL_ONE);/基于alpha值半透明的混合方式3). 下面的代码用来测试B是否被按下。如果被按下,计算机会检测混合方式是处于关闭还是打开状态。如果混合方式被打开,计算机会将它关闭。如果混合方式被关闭,计算机会将它打开。代码如下:case B:if(!bp)bp=TRUE;blend=!blend;if(blend)glEnable(GL_BLEND);/打开混合功能glDisable(GL_DEPTH_TEST);/关闭深度测试elseglDisable(GL_BLEND);/关闭混合功能glEnable(GL_DEPTH_TEST);/打开深度测试else bp=FALSE;break;4.3.3绘制圆柱,圆盘,球体。由于是二次几何物体,参数及方向与绘制平面不同,也可以用平面模拟,那样会很慢,且需要更多代码。1). 绘制圆柱:void gluCylinder(GLUquadricObj *qobj, GLdouble baseRadius,GLdouble topRadius, GLdouble height,GLint slices, GLint stacks)qobj由gluNewQuadric创建的二次对象。baseRadius圆柱体在Z=0平面内的半径。topRadius圆柱体在Z=height平面内的半径。height圆柱体的高度。slices圆柱体围绕Z轴方向的分段数。stacks圆柱体沿着Z轴方向的分段数。gluCylinder函数沿着Z轴方向绘制了一个圆柱体。圆柱体的底部在Z=0平面内,顶部在Z=height平面内。同球体一样,圆柱体围绕Z轴分割为许多段,并且沿着Z轴也分割为几段。需要注意的是,如果topRadius设置为零,那么该函数绘制的将是一个锥体。如果方向设置为GLU_OUTSIDE(使用gluQuadricOrientation)那么生成的任何法向量将指向Z轴的负方向,否则指向Z轴方向。2). 绘制球体:void gluSphere(GLUquadricObj *qobj, GLdouble radius,GLint slices, GLint stacks)qobj由gluNewQuadric创建的二次对象。Radius球体的半径。slices球体体围绕Z轴方向的分段数(相当于经线)。stacks球体体沿着Z轴方向的分段数(相当于纬线)。gluSphere函数绘制中心在坐标原点,半径为radius的球体,球体围绕Z轴分割为slices段,沿着Z轴分割为stacks段(相当于经线和纬线)。如果方向设置为GLU_OUTSIDE(使用gluQuadricOrientation)那么生成法向量将指向背离球体的中心,否则,指向球体的中心。3). 绘制圆盘:void gluDisk(GLUquadricObj *qobj, GLdouble innerRadius,GLdouble outerRadius, GLint slices, GLint loops)qobj由gluNewQuadric创建的二次对象。innerRadius圆盘的内部半径(可能为零)。outerRadius圆盘的外部半径。slices圆盘围绕Z轴方向的分段数。loops围绕原点圆盘分割的段数。gluDisk函数在Z=0平面内绘制圆盘。圆盘的外半径为outerRadius,内半径为innerRadius为0,那么不会产生圆洞。圆盘围绕Z轴分割为许多段,并分割为圆环段,这两个参数分别由slices和loops指定。圆盘的正Z面认为是外侧,这就意味着,如果方向设置为GLU_OUTSIDE,那么生成的任何法向量的指向均沿着Z轴。gluCylinder(gluNewQuadric(),1, 1, 8,12,1);/绘制圆柱gluSphere(gluNewQuadric(),0.15,12,12);/绘制球体gluDisk(gluNewQuadric(),p*0.45,p*0.55,12,12);/绘制圆盘4.3.4设置路灯开关程序中的路灯可以用键盘“G”全部点亮或熄灭,效果是场景中的建筑物边亮或边暗。设置全局变量bool goodlight,在接收键盘事件函数中添加case G:if(!goodlight)goodlight=TRUE;else goodlight=FALSE;break;在全部绘图之前添加if(!goodlight)glColor3f(0.8f,0.8f,0.8f);elseglColor3f(1.0f,1.0f,1.0f);glColor3f(1.0f,1.0f,1.0f);设置的颜色在通常情况下是会一直使用在每个绘制的物体上的,其中的参数RGB都相等,则表示为白色的明暗效果,R=G=B=1.0f为最亮的白色,R=G=B=0.0F为最暗的白色既黑色。这样也只能是当G按下时,场景全部变明或暗,绘制路灯的函数也要添加if (goodlight)glColor3f(1.0f,1.0f,1.0f);glBindTexture(GL_TEXTURE_2D, texture119);/路灯开关glBegin(GL_QUADS);glTexCoord2f(0.0f, 0.0f); glVertex3f(-0.1f,- 0.1f, 0.0f);glTexCoord2f(1.0f, 0.0f); glVertex3f( 0.1f,- 0.1f, 0.0f);glTexCoord2f(1.0f, 1.0f); glVertex3f( 0.1f, 0.1f, 0.0f);glTexCoord2f(0.0f, 1.0f); glVertex3f(-0.1f, 0.1f, 0.0f);glEnd();elseglColor3f(0.8f,0.8f,0.8f);这里多了一张图片119,它是纯白色的,因为颜色也和图片有关。如果我们贴上的是一张绿色的图片,那么对象的颜色将是亮绿色。这里用到的glColor3f(R=G=B)是用它调整图片的亮度,而不是用它来设置颜色。4.3.5 旋转,翻转。旋转和翻转在实现原理上是一样的,只不过是在不同的坐标轴上罢了。我们认为在Y轴上的旋转是旋转,在X轴上是翻转,当然也可以在Z轴上旋转,动作是一样的。本文的程序里没有做轴的旋转,只做了XY轴上的旋转。函数实现:glRotatef(rquad,1.0f,0.0f,0.0f)/X轴旋转rquad角度glRotatef(rquad,0.0f,1.0f,0.0f)/Y轴旋转rquad角度当rquad为正数时,旋转方向是正对着坐标轴箭头所指方向的逆时针方向,也可以写成这样:glRotatef(rquad,0.0f,-1.0f,0.0f)/Y轴旋转rquad角度这表示向顺时针方向旋转,角度rquad可以定义成您需要的数据类型,如int,float, Glint, GLdouble等,也可以写成这样:glRotatef(rquad,1.0f,-1.0f,0.0f)/旋转rquad角度表示在X轴,-Y轴同时旋转,不过很少用到。4.3.6 移动。移动是指将坐标原点相对原坐标原点的移动,屏幕坐标如下Y原点 XZ原点是在平面的中心,XY平面与屏幕重合,Z是垂直屏幕向外的。本文的移动是这样实现的:const float piover180=0.0174532925f;/角度变弧度GLfloat xtrans=-xpos;GLfloat ztrans=-zpos;GLfloat ytrans=-walkbias-0.25f;GLfloat sceneroty=360.0f-yrot;glRotatef(lookupdown,1.0f,0,0);/X翻转glRotatef(sceneroty,0,1.0f,0);/y旋转glTranslatef(xtrans+xup,ytrans+yup,ztrans+zup);/移动/全部绘图/接收键盘事件case VK_PRIOR: /page uplookupdown -= 1.0f;break;/当page up键按下在X轴旋转lookupdown-= 1.0f角度case VK_UP:/方向键的向上键xpos-=q* (float)sin(heading*piover180)*0.5f;zpos -=q* (float)cos(heading*piover180)*0.5f;break;/在Y轴有旋转,所以XZ都有移动case VK_LEFT:/ 方向键的向左键heading +=2.0f;yrot = heading;break; /当左键键按下在Y轴旋转yrot +=2.0f;角度case A: /键盘A键,向左移动,xup +=q* (float)cos(-heading*piover180)*0.25f;zup +=q* (float)sin(-heading*piover180)*0.25f;break;/在Y轴有旋转,所以XZ都有移动case W: /键盘W键,向上移动,yup -=q*0.4f;break;/Y轴上移动yup -=q*0.4f;个单位五实现结果分析及总结本程序在以下环境调试通过。硬件:CY2.0GHZ/256M/80G/FX5200 64MB/865PE.pro软件:Windows XP/VC+6.05.1、键盘控制说明:方向键为前进/后退/左/右转Page up 仰角观察Page down 俯角观察B:透明纹理开/关L:环境光/散射光G:路灯电源开/关A:向左移动D:向右移动W:垂直上移S:垂直下移5.2、运行结果截图图5.2.1校门及第二教学楼图5.2.2校门一角图5.2.3体育馆图5.2.4篮球场及第一教学楼其它运行结果截图请参见封二、封三。5.3、运行结果讨论及分析1. 由于程序是以调用位图文件为主.并一次性调入内存,小于256M内存的PC可能会慢一些,但不会出错。2. 在位图不存在或程序找不到的情况下不会报错,原贴图的地方是白色或程序中设置的颜色。3. 单独改动图片不会影响程序,尺寸或格式不对,程序中不会显示该图片。4. 程序调用图片时和图片方向是有关的,反方向调用图片时,显示的是图片的背面。5. 程序提供全屏,窗口选择,可以在两种方下显示,窗口方式提供窗口拖拽变形及最大化、最小化。6. 程序中与屏幕相距超过100个单位的物体时不会在屏幕上显示,这是OpenGL的特性,不是程序错误,两张图片过近时会有闪烁现象,这也是OpenGL计算出的效果,只能尽量避免。7. 路灯开时,场景变亮并非灯光照射而是将场景的亮度由原来的80%提高到100%。8. 散射光效果开关是L键。程序中只有一个点光源。在校门前上方。9. 程序里没有用过多的光照效果,由于时间关系图片本身处理的也不尽好,可进一步改进。六.结束语本设计实现了基于OpenGL的三维图形场景的绘制。所再现的是辽宁石油化工大学的校园,校园中大部分景物已经用数码相机取的图片,但有地方没有照片,是用其它图片代替而成,使整个场景逊色不少!而且没有过多的光照效果,只有自然光和散射光,能使整个场景看起的更清晰,程序中的散射光效果还可以,还有透视效果,也许是图片处理的不够好,这些效果都没有想象中的好,由于时间关系,目前完成到此,以后会继续深入学习这个很好用的函数库OpenGL。从本程序就可以看出OpenGL的强大功能,其实本程序只用了几个很常用的函数,就能把整个校园场景控制在程序中。自然也存在很多不足之处,本人必定会在以后的学习,工作中继续学习OpenGL和使用它,让OpenGL给我们带来更多更好的视觉效果。七.致谢特别感谢我的指导老师纪玉波先生,在百忙之中不厌其烦地给我技术指导和鼓励。感谢网络管理中心潘一老师,工会蔡老师提供数码相机。另外感谢所有支持我的同学和朋友,谢谢他们的帮助和鼓励。八.参考书目1 万斌. VC+ OpenGL DirectX三维动画编程宝典M,北京希望电子出版社. 2003.12 李颖. OpenGL函数与范例解析手册M, 国防工业出版社. 2002.13 尚游. OpenGL图形程序设计指南M, 中国水利水电出版社. 2001.104 和平鸽工作室. OpenGL高级编程与可视化系统开发M,中国水利水电出版社. 2003.15 保文星,何丰. 利用OpenGL生成物体的三维透视景观图J,云南民族学院学报(自然科学版). 2001, 第10卷第4期, PP477-4806 王莹莹. 在VC中利用0penGL实现动态效果图象的技巧J. 微型电脑应用. 2002, 第18卷第6期, PP50-
展开阅读全文
相关资源
正为您匹配相似的精品文档
相关搜索

最新文档


当前位置:首页 > 办公文档 > 工作计划


copyright@ 2023-2025  zhuangpeitu.com 装配图网版权所有   联系电话:18123376007

备案号:ICP2024067431-1 川公网安备51140202000466号


本站为文档C2C交易模式,即用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知装配图网,我们立即给予删除!