• 2.03 MB
  • 2022-04-22 11:16:02 发布

基于OPENGL的飞机飞行动画模拟设计电子信息工程毕业论文.docx

  • 67页
  • 当前文档由用户上传发布,收益归属用户
  1. 1、本文档共5页,可阅读全部内容。
  2. 2、本文档内容版权归属内容提供方,所产生的收益全部归内容提供方所有。如果您对本文有版权争议,可选择认领,认领后既往收益都归您。
  3. 3、本文档由用户上传,本站不保证质量和数量令人满意,可能有诸多瑕疵,付费之前,请仔细先通过免费阅读内容等途径辨别内容交易风险。如存在严重挂羊头卖狗肉之情形,可联系本站下载客服投诉处理。
  4. 文档侵权举报电话:19940600175。
'华侨大学2014届本科生毕业论文基于OpenGL的飞机飞行动画模拟设计顾礼书题目:基于OPENGL的飞机飞行动画模拟设计学院:信息科学与工程学院专业:电子信息工程年级:2011级学号:1115103015姓名:顾礼书指导老师:邱应强2015年05月 华侨大学2014届本科生毕业论文基于OpenGL的飞机飞行动画模拟设计顾礼书摘要随着计算机图形学的不断发展,计算机对图形的表示、计算、处理及显示的相关原理及算法得到了显著的突破。其实现从最开始的加强信息的传递与理解,到后来的能够与计算机动画与虚拟现实相结合,大大地促进了各领域的应用与发展。本文意在通过对基于OpenGL的飞机飞行动画模拟设计来说明计算机如何实现科学计算可视化,并与计算机动画、虚拟现实相结合从而为人们呈现出一个绚丽的第四维空间。本文主要说明了如何在VC++的平台中,实现基于OpenGL实现3D飞机飞行动画的模拟设计。本文主要完成以下任务:简述VC++及OpenGL应用的基本原理、发展及其关键技术、如何利用VC++构建OpenGL的程序框架、系统各模块功能的实现与联立并能够在自动漫游基础上可以通过键盘响应实现人机交互漫游,最后给出了系统测试情况与总结。基于上述,最终完成在VC++的平台中,实现基于OpenGL的3D飞机飞行动画的模拟设计得以验证说明计算机实现科学计算可视化的过程,初窥OpenGL在计算机动画和虚拟现实两大发展方向中的巨大作用。关键词:VC++;OpenGL;科学计算可视化;计算机动画;虚拟现实 华侨大学2014届本科生毕业论文基于OpenGL的飞机飞行动画模拟设计顾礼书ABSTRACTWiththedevelopmentofcomputergraphics,thereisagreatsignificantbreakthroughintherelatedtheoryandalgorithmthatreferstotheexpression,calculation,processinganddisplayofgraphsbycomputer.Therealizationgreatlypromotedtheapplicationanddevelopmentofmanyareaswhichthepurposeistobeabletobecombinedwithvisualrealitynowthantostrengthenthetransmissionandunderstandingwithinformation.ThepaperintendstoexplainhowtoachievetheVisualizationinScientificComputing,andhowtobecombinedwithComputerAnimationandvisualrealitytoshowacolorfulforthdimensionspaceforpeoplebythedesignofplaneisflyingwhichbasesontheOpenGL.Inthispaper,itillustrateshowtoachievethedesignofanimationthatthe3DplaneisflyingintheplatformofVC++,whichbasesontheOpenGL.Inthispaper,theprimarytaskistosketchthefundamental,developmentandkeytechnologyoftheapplicationwithVC++andOpenGL,howtoconstructtheframeoftheOpenGL’sapplicationwithVC++andhowtoachievetherealizationofmodulesofthedesigntobeabletoachieveinteractiveroamingwiththeresponseofkeywhichbaseontheautoroaming.Infinal,thepapermakesthetestofthedesignandsummary.Infinal,basedontheseresults,thispaperprovedtheprocessoftheachievingofVisualizationinScientificComputingandthegreatmeaningofOpenGLthatdoseinthedevelopmentofComputerAnimationandvisualrealitybyachievingthedesignofplaneisflyingintheplatformofVC++.Keywords:VC++,OpenGL,VisualizationinScientificComputing,ComputerAnimation,visualreality 华侨大学2014届本科生毕业论文基于OpenGL的飞机飞行动画模拟设计顾礼书目录第一章绪论11.1前言11.2OpenGL国内外研究现状11.3本课题研究的主要内容及目的2第二章OpenGL简述及其程序框架建立42.1什么是OpenGL42.2三维图形开发标准42.3OpenGL图形的实现方式52.3.1设备上下文DC与渲染上下文RC52.3.2OpenGL像素格式设置52.3.3OpenGL图形处理流程、主要绘制方式及运行方式72.4OpenGL库的组成及基本数据类型82.5VisualC++简述92.6MFC环境下OpenGL单文档应用程序框架102.6.1构建OpenGL程序框架102.6.2MFC简述112.6.3构建MFC环境下OpenGL单文档应用程序框架11第三章课题实现的关键技术163.1坐标变换163.2光照173.3纹理映射183.3.1Mip贴图183.3.2融合213.4雾效223.5帧缓存技术与动画23第四章基于OpenGL的飞机飞行动画设计254.1设计主流程图254.2地形的初始化与绘制264.2.1地形设计方案选择及其原理264.2.2随机高程数据生成的地形设计26 华侨大学2014届本科生毕业论文基于OpenGL的飞机飞行动画模拟设计顾礼书4.3绘制天空294.4太阳的绘制304.5水面的绘制314.6飞机模型输入324.7飞机尾焰33第五章动画效果实现375.1动画效果方案选择375.2各场景与模型之间的联立375.2.1关键变量设置375.2.2按键响应395.2.3场景漫游及模型变换结合变量的具体实现过程405.3设计结果测试40第六章总结42参考文献43附录44附录一:[英文文献]44附录二:[中文翻译]53致谢62 华侨大学2014届本科生毕业论文基于OpenGL的飞机飞行动画模拟设计顾礼书第一章绪论1.1前言众所周知,现如今我们已经步入了信息时代,随着计算机的诞生,我们在信息时代的道路上越走越远,面临的挑战也越来越多。计算机图形学作为计算机学科领域中的重要一部分,吸引了许多著名的学者对其做出了巨大的贡献,使其得到了长足的发展。从二维到三维,从静态到动态,从非实时到实时,我们欣喜地看到了这样的变化。计算机图形学不仅是计算机发展的重要支撑之一,更肩负着带动及融合其他众多领域发展的重大使命。计算机图形学的研究内容十分广泛,其中包括:图形硬件、图形标准、图形交互技术、光栅图形生成算法、曲线曲面造型、实体造型、真实感图形计算与显示算法,以及科学计算可视化、计算机动画、自然景物仿真、虚拟现实等。当实时3D图形概念的提出及实现后,便引发了众多的开发人员及学者对其进行研究,结合计算机图形学的科学计算可视化、计算机动画及虚拟现实等研究内容,使实时3D图形概念能够应用在许多领域,且范围越来越广,其中包括交互式游戏和模拟乃至数据的可视化显示(用于科学、医学或商业用途),甚至,越来越多的高科技领域通过虚拟现实来进行系统开发。在过去,在许多关于航天航空及军事的系统开发研制中,例如飞行系统的研制通常是依靠飞行实验来实现的。但是这种的传统实体实验无疑令实验的耗费增大、周期延长,不利于该系统的研制于开发。随着计算机图形的发展,这种传统实验方式在很大程度上可以通过基于OpenGL的可视化虚拟现实仿真技术来取代,以此消除传统实验所带来的缺点,科学计算可视化的成果还令飞机等航天工具的飞行动态与航迹更加地清晰直观。而OpenGL作为计算机图形学发展的产物之一,它可以与各种设计平台相结合,在科学计算可视化、计算机动画及虚拟现实的研究领域当中扮演着功能强大、最具发现前景的实现工具的角色。1.2OpenGL国内外研究现状OpenGL最初是以SGI公司开发的IRISGL形态呈现的。IRISGL是个2D图形函数库,随着时代的进步与人们需求的提升,IRISGL逐渐演化成为SGI高端IRIS图形工作站所使用的3D编程API。根据最初的设计,IRISGL并没有被定性为具有顶点风格的几何图形处理接口,这就迫使SGI对其进行改进,通过对IRISGL的移植性进行改进和提高,于是,OpenGL就诞生了。我们都知道,如果某家厂商能够控制标准,那么这个标准就谈不上标准,而SGI很早便认识到软件能够促进计算机的销售,而包括IBM、Intel、Microsoft等在内的厂商都意62 华侨大学2014届本科生毕业论文基于OpenGL的飞机飞行动画模拟设计顾礼书识到了这一点,于是OpenGL体系结构审核委员会(ARB,OpenGLArchitectureReiviewBoard)就诞生了。OpenGL规范1.0版正式于1992年7月1日出台。随着时间的流逝,ARB又陆续增加了一些新成员,其中有许多来自PC硬件社区。在他们每隔四年一次的会议中,他们会针对OpenGL的规范维护及提高提出相应的应对与计划,对其标准进行升级。但近年来,由于某些原因,SGI的业务不断下滑。2006年,SGI将OpenGL标准的控制权交给了TheKhronosGroup,这是一个新的工作组,是一个由内部成员提供资金的行业协会,致力于开放媒体标准的创建和维护。大多数ARB成员已经成为Khronos的成员,因此这个变动并没有产生太大的波折。Khronos小组继续发展和升级OpenGL以及它的姐妹API-OpenGLES。发展至今,OpenGL以两种形式存在。第一种形式是行业标准,是由《OpenGL规范》所定义的。这个规范用非常完整和专业的术语描述了OpenGL。它完整地定义了OpenGLAPI,以及OpenGL的整个状态机,并描述了可以共同操作的各种特性。第二种形式就是OpenGL实现,软件开发人员和客户可以使用它生成实时图形。如果厂商希望创建并销售OpenGL实现,首先必须从Khronos小组获得OpenGL许可。此外,厂商的实现必须通过OpenGL一致性测试。在OpenGL的成长期时,因为各厂商之间API战争的爆发,SGI撤去对OpenGL的支持,使OpenGL濒临绝境。但有趣的是,没有了SGI的支持,OpenGL反而开始焕发出了它自己的生命力。得到过SGI的一些帮助的硬件生产商继续用新的驱动程序支持OpenGL。当OpenGL再次广泛地在消费者硬件平台上得到应用时,开发人员事实上已经不再需要SGI或其他任何人告诉他们OpenGL的优点。OpenGL易于使用,并且已经出现多年。这意味着人们可以利用大量的现有文档、示例程序、SigGraph论文等。于是,OpenGL开始走向繁荣。当OpenGL被越来越多的开发人员使用,我们越发清晰地认识到实现主导这个领域的是开发人员。OpenGL使许多开发人员可以更好地满足顾客的需求,这是它能够兴旺的根本原因。由于OpenGL无法替代的优越性,使其越来越流行,不仅成为了Windows特定渲染技术的替代者,而且现在在市场上的主要操作系统和硬件设备都迫不及待地加强对其的支持。今天,OpenGL显然已经被广泛地认可为二维图形与三维图形的行业内标准的API。这种推动力把OpenGL带入了一个可以预见的未来,使它成为了范围更广的应用程序和硬件平台API的选择。1.3本课题研究的主要内容及目的本课题研究的主要内容为模拟一架飞机在一个地形上空飞行的全过程其中需要完成62 华侨大学2014届本科生毕业论文基于OpenGL的飞机飞行动画模拟设计顾礼书的任务包括:(1)地形的初始化与地形的绘制;(2)天空太阳的绘制;(3)雾化效果与太阳光效果;(4)飞机的绘制;(5)飞机尾焰的绘制;(6)飞机飞行动力学的仿真计算。最终在在建立的合适窗口内,用户可能通过键盘按键响应,与飞行动画实现交互,控制飞机的飞行速度、方向等来观察飞机的飞行变化。本课题研究的目的在于:通过本次设计,向大家讲述如何将科学计算可视化,并以计算机动画呈现在大家眼前,初窥虚拟现实的技术内涵,最后得以说明OpenGL为实现工具的实时3D图形在科学计算可视化、计算机动画及虚拟现实中的巨大作用。62 华侨大学2014届本科生毕业论文基于OpenGL的飞机飞行动画模拟设计顾礼书第二章OpenGL简述及其程序框架建立2.1什么是OpenGLOpenGL是一个性能优越的应用程序编程接口,相当与MFC库概念类似的库。OpenGL拥有高度的可移植性,它为开发人员提供了丰富的图形函数,令开发人员能够快速地设计出三维图形或三维图形交互软件。当我们基于各种开发平台设计实时3D图形时,通过调用OpenGL提供的函数进行编程,最终得出一个应用程序,但是并不能说它是“OpenGL程序”,因为OpenGL只是一个函数库,只是开发人员在开发程序的时候运用了这个库。就好比,我们利用MFC库编写了一个应用程序,但是我们不能称这个程序为MFC程序一样。OpenGL纯粹地致力与图形开发,所以OpenGL中的函数的功能都是围绕图形设计与处理的,其他与图形无关的功能实现(如设备操作、文件读取等)由调用其他库的函数来实现。2.2三维图形开发标准随着三维图形应用的极速发展,市场上的三维图形工具相继推出,但是却没有任何一种工具能在交互式三维图形建模能力与编程方便性上能够与OpenGL相媲美的。一个完整窗口系统的OpenGL图形处理系统的结构分为:(1)最底层图形硬件(2)操作系统(3)窗口系统(4)OpenGL(5)应用软件其结构如图2-1所示。62 华侨大学2014届本科生毕业论文基于OpenGL的飞机飞行动画模拟设计顾礼书开发工具和应用窗口系统操作系统图形硬件OpenInventor,SoftImage3DOpenGLX-Windows,WindowsNT…Unix,Windows9x/NT…AGC-3D,SGI-XZ图2-1OpenGL运行平台和结构2.3OpenGL图形的实现方式2.3.1设备上下文DC与渲染上下文RCOpenGL的绘图方式特点表现为:(1)OpenGL采用的是渲染上下文RC(RenderContext,又称渲染描述表)绘图(2)OpenGL使用的是特殊的像素格式在Windows中,是通过一种叫做设备上下文(DeviceContext,又称设备描述表)进行GDI绘制的。就好比一个画家在画画,这个设备上下文就好比画家画画前的一切准备工作设置,其中包括了画板、画纸、画笔、背景颜色、绘图技巧等。同样的,在使用OpenGL函数进行绘图时也类似地设定一个渲染上下文RC。如同DC一样,RC中也储存了OpenGL绘制的一些初始设置,如像素格式、缓存形式、光照等。若某个程序使用的是单个RC,则在应用程序窗口创立的同时,我们创建RC,当窗口销毁时我们再删除它,释放资源。当我们为OpenGL建立一个RC后,我们要将其设置为现行RC,若我们没有为OpenGL建立现行RC,则所有的绘图命令将无法被执行。在OpenGL中建立一个RC后,必需为其联立一个相应的DC,才能调用设备完成绘制映射。并且,当RC被设定为现行后,只要该现行RC一直存在,则与其相联系的DC资源一直被占用,直到现行RC被删除。2.3.2OpenGL像素格式设置像素格式是OpenGL窗口的重要属性,它包括是否使用双缓冲、颜色位数和类型以及62 华侨大学2014届本科生毕业论文基于OpenGL的飞机飞行动画模拟设计顾礼书深度位数等。像素格式可由Windows系统定义的所谓像素格式描述子结构来定义(PIXELF-ORMATDESCRIPTOR),该结构定义在windows.h中。其结构形式如下:62 华侨大学2014届本科生毕业论文基于OpenGL的飞机飞行动画模拟设计顾礼书表2-1像素格式属性标识符解释PFD_DRAW_TO_BITMAP支持内存中绘制位图PFD_DRAW_TO_WINDOW支持屏幕绘图PFD_DOUBLEBUFFER支持双缓冲PFD_CENERIC_FORMAT指定GDI支持的像素格式PFD_NEED_PALETTE指定需要逻辑调色板PFD_NEED_SYSTEM_PALETTE指定需要硬件调色板PFD_STEREONT不支持PFD_SUPPORT_OPENGL支持OpenGLPFD_SUPPORT_GDI支持GDI,此时不可使用PFD_DOUBLEBUFFER2.3.3OpenGL图形处理流程、主要绘制方式及运行方式OpenGL的工作流程如下图所示:求值器对顶点操作及几何要素装配光栅化对像素段操作帧缓冲区显示列表像素操作纹理装配顶点数据像素数据输入像素数据输出图2-2OpenGL的工作流程图上述流程图可简述为:首先以基本图元(包括点、线、多边形、图形等)按照要求的三维模型的数学描述进行建模,之后将模型放在所要求的位置,调整视点(观察者的空间位置)及可视范围,接着按照要求对模型场景进行3D描述,并通过光栅化将顶点数据转化为二维图像,再将其坐标转换为相应的窗口坐标,最后通过帧缓冲区的交换可实现动画效果。OpenGL的绘制方式主要有:(1)线框绘制方式;(2)深度优先线框绘制方式;(3)反走样线框绘制方式;(4)平面明暗处理方式;(5)光学明暗处理方式;(6)加阴影和纹理的方式;(7)运动模糊绘制方式等。OpenGL主要有以下3种运行方式:1、硬件加速方式OpenGL大部分功能实现由硬件执行,只有少量的功能实现由操作系统实现。2、三维图形加速模式62 华侨大学2014届本科生毕业论文基于OpenGL的飞机飞行动画模拟设计顾礼书硬件承担复杂的图形操作,而其余的功能则由操作系统实现。3、纯软件模式完全由操作系统利用软件模拟方式运行OpenGL。2.4OpenGL库的组成及基本数据类型前文已讲述过OpenGL相当与一个函数库,所以它的库函数大致可以分为6类,表2-2给出了OpenGL包含的库类型、函数量、函数名前缀及其主要功能。表2-2OpenGL库类型、库内函数量、函数名前缀及其功能库名函数量函数名前缀功能OpenGL核心库115gl主要用于常规的、核心的图形处理OpenGL实用库43glu主要用于实现一些较为复杂的操作,如:坐标变换、纹理、绘制二次图形等OpenGL辅助库31aux主要用于窗口管理、输入输出处理以及绘制一些简单三维物体OpenGL工具库30glut主要用于基于窗口的控制,如:多窗口绘制、空消息、定时器及绘制一些较复杂物体Windows专用库16wgl要用于连接OpenGL和Windows95/NT,以弥补OpenGL在文本方面的不足Win32API函数库6无主要用于处理像素存储格式和双帧缓存OpenGL基本数据类型如表2-3所示,OpenGL中定义的数据类型均以GL开头。OpenGL中还定义了大量的符号常数,均以GL_开头,全部采用了大写字母,常数的各部分之间采用了下划线分隔。例如:GL_POINTS(绘制单个顶点集)、GL_LINES(绘制多级独立的双顶点线段)等。表2-3命令后缀和参数数据类型字符相应的C语言类型OpenGL数据类型定义bsignedcharGLbytesshortGLshortiintGlint,GLsizeiffloatGLfloat,GLclampfddoubleGLdouble,GLclampd62 华侨大学2014届本科生毕业论文基于OpenGL的飞机飞行动画模拟设计顾礼书ubunsignedcharGLubyte,GLbooleanusunsighedshortGLshortuiunsignedintGLuint,GLenum,GLbitfieldvoidGLvoid2.5VisualC++简述VisualC++是由Microsoft公司推出的基于Windows系统的可视化集成开发环境。同其他的可视化集成开发环境一样,VisualC++集程序的代码编辑、编译、连接和调度等功能于一体,再加上Microsoft公司为VisualC++开发的功能强大的MFC(MicrosoftFoundationClass,微软基础类库),使VisualC++成为开发Windows应用程序的最佳选择[2]。VisualC++提供了对面向对象技术的支持,利用类将与用户界面设计有关的WindowsAPI函数封闭起来,通过MFC类库的方式提供给开发人员,大大提高了程序代码的可重用性;VisualC++还提供了功能强大的应用程序生成向导(AppWizard),能够帮助用户自动生成一个应用程序框架,用户只要在该框架的适当位置添加代码就可以得到一个满意的应用程序[2]。利用VisualC++建立一个应用程序的基本流程如下图所示:开始执行终止程序初始化应用程序初始化并创建应用程序窗口消息是否为WM_QUIT应用程序中是否处理了此信息处理消息转送消息给窗口进行默认处理是是否否图2-3Windows应用程序的基本流程62 华侨大学2014届本科生毕业论文基于OpenGL的飞机飞行动画模拟设计顾礼书2.6MFC环境下OpenGL单文档应用程序框架2.6.1构建OpenGL程序框架实现OpenGL编程同编写其他应用程序的基本流程是一致的,都必须先为想要实现的功能的代码构建一个基于窗口设计的框架,而实现OpenGL绘制的重点在于采用渲染上下文RC绘图,所以框架的重心在于渲染上下文RC的设置、RC与设备上下文DC的联系等,因此构建OpenGL程序框架的基本流程如图所示:开始定义窗口类设置窗口类型获得窗口客户区设备上下文句柄m_pDC;将RC与DC联系起来将RC设置为现行RC注册窗口类设置定时器设置RC;设置逻辑调色板初始化OpenGL设置绘制三维图形消息是否为WM_QUIT结束程序注销窗口释放DC和RC删除RC删除DC是否删除定时器图2-4构建OpenGL程序框架的基本流程图62 华侨大学2014届本科生毕业论文基于OpenGL的飞机飞行动画模拟设计顾礼书2.6.2MFC简述随着计算机高级语言的发展,诞生了许多高级语言,不同语言之间各有特色,解决问题的思想方法各有差异,而C++则是通过构造能够映射问题的对象模型,获取对象的状态信息,从而得到输出实现问题的解决。因此C++主要不同与C语言之处便是提出了类与对象的定义,令开发人员能够更加容易快捷地进行交互式程序的设计。通过类与对象的设计,可以将许多基本控制函数封装起来,通过集成平台形成多种多样的程序框架,或是形成便于记忆使用的工具库。说到工具库,就不得不提及MFC。MFC(MicrosoftFoundationClass)是微软基础类库的简称,是微软公司设计提供的一个C++类库,封装了大部分的windowsAPI函数。并且MFC不仅是一个类库,还是一个框架。由2.5所述,我们可以通过VisualC++应用程序生成向导(AppWizard)自动生成MFC环境下的单文档应用程序框架,省去窗口设计等过程,只要在相应的位置添加相应的代码就能够很好地进行OpenGL编程,更好地将重心放在课题的研究上。2.6.3构建MFC环境下OpenGL单文档应用程序框架构建构建MFC环境下OpenGL单文档应用程序框架的主要步骤如下:1、在单文档窗口的创建过程中,设置好显示的像素格式,并按要求设置好窗口的属性和风格;2、首先获得Windows设备描述表DC,然后将其与事先设置好的OpenGL渲染上下文RC联系起来;3、调用OpenGL命令进行图形绘制;4、退出OpenGL图形窗口时,解除RC与DC的联系,并将之释放。其具体过程如下:(1)启动VC,在【File】菜单中,选择New,在Project选项中选择“MFCAppWizard(exe)”,新建一个单文档工程,名称为MYPLANE。(2)添加OpenGL库。从【Project】菜单中选择【Settings…】,在弹出的“ProjectSetting”对话框中选择Link标签,在“Object/libraryModule”编辑框内加入“opengl32.libglu32.libglaux.lib”,单击OK完成库的添加。(3)添加消息响应函数。利用MFCClassWizard为CMYPLANEView类添加消息WM_CRETE、WM_DESTROY、WM_SIZE和WM_TIMER的响应函数。(4)修改StdAfx.h文件,加入GL库的头文件,这样就可以在工程的任何地方调用62 华侨大学2014届本科生毕业论文基于OpenGL的飞机飞行动画模拟设计顾礼书OpenGL函数了。代码修改如下://包含有关OpenGL函数的头文件#include#include#include#include(5)修改MYPLANEView.h文件,为其增加如下成员变量与函数。代码修改如下://添加成员函数与成员变量BOOLRenderScene();//绘制场景BOOLSetupPixelFormat(void);//设置像素格式VoidSetLogicalPalette(void);//设置逻辑调色板BOOLInitializeOpenGL(CDC*pDC);//初始化OpenGL场景HGLRCm_hRC;//OpenGL绘制描述表HPALETTEm_hPalette;//OpenGL调色板CDC*m_pDC;//OpenGL设备描述表(6)修改MYPLANEView.cpp文件,修改该文件中的CMYPLANEView::PreCreateWindow()函数,此函数即在预备创建窗口前设置好窗口类型与风格。代码修改如下:BOOLCMYPLANEView::PreCreateWindow(CREATESTRUCT&cs){…//设置窗口类型cs.style|=WS_CLIPCHILDREN|WS_CLIPSIBLINGS;/*窗口类型必须设置成WS_CLIPCHILDREN|WS_CLIPSIBLINGS的原因是一旦设定了一个DC的位图格式,该DC所联系的窗口的位图格式也随之设定,否则该窗口若含有子窗口或联系窗口,而这些窗口的位图格式没有设成与对应RC一致的格式的话,OpenGL在窗口上面绘图就容易出错[1]。*/…}(7)继续修改该文件中的CMYPLANEView::OnDraw()函数:voidCMYPLANEView::OnDraw(CDC*pDC){…RenderScene();//绘制场景…}(8)修改该文件中的CMYPLANEView::OnCreate()函数,此函数对应流程图即为在创建窗口时获得窗口句柄并设置定时器及初始化OpenGL场景。代码修改如下:intCMYPLANEView::OnCreate(LPCREATESTRUCTlpCreateStruct)62 华侨大学2014届本科生毕业论文基于OpenGL的飞机飞行动画模拟设计顾礼书{…//初始化OpenGL和设置定时器m_pDC=newCClientDC(this);SetTimer(1,20,NULL);InitializeOpenGL(m_pDC);…}(9)修改该文件中的CMYPLANEView::OnDestroy()函数,此函数对应流程图即为在窗口销毁时,释放DC与RC,并将之删除,最后删除定时器。代码修改如下:voidCMYPLANEView::OnDestroy(){…//删除调色板和渲染上下文、定时器::wglMakeCurrent(0,0);::wglDeleteContext(m_hRC);if(m_hPalette)DeleteObject(m_hPalette);if(m_pDC){deletem_pDC;}KillTimer(1);…}(10)修改该文件中的CMYPLANEView::OnSize()函数,此函数的作用是当窗口改变时,会对应地改变投影方式与视口大小,使得场景不受窗口影响正确地显示在屏幕上。代码修改如下:voidCMYPLANEView::OnSize(UINTnType,intcx,intcy){…glViewport(0,0,cx,cy);//窗口缩放时的视口变换函数…}(11)修改该文件中的CMYPLANEView::OnSize()函数,此函数的作用是当窗口的客户区无效时重新绘制客户区。例如:如果一个窗口被另外一个窗口遮住,那么被遮住的部分是无效的,此时客户区被判定为无效,需要重绘。voidCMYPLANEView::OnTimer(UINTnIDEvent){…62 华侨大学2014届本科生毕业论文基于OpenGL的飞机飞行动画模拟设计顾礼书Invalidate(FALSE);//添加定时器响应函数和场景更新函数…}(12)在文件中添加逻辑调色板函数CMYPLANEView::SetLogicalPalette()(具体代码见附录)与像素格式设置函数CMYPLANEView::SetupPixelFormat(),CMYPLANEView::S-etupPixelFormat()的具体代码如下:BOOLCMYPLANEView::SetupPixelFormat(){PIXELFORMATDESCRIPTORpfd={sizeof(PIXELFORMATDESCRIPTOR),//pfd结构的大小1,//版本号PFD_DRAW_TO_WINDOW|//支持在窗口中绘图PFD_SUPPORT_OPENGL|//支持OpenGLPFD_DOUBLEBUFFER,//双缓存模式PFD_TYPE_RGBA,//RGBA颜色模式24,//24位颜色深度0,0,0,0,0,0,//忽略颜色位0,//没有非透明度缓存0,//忽略移位位0,//无累加缓存0,0,0,0,//忽略累加位32,//32位深度缓存0,//无模板缓存0,//无辅助缓存PFD_MAIN_PLANE,//主层0,//保留0,0,0//忽略层,可见性和损毁掩模};intpixelformat;pixelformat=::ChoosePixelFormat(m_pDC->GetSafeHdc(),&pfd);//选择像素格式::SetPixelFormat(m_pDC->GetSafeHdc(),pixelformat,&pfd);//设置像素格式if(pfd.dwFlags&PFD_NEED_PALETTE)SetLogicalPalette();//设置逻辑调色板…}(13)在文件中添加初始化OpenGL场景函数MYPLANEView::InitializeOpenGL(),其具体代码如下:BOOLCMYPLANEView::InitializeOpenGL(CDC*pDC){62 华侨大学2014届本科生毕业论文基于OpenGL的飞机飞行动画模拟设计顾礼书m_pDC=pDC;SetupPixelFormat();//生成绘制描述表m_hRC=::wglCreateContext(m_pDC->GetSafeHdc());//置当前绘制描述表::wglMakeCurrent(m_pDC->GetSafeHdc(),m_hRC);…}(14)最后在文件中添加场景绘制与渲染函数CMYPLANEView::RenderScene(),并在该函数中写入想要实现的绘制场景代码,经过编译就可以实现在窗口客户区的绘制。以上代码是基于Win32的OpenGL应用程序构台框架,这些都是一些固定的用法,如果没有特殊要求的话,我们可以直接使用,并不需要对其进行修改。62 华侨大学2014届本科生毕业论文基于OpenGL的飞机飞行动画模拟设计顾礼书第三章课题实现的关键技术3.1坐标变换如同我们所知道的所有物质都是由原子组成的,而所有的原子又是由质子、中子及电子组成的。同理,在OpenGL中建立的复杂模型也是由更小、更简单的形状组成的,然后根据模型的要求按照特定的方式进行排列组合,最终形成了复杂的模型。在OpenGL中这样最小形状的存在我们称为图元,如:点、线、多边形等,而最小的图元即是点。了解了这些概念后,我们就可以开始着手对现实的物体进行建模并将其搬移到计算机屏幕上了,但是我们知道计算机屏幕上只能表现二维图像,并且计算机只能处理数据,所以我们要将三维图形数据化,才能通过计算机对三维图形进行操作,以此实现我们想要的结果。那么我们如何对三维图形进行正确的数据描述并进行转换,最终使其映射到屏幕上呢?于是我们发现了坐标系是联系数据与三维图形的唯一纽带。首先,我们确定一个参考点,这个参考点可以虚拟假设成人眼坐标,之后便可以在三维空间中建立虚拟的三维坐标,以此对模型的顶点进行坐标描述,当完成对三维图形的坐标描述之后,我们也就完成了对三维图形的数据化。接下来我们就可以将三维图形映射到二维平面上了,我们通过投影来完成上述映射。投影分为透视投影与正交投影两种。我们把投影平面所在的三维空间称为三维视景体,在透视投影中,视景体是一个棱台状,因此形成的效果是远大近小;在下次投影中,视景体的形状则是一个长方形,投影的结果无论远近都是一样的大小,而只有在视景体内的三维物体才能投影到二维平面上[2]。并且我们知道计算机设备多种多样,我们要将投影后的三维图形映射到计算机屏幕上还需要令其坐标适应计算机屏幕的坐标,所以我们还要进一步对三维图形的坐标进行变换,这个过程由视图处理矩阵来完成。因为OpenGL是基于窗口设计的,所以最终我们是在一个窗口内看到我们设计的三维场景,所以我们还需要对坐标进行最后的变换,将坐标转换成为适应窗口的窗口坐标,而这个过程我们称之为视口映射,在这个过程当中,我们可以决定窗口对三维场景的取景范围,映射比例等等,完成这个过程是以视口变换矩阵来实现的。下图给出了坐标变换的基本流程。几何变换矩阵投影变换矩阵视图处理矩阵视口变换矩阵[x,y,z,w]人眼坐标裁剪坐标设备坐标窗口坐标图3-1坐标变换基本流程62 华侨大学2014届本科生毕业论文基于OpenGL的飞机飞行动画模拟设计顾礼书当我得到了三维图形的坐标信息之后,我们就可以通过矩阵变换的形式对顶点坐标进行操作实现三维图形的移动、旋转、缩放等,还可以通过三维图形的坐标信息对其进行纹理贴图、材质设置等,以此来实现更好的3D描述,使设计的三维图形更加立体。在OpenGL中,我们使用其提供的glMatrixMode()函数,通过传递不同的设置参数,可以分别对视图模型矩阵、投影矩阵、纹理矩阵等进行操作,并且可以利用glPushMatrix()函数与glPopMatrix()这两个函数将矩阵保存到堆栈中或从堆栈中读取,这样大大提高了设计与排版的灵活性。通过设置动态变量对矩阵进行变换,再利用双缓存就可以实现三维图形的动态效果。所以说坐标变换是所有后续关键技术的基础,是重中之重。3.2光照三维图形建立之后,要令其产生3D效果还需要一系列的透视和艺术技巧,而光照是不可或缺的。如果没有光照,所制作的三维图形就没有立体感,和二维图形基本没有区别。没有光照,我们甚至都看不到图形。当现实中的物体被光照射时,该物体吸收光中的部分光线,剩下的光线则被反射。这些反射的光进入了人眼,从而使得人们能够感知到物体的各种特性,如形状、颜色或其他细节等。我们称从光源射向物体的光为入射光,从物体表面反射回的光为反射光。OpenGL用一种近似的光照模型模拟现实世界的光照效果。在模型中,光源当物体吸收和反射光时起作用。不同的材质有不同的属性,有的会自己发光,有的在各个方向上发散部分入射光,有的则像镜子一样在特定的方向高强度地反射入射光。在OpenGL的简化光照模型中,设定光照由4个成分组成,分别为:(1)辐射光:辐射光是指发光体直接发出的光,所以辐射光不受其他光源影响;(2)环境光:环境光是一种被环境多次反射从而失去方向的光,所以环境光看起来就像来自于所有的方向。当它照射在一个物体的表面时,它将在所有的方向上等量反射;(3)漫反射光:漫反射光来自一个特定的方向,它指的是那些被照射物体表面的反射光中均匀地向各个方向反射出的光;(4)镜面反射光:镜面反射光具有很强的方向性,当它照射物体表面时,以等于入射角的反射角进行反射,并且当视点与物体上某点的夹角与光线的入射角相近时,我们将会看到该表面形成了一个高亮区域,我们称其为亮点。在实际的应用中,4部分独立计算并最后回到一起。在OpenGL中,由函数glLight(GLenumlight,GLenumpname,TYPEparam)来定义一个光源。表3-1给出了pname的值及其功能和缺省值。62 华侨大学2014届本科生毕业论文基于OpenGL的飞机飞行动画模拟设计顾礼书表3-1pname的值及其功能和缺省值pname功能缺省值GL_AMBIENT环境光分量的强度(0.0,0.0,0.0,0.0)GL_DIFFUSE漫反射光分量的强度(1.0,1.0,1.0,1.0)GL_SPECULAR镜面反射光分量的强度(1.0,1.0,1.0,1.0)GL_POSITION光源位置(0.0,0.0,0.0,0.0)GL_SPOT_DIRECTION光源聚光方向(0.0,0.0,-1.0)GL_SPOT_EXPONENT光源的聚光指数0.0GL_SPOT_CUTOFF聚光的截至角180.0GL_CONSTANT_ATTENUATION光的常数衰减因子1.0GL_LINEAR_STTENUATION光的线性衰减因子0.0GL_QUADRATIC_ATTENUATION光的二次衰减因子0.0在本设计中,对于光照做如下设置:GLfloatLightAmbient[]={0.5f,0.5f,0.5f,1.0f};GLfloatLightDiffuse[]={1.0f,1.0f,1.0f,1.0f};GLfloatLightSpecular[]={0.5f,0.5f,0.5f,1.0f};GLfloatLightPosition[]={0.0f,0.0f,0.0f,1.0f};glLightfv(GL_LIGHT1,GL_AMBIENT,LightAmbient);//设置光源的环境光glLightfv(GL_LIGHT1,GL_DIFFUSE,LightDiffuse);//设置光源的漫反射光glLightfv(GL_LIGHT1,GL_SPECULAR,LightSpecular);//设置光源的镜面反射光glLightfv(GL_LIGHT1,GL_POSITION,LightPosition);//设置光源的位置glEnable(GL_LIGHT1);//开启光源3.3纹理映射3.3.1Mip贴图纹理映射是增强三维图形真实感的重要技术之一。我们通过运用纹理映射,可以使制作真实感的二维或三维图形变得更加容易、简单,省去大量花在设计图形表面纹理上的时间。好比我们画了一个长方体,只有在六个面上贴上石头纹理,它看上去就跟现实中切割好的石头一样了。纹理映射在本课题的作用主要在于模拟地形、天空及太阳。OpenGL中提供了一系列相关的纹理操作函数,我们通过调用它们来实现对纹理的操作,最终实现其映射。纹理映射只能工作在RGB模式下,进行纹理映射的基本步骤如下:(1)定义纹理(2)控制纹理62 华侨大学2014届本科生毕业论文基于OpenGL的飞机飞行动画模拟设计顾礼书(3)映射方式(4)纹理坐标为了提高整个场景的渲染性能,并改善场景的显示质量,在本课题的设计中采用了Mip贴图的多重纹理技术,所以说Mip贴图是一种功能强大的纹理技巧。Mip贴图纹理由一系列纹理图像组成,其中每个图像的大小都是前面图像大小的一半,图3-2给出了这样的例子。图3-2一系列mip贴图图像在OpenGL中通过gluBuild2DMipmaps(GLenumtarget,GLintinternalForrnat,Glintwidth,GLenumheight,GLenumtype,Glintlevel,Glintbase,Glintmax,constvoid*data)函数来建立Mip贴图,其中,target指定目标纹理,这里必须是GL_TEXTURE_2D,internalFornat指定颜色成分,width指定图像的宽度,height指定图像的高度,type指定告诉OpenGL图像数据由什么类型的颜色数据组成,level指定data参数所指定的mip层,base指定mip的最小层,max指定mip的最大层,data指定用于生成mip贴图的图像数据。在OpenGL中通过glTexParameteri(GLenumtarget,GLenumpname,constTYPE*pnames)来定义纹理参数(过滤方式),以达到反走样的目的。其中,target指定目标纹理,这里必须是GL_TEXTURE_2D,下面给出pname参数列表及pnames的取值。表3-2参数pname的取值范围参数pnamepnames的取值GL_TEXTURE_MAG_FILTERGL_NEARESTGL_LINEARGL_TEXTURE_MIN_FILTERGL_NEARESTGL_LINEARGL_NEAREST_MIPMAP_NEARESTGL_NEAREST_MIPMAP_LINEARGL_LINEAR_MIPMAP_NEARESTGL_LINEAR_MIPMAP_LINEAR上述表格中pnames的取值功能分别为:●GL_NEAREST:返回与纹理化的像素中点距离最近的纹理元素的值。62 华侨大学2014届本科生毕业论文基于OpenGL的飞机飞行动画模拟设计顾礼书●GL_LINEAR:返回最靠近纹理化像素中点的4个纹理元素的加权平均值。●GL_NEAREST_MIPMAP_NEAREST:选择一个与纹理化的像素在尺寸上最匹配的mipmap,并用CL_NEAREST标准产生一个纹理值。●GL_NEAREST_MIPMAP_LINEAR:选择一个与纹理化的像素在尺寸上最匹配的mipmap,,并用GL_LINEAR标准产生一个纹理值。●GL_LINEAR_MIPMAP_NEAREST选择2个与纹理化的像素在尺寸上最匹配的mipmap,并用CL_NEAREST标准从每个mipmap中产生一个纹理值。最后的纹理值是这2个值的加权平均值。●GL_LINEAR_MIPMAP_LINEAR:选择2个与纹理化的像素在尺寸上最匹配的mipmap,并用GL_LINEAR标准从每个mipmap中产生一个纹理值。最后的纹理值是这2个值的加权平均值。在OpenGL中,通过auxDIBImageLord()函数来读取外部图形文件的宽度、调度及数据,通过glGenTexture(GLsizein,GLuint*textures)函数为图像数据分配索引,通过glBindTexture(GLenumtarget,GLuinttexture)函数启用某个纹理。那么如何将纹理正确地映射到几何图形上呢?首先我们要了解纹理贴图中的纹理单元并不是按照我们通常所理解的内存位置进行排列的,而是根据一种抽象的纹理坐标排列的。并且我们将纹理坐标设定为浮点数,使其范围在[0.01.0]之间,纹理坐标系各轴被命名为s、t、r、q,支持从一维至三维的纹理坐标,并提供一种方法对坐标进行缩放。图3-3显示了一维纹理至三维纹理在纹理坐标系中排列的方式。基于上述理解,我们就可以通过glTexCoord2f(GLints,GLintt)函数将纹理坐标应用到每个顶点上。之后,OpenGL就会根据具体要进行贴图的对象大小对纹理进行放大或缩放,将纹理贴到该对象上,而放大与缩放过程当中便通过上述提到过的glTexParameteri(GLenumtarget,GLenumpname,constTYPE*pnames)函数来过滤纹理,防止纹理在映射的过程当中走样,图3-4给出一个纹理映射的示例。图3-3纹理单元在纹理中的位置62 华侨大学2014届本科生毕业论文基于OpenGL的飞机飞行动画模拟设计顾礼书图3-4一个简单的纹理映射示例综上所述,建立一个mipmap贴图的基本流程如下图所示:开始结束读取文件获取索引设置纹理参数建立mip贴图图3-5建立mip贴图的基本流程3.3.2融合三维图形经历了单层的纹理映射后,虽然在真实感上得到了很大的提升,但是还远远不够,在OpenGL中还提供更多的特殊效果来提升三维图形的真实感,如本节所讲述的融合特效。融合,即将两种颜色的各个分量按照一定的比例混合在一起,在OpenGL中设定alpha(不透明度)为其混合比例,也就是RGBA值中的A,称(1-A)为透明度。举个例子说明,当我们透过红色的玻璃看黄色的花时,假设这块玻璃的不透明度为80%,这样我们在玻璃上看到的融合后的颜色是由80%的红色及20%的花的颜色构成。在这个例子中,定义花的颜色的比例为源因子为(Sr,Sg,Sb,Sa),红色玻璃颜色的比例为目的因子(Dr,Dg,Db,Da),源颜色为(Rs,Gs,Bs,As),目的颜色为(Rd,Gd,Bd,Ad),则最终呈现在红色玻璃上的颜色为:62 华侨大学2014届本科生毕业论文基于OpenGL的飞机飞行动画模拟设计顾礼书(RsSr+RdDr,GsSg+GdDg,BsSb+BdDb,AsSa+AdDa)最终每个颜色分量的计算结果被限定在[0.01.0]范围内。OpenGL提供了多种多样的融合方式选择,我们可以根据不同的设计需要进行选择,通过glBlendFunc(GLenumsfactor,GLenumdfactor)函数进行选择,sfactor指定源融合因子,dfactor指定目的融合因子。表3-3给出了源和目的的融合因子及其含义。表3-3源和目的融合因子及其含义取值常量相关因子计算后融合因子GL_ZERO源或目的(0,0,0,0)GL_ONE源或目的(1,1,1,1)GL_DST_COLOR源(Rd,Gd,Bd,Ad)GL_SRC_COLOR目的(Rs,Gs,Bs,As)GL_ONE_MINUS_DST_COLOR源(1,1,1,1)-(Rd,Gd,Bd,Ad)GL_ONE_MINUS_SRC_COLOR目的(1,1,1,1)-(Rs,Gs,Bs,As)GL_SRC_ALPHA源或目的(As,As,As,As)GL_ONE_MINUS_SRC_ALPHA源或目的(1,1,1,1)-(As,As,As,As)GL_DST_ALPHA源或目的(Ad,Ad,Ad,Ad)GL_ONE_MINUS_DST_ALPHA源或目的(1,1,1,1)-(Ad,Ad,Ad,Ad)GL_SRC_ALPHA_SATURATE源(f,f,f,f)-min(As,1-As)设置完毕后,最后通过调用函数glEnable(GL_BLEND)及glDisable(GL_BLEND)来启用或关闭融合特效。3.4雾效雾是OpenGL为了实现三维图形更好的3D描述所支持的特效之一,并且非常容易使用。雾效的使用有着许多优点,首先它不仅可以令整个场景看起来更真实,而且还可以提高整体的绘制的速度。OpenGL是通过物体在场景中与观察者的距离修正其颜色,由此产生雾化效果。在OpenGL中提供三种雾的方式,如表3-3所述。其中,Start为雾的起始位置,end为雾的终止位置,d为雾的稠密程度,c为像素的位置。表3-4OpenGL所支持的3种雾的方式雾模式雾方程式GL_LINEARf=(end-c)/(end-start)GL_EXPf=exp(-d*c)GL_EXP2f=exp(-(d*c)2)在OpenGL中通过glFog{fi}[v](GLenumpname,GLenumparams)对雾效进行设置,表3-5给出了pname的取值及其含义。62 华侨大学2014届本科生毕业论文基于OpenGL的飞机飞行动画模拟设计顾礼书表3-5pname的取值及其含义pname含义GL_FOG_MODE参数params可以接受3个符号常量:GL_LINEAR,GL_EXP,GL_EXP2,缺省的雾化模式是GL_EXP。GL_FOG_DENSITY参数params指定用于双指数雾化方程的雾浓度d。GL_FOG_START参数params指定参数start。GL_FOG_END参数params指定参数end。GL_FOG_INDEX参数params指定雾的颜色索引值i。GL_FOG_COLOR参数params指定雾的颜色值。综上所述,雾化的步骤可以简单地分为如下步骤:(1)选择雾的方式,使用GL_FOG_MODE作为pname参数的值,并选择常量GL_EXP、GL_EXP2、GL_LINEAR之一作为param参数的值调用glFog()函数。(2)定义雾的特征,其特征包括雾的浓度与颜色。对于线性雾,还可以指定雾的起点与终点。此外,还可以通过glHint(GL_FOG_HINT,…)函数指定是按像素(GL_NICEST)还是按顶点(GL_FASTEST)进行雾的计算。(3)启动雾。调用glEnable(GL_FOG)启动雾。关闭则通过调用glDisable(GL_FOG)。在本课题中的雾化设置如下所示:GLuintfogMode[]={GL_EXP,GL_EXP2,GL_LINEAR};//保存三种雾的模式GLuintfogfilter=0;//当前使用的雾的模式GLfloatfogColor[4]={fog_r,fog_g,fog_b,1};//雾的颜色glFogi(GL_FOG_MODE,fogMode[2]);//设置雾的模式glFogfv(GL_FOG_COLOR,fogColor);//设置雾的颜色glFogf(GL_FOG_DENSITY,0.294f);//设置雾的浓度glHint(GL_FOG_HINT,GL_NICEST);//雾的工作方式glFogf(GL_FOG_START,10.0f);//设置雾的开始深度glFogf(GL_FOG_END,visual_distance);//设置雾的结束深度glEnable(GL_FOG);//使用雾3.5帧缓存技术与动画当图形被绘制到屏幕上时,它都是由像素组成的。其中的每个像素都带有固定的信息,如:颜色、深度等。因此在绘制图形时,我们必须在内存中保存这些信息,我们将内存中均匀保存这些信息的内存块称为缓存区或缓存。为了保证存储数据的一致性,使程序工作更加有条不紊,我们分配不同的缓存区存储不同的像素信息。在给定的相同的缓存区中,62 华侨大学2014届本科生毕业论文基于OpenGL的飞机飞行动画模拟设计顾礼书每个像素拥有一致的数据格式。我们将所有这些缓存称为帧缓存。OpenGL帖缓存由四种缓存组成,分别为:(1)颜色缓存:颜色缓存是我们将要绘制图形时,内存为其分配的缓存,其中存储的内容可以是颜色索引的数据形式,也可以是RGB颜色数据形式;(2)深度缓存:深度缓存指的是存储像素深度信息的缓存。我们将观测者与观测物体之间的距离定义为深度,沿着一条视线,具有较小深度值的像素将取代深度值比它大的像素,意味着远的物体被近的物体所掩盖。深度缓存也称为Z-buffer。在实际应用中,x、y是指定屏幕上水平与垂直距离的坐标轴,而z则是指定眼睛到屏幕的垂直距离的坐标轴;(3)模板缓存:模板缓存可以保持屏幕上某些部位的图形不变,而其他部位仍然可以进行图形绘制;(4)累积缓存:累积缓存中存储的数据同颜色缓存存储的数据一样,都是颜色数据。但它与颜色缓存的不同之处在于,累积缓存只能存储RGB颜色数据。在OpenGL中通过以下函数glClearColor(GLclampfred,GLclampfgreen,GLclampfblue,GLclampfalpha)、glClearIndex(GLfloatc)、glClearDepth(GLclampddepth)、glClearStencil(GLints)、glClearAccum(GLflaotret,GLfloatgreen,GLfloatblue,GLfloatalpha)分别对颜色缓存、索引缓存、尝试缓存、模板缓存及累积缓存进行指定清除值,再通过函数glClear(GLbitfieldmask)进行不同参数的传递来实现对缓存区的清除,其中mask可以是以下这些位逻辑的“或”:GL_COLOR_BUFFER_BIT、GL_DEPTH_BUFFER_BIT、GL_STENCIL_BUFFER_BIT、GL_ACCUM_BUFFER_BIT。OpenGL为用户提供了双缓存,可以用其来制作动画。在双缓存的作用下,我们利用前台显示缓存内容中的一帧画面,后台则绘制下一帧画面,当绘制完毕后,将后台缓存内容搬移到前台进行显示,之后后台继续绘制下一帧画面,以此循环则可以我们便看到了连续的画面,实现了动画的效果。在OpenGL中设计这样的动画程序很简单,只需要掌握一个重点函数,即auxSwapBuffers(void),而利用MFC设计OpenGL时则是通过SwapBuffers()函数来实现。62 华侨大学2014届本科生毕业论文基于OpenGL的飞机飞行动画模拟设计顾礼书第四章基于OpenGL的飞机飞行动画设计4.1设计主流程图开始初始化OpenGL场景初始化地形高度数据初始化粒子系统数据结束Wireframe=1绘制地形框架装载飞机模型数据计算绘制地形绘制天空water=1绘制水面绘制飞机绘制太阳消息是否为WM_QUIT按键响应模块YYNNYN图4-1程序主流程图62 华侨大学2014届本科生毕业论文基于OpenGL的飞机飞行动画模拟设计顾礼书4.2地形的初始化与绘制4.2.1地形设计方案选择及其原理当我们想到什么是自然界中最复杂的场景时,无疑,我们会想到地形。因此国内外计算机图形学领域将三维真实感地形的绘制作为重点研究对象之一。随着计算机技术和相关学科理论的发展,三维电子地图的绘制经历了三个阶段,分别为:(1)线划地形图;(2)实体型地形图(3)三维真实感地形图。按照本课题研究的主要内容,我们对地形的真实感要求并不高,主要侧重与场景的漫游实现,从而达到动画效果,因此我们选择模拟地形来实现地形设计。对于模拟地形,我们一般采用的方法为:(1)随机调和数据生成;(2)分形高程数据生成。分形高程数据的生成方法主要是利用分形的自相似原理。如图4-2所示,可以看出随着分形的深入,越来越逼近真实的地形。(a)(b)(c)图4-2(a)低程度分形地形;(b)中等程度分形地形;(c)高度分形地形生成随机高程数据生成地形的方法步骤如下:(1)随机生成一些特征点的高程数据。(2)在特征点之间采用曲线拟合的方法生成比较平滑的地形。(3)在网格上根据随机高程数据进行着色或通过纹理映射将外部纹理贴上去。为了更好地实现场景的漫游,本设计最终选择实时性更高的随机高程数据生成的方法进行地形的设计。4.2.2随机高程数据生成的地形设计在本设计中,使用循环语句嵌套,在循环中调用如下公式生成随机高程地形数据:…for(i=0;i250?激活所有粒子,给予粒子完整生命周期1随机生成淡化速度值初始化粒子的y、z坐标位置及z轴方向加速度随机生成x、y、z轴方向矢量值xi、yi、zi结束loop250?按照速度变化glow的值绘制尾焰光晕线框纹理映射绘制粒子线框纹理映射loop++是是否否图4-19粒子系统绘制基本流程(a)不带光晕尾焰(b)带光晕尾焰图4-20飞机尾焰绘制仿真结果62 华侨大学2014届本科生毕业论文基于OpenGL的飞机飞行动画模拟设计顾礼书第五章动画效果实现5.1动画效果方案选择经过上几章的论述,我们已经做好了一切准备工作,通过双缓存我们就可以实现最终的动画效果。接下来的工作便是选定一个方案将帧与帧通过定时器联系起来,最终完成飞机飞行动画设计,并通过MFC环境下提供的按键响应函数,在自动漫游的基础上通过键盘实现交互漫游。在OpenGL中要实现场景漫游可以通过以下两种方案实现:1、通过调用gluLookAt()函数设置动态的相机在世界坐标的位置、动态的相机镜头对准的物体在世界坐标的位置及动态的相机向上的方向在世界坐标中的方向来实现场景移动,但是这样对于场景的实时实现来说相对比较复杂,所以并不采取这种方案进行设计。2、通过移动场景来实现漫游,这种方案只需要简单地调用函数glRotatef()及glTranslatef()就可以实现,我们只需要做好动态参数的设置与传递就可以将各种场景与模型联立起来统一进行变换,具有实时性高,实现简单,动画效果好等优点,所以在本设计中采取这种方案实现动画设计。在本设计开始的地形初始时,设置了500*500的数组用以存放随机高程地形数据,为了实现场景的漫游,将可视范围设置为200*200,在搬移场景时,遍历地形而飞机不动亦或者在原地旋转,以飞机为参照点给人一种飞机在飞行的错觉。我们可以想像一下,现在我们处在一个半球形顶的大空间内,在上面绘着天空白云的纹理,正前方还有一个大太阳,而我们坐在一个飞机里,地板就像跑步机一样一直在向后滚动,这时候我们好像坐着飞机往前飞一样。当机体突然向左倾斜,机头向左摆动,此时我们的地板向我们的左后方向滚动,太阳向右偏移了,这时我们就会感觉像坐着飞机向左飞了,这就是本设计的核心思想。5.2各场景与模型之间的联立5.2.1关键变量设置接下来我们就只需要按照5.1所述过程进行参数变量的设计,就能够实现各场景与模型之间的联立了。表5-1给出了一些主要变量、计算公式及其功能。62 华侨大学2014届本科生毕业论文基于OpenGL的飞机飞行动画模拟设计顾礼书表5-1部分主要变量、公式及其功能变量名(意义)计算公式作用Throttle(变速因子)Throttle+=(_Throttle-Throttle/10)*0.9借用节流阀的概念,通过键盘响应对_Throttle的值进行设计,最终计算得出相应的加速或减速因子值Speed(合速度)Speed+=Speedi/1000Speedi由Throttle计算得出,Speed在原有基础上对其进行加减,以达到加速减速的效果XP(x轴方向速度)XP=-sin(heading*piover180)*Speed通过合速度计算出飞机在x轴方向上的速度YP(y轴方向速度)YP=-sin(pitch*piover180)*Speed通过合速度计算出飞机在y轴方向上的速度ZP(z轴方向速度)ZP=-cos(heading*piover180)*Speed通过合速度计算出飞机在z轴方向上的速度XPOS(场景x轴中心位置)XPOS+=XP/30根据飞机的x轴方向速度变更x轴中心位置YPOS(场景y轴中心位置)YPOS+=YP/30根据飞机的y轴方向速度变更y轴中心位置ZPOS(场景z轴中心位置)ZPOS+=ZP/30根据飞机的z轴方向速度变更z轴中心位置zprot(飞机绕z轴旋转角度)zprot±=5/(|Speed|+1)(1)zprot=zprot*0.935(2)(1)是飞机在按键响应下根据速度进行旋转变向;(2)是当没有按键响应时飞机重新变回平稳飞行状态sceneroty(场景绕y轴旋转角度)sceneroty=360-zprot/3当飞机变向移动时,场景应该朝相反方向旋转yaw(飞机绕y轴旋转角度)yaw+=zprot/5(1)yaw*=.95f(2)(1)是飞机在按键响应下根据速度进行旋转变向;(2)是当没有按键响应时飞机重新变回平稳飞行状态pitch(飞机绕x轴旋转角度)pitch±=15/(|Speed|+1)是飞机在按键响应下根据速度进行上下旋转变向62 华侨大学2014届本科生毕业论文基于OpenGL的飞机飞行动画模拟设计顾礼书5.2.2按键响应如前文所述,通过CMYPLANEView::OnKeyDown()函数实现交互漫游,图5-2给出按键响应的程序流程图。开始输入nCharnChar=0~9?nChar=’←’?nChar=’→’?nChar=’↑’?nChar=’↓’?nChar=’l’&’L’?nChar=’w’&’W’?结束对变速因子进行设置对飞机绕y、z轴旋转角度设置zprot+=5/(|Speed|+1)对飞机绕y、z轴旋转角度设置zprot+=5/(|Speed|+1)对飞机绕x轴旋转角度设置pitch+=15/(|Speed|+1)对飞机绕x轴旋转角度设置pitch-=15/(|Speed|+1)对绘制水面标志进行设置water=!water对绘制模式标志进行设置wireframe=!wireframe是是是是是是是否否否否否否图5-2按键响应程序流程图62 华侨大学2014届本科生毕业论文基于OpenGL的飞机飞行动画模拟设计顾礼书5.2.3场景漫游及模型变换结合变量的具体实现过程其实归根结底在OpenGL中的一切操作都是针对坐标的操作,动画的实现也是对坐标的操作,只要令坐标移动起来,令坐标系旋转起来。在5.2.1中已设置了可视范围的中心坐标(XPOS,YPOS,ZPOS),这时通过代码在[-XPOS-100–XPOS+100]、[-ZPOS-100–ZPOS+100]的范围内绘制地形。绘制完毕后,只要调用glTranslatef(XPOS,YPOS,ZPOS)将场景搬移到可视范围内,之后重置当前矩阵,绘制飞机与尾焰。当飞机上飞时,将场景向下搬移场景;当飞机下飞时,向上搬移场景;当飞机向左飞行时,同时向右、向后搬移场景,并调用glRotatef(sceneroty,0,1,0)旋转场景,重置矩阵绘制飞行与尾焰时调用glRotatef(yaw,0,1,0)、glRotatef(zprot*15,0,0,1)、glRotatef(pitch,1,0,0)旋转飞机,最后通过定时器响应、按键响应更新变量,就实现了场景漫游与模型变换。5.3设计结果测试图5-3显示了完整三维场景下的飞机沿直线飞机的动画效果。图5-3完整场景下飞机飞行动画当按下“←”、“→”时,飞机向左或向右飞行,图5-4给出了向左向右飞行的比对图。(a)飞机向左飞行(b)飞机向右飞机图5-4飞机变向飞行绘制结果62 华侨大学2014届本科生毕业论文基于OpenGL的飞机飞行动画模拟设计顾礼书当按下“L”时,可以选择是否绘制水面,图5-5给出了其对比图。(a)无水面绘制(b)有水面绘制图5-5地形变换绘制结果当按下“W”时,可以选择绘制模式是线框绘制还是纹理绘制,图5-6给出了其对比图。(a)线框绘制(b)纹理绘制图5-6场景绘制模式变换结果经过测试,本设计如实完成了在自动漫游基础上可以通过键盘响应实现人机交互漫游,最终完成了基于OpenGL的飞机飞行动画模拟设计。62 华侨大学2014届本科生毕业论文基于OpenGL的飞机飞行动画模拟设计顾礼书第六章总结随着时代的进步,各种领域研究的深入,许多人发现信息的传递和理解变得犹为的艰难,并随着计算机的逐步发展,人们的这种需求在不断地得到扩大与丰富,计算机图形学得以快速地发展,通过科学计算可视化、计算机动画与虚拟现实的结合,来满足人们的需求,甚至有时超出了人们的预想。为此,市场上出现许多三维图形工具意图实现这样的过程与结合,其中OpenGL所体现的高度的可靠性、可扩展性、可伸缩性令其成为众多工具中的佼佼者,并且它易于使用、灵活性高。基于上述,本文通过针对基于OpenGL的飞机飞行动画模拟设计完成如下方面工作:(1)通过对课题的反复思索,并不断地阅读相关书籍与查找相关文献资料,以自己的理解剖析本课题题研究的背景、意义及其国内外发展现状,并在了解了这些之后,规划了本设计需要完成的主要任务,分别为:1、地形的初始化与地形的绘制;2、天空太阳的绘制;3、雾化效果与太阳光效果;4、飞机的绘制;5、飞机尾部喷管喷出的火焰的绘制;6、飞机飞行中的过程控制计算;(2)基于本次的设计,对OpenGL的基础知识及开发平台的应用在自己理解的基础上进行了简述;(3)简述本次设计中所涉及到的OpenGL中的关键技术;(4)简述如何灵活地利用OpenGL中提供的技术实现来完成相关任务设计;(5)简述在完成分任务的设计之后如何实现各场景与模型之间的联立,使之能够在自动漫游基础上可以通过键盘响应实现人机交互漫游,最终完成了基于OpenGL的飞机飞行动画模拟设计。向大家展示了计算机实现科学计算可视化的基本流程,并通过与计算机动画与虚拟现实的结合,将其展现在计算机屏幕上,令大家能够真切地感受到计算机图形学发展的成果。本次设计如预期般完成了本课题的设计要求,但是其依然有着许多不足的地方,例如在建模上还是比较简陋、缺少碰撞检测等。但是随着以后深入的学习,相信这些问题都能够得到完善的解决。虽然本人的这次设计比较简陋,但是在现实中肯定已有建模逼真、计算科学的设计与现实相逼近,实现真正意义上的虚拟现实。并且,相信随着科学技术的发展,最终虚拟与现实能够真正地连通起来。62 华侨大学2014届本科生毕业论文基于OpenGL的飞机飞行动画模拟设计顾礼书参考文献[1]和平鸽工作室.三维图形系统开发与实用技术.北京:清华大学出版社,2003.[2]刘锐宁,宋坤.VisualC++从入门到精通.北京:清华大学出版社.2008[3]和平鸽工作室编.OpenGL高级编程与可视化系统开发(高级编程篇).北京:中国水利水电出版社,2003.[4](美国)赖特(RichardS.Wright.Jr),(美国)利普恰克(BenjaminLipchak),(美国)黑内尔(NicholasHaemel).OpenGL.SuperBible.4th.Edition,2010.09.01[5]NeHe的OpenGL中文教程.网络资源.http://www.yakergong.net/nehe/62 华侨大学2014届本科生毕业论文基于OpenGL的飞机飞行动画模拟设计顾礼书附录附录一:[英文文献]OpenGL.SuperBible.4th.EditionRichardS.Wright,Jr.BenjaminLipchakNicholasHaemelColor,Materials,andLighting:TheBasicsUsingColorinOpenGLYounowknowthatOpenGLspecifiesanexactcolorasseparateintensitiesofred,green,andbluecomponents.YoualsoknowthatmodernPChardwaremightbeabletodisplaynearlyallthesecombinationsoronlyaveryfew.How,then,dowespecifyadesiredcolorintermsofthesered,green,andbluecomponents?TheColorCubeBecauseacolorisspecifiedbythreepositivecolorvalues,wecanmodeltheavailablecolorsasavolumethatwecalltheRGBcolorspace.Figure5.6showswhatthiscolorspacelookslikeattheoriginwithred,green,andblueastheaxes.Thered,green,andbluecoordinatesarespecifiedjustlikex,y,andzcoordinates.Attheorigin(0,0,0),therelativeintensityofeachcomponentiszero,andtheresultingcolorisblack.ThemaximumavailableonthePCforstorageinformationis24bits,sowith8bitsforeachcomponent,let’ssaythatavalueof255alongtheaxisrepresentsfullsaturationofthatcomponent.Wethenendupwithacubemeasuring255oneachside.Thecornerdirectlyoppositeblack,wheretheconcentrationsare(0,0,0),iswhite,withrelativeconcentrationsof(255,255,255).Atfullsaturation(255)fromtheoriginalongeachaxisliethepurecolorsofred,green,andblue.FIGURE5.6TheoriginofRGBcolorspace.This“colorcube”(seeFigure5.7)containsallthepossiblecolors,eitheronthesurfaceofthecubeorwithintheinteriorofthecube.Forexample,allpossibleshadesofgraybetweenblackandwhitelieinternallyonthediagonallinebetweenthecornerat(0,0,0)andthecornerat(255,255,255).62 华侨大学2014届本科生毕业论文基于OpenGL的飞机飞行动画模拟设计顾礼书FIGURE5.7TheRGBcolorspace.Figure5.8showsthesmoothlyshadedcolorcubeproducedbyasampleprogramfromthischapter,CCUBE.Thesurfaceofthiscubeshowsthecolorvariationsfromblackononecornertowhiteontheoppositecorner.Red,green,andbluearepresentontheircorners255unitsfromblack.Additionally,thecolorsyellow,cyan,andmagentahavecornersshowingthecombinationoftheotherthreeprimarycolors.Youcanalsospinthecolorcubearoundtoexamineallitssidesbypressingthearrowkeys.FIGURE5.8TheoutputfromCCUBEisthiscolorcube.SettingtheDrawingColorLet’sbrieflyreviewtheglColorfunction.Itisprototypedasfollows:voidglColor(red,green,blue,alpha);Inthefunctionname,therepresentsthenumberofarguments;itmightbe3forthreeargumentsofred,green,andblueor4forfourargumentstoincludethealphacomponent.Thealphacomponentspecifiesthetranslucencyofthecolorandiscoveredinmoredetailinthenextchapter.Fornow,justuseathree-argumentversionofthefunction.Theinthefunctionnamespecifiestheargument’sdatatypeandcanbeb,d,f,i,s,ub,ui,orus,forbyte,double,float,integer,short,unsignedbyte,unsignedinteger,andunsignedshortdatatypes,respectively.Anotherversionofthefunctionhasav62 华侨大学2014届本科生毕业论文基于OpenGL的飞机飞行动画模拟设计顾礼书appendedtotheend;thisversiontakesanarraythatcontainsthearguments(thevstandsforvectored).InAppendixC,“APIReference,”youwillfindanentrywithmoredetailsontheglColorfunction.MostOpenGLprogramsthatyou’llseeuseglColor3fandspecifytheintensityofeachcomponentas0.0fornoneor1.0forfullintensity.However,itmightbeeasier,ifyouhaveWindowsprogrammingexperience,tousetheglColor3ubversionofthefunction.Thisversiontakesthreeunsignedbytes,from0to255,tospecifytheintensitiesofred,green,andblue.UsingthisversionofthefunctionislikeusingtheWindowsRGBmacrotospecifyacolor:glColor3ub(0,255,128)=RGB(0,255,128)Infact,thisapproachmightmakeiteasierforyoutomatchyourOpenGLcolorstoexistingRGBcolorsusedbyyourprogramforothernon-OpenGLdrawingtasks.However,weshouldsaythat,internally,OpenGLrepresentscolorvaluesasfloating-pointvalues,andyoumayincursomeperformancepenaltiesduetotheconstantconversiontofloatsthatmusttakeplaceatruntime.Itisalsopossiblethatinthefuture,higherresolutioncolorbuffersmayevolve(infact,floating-pointcolorbuffersarealreadystartingtoappear),andyourcolorvaluesspecifiedasfloatswillbemorefaithfullyrepresentedbythecolorhardware.ShadingOurpreviousworkingdefinitionforglColorwasthatthisfunctionsetsthecurrentdrawingcolor,andallobjectsdrawnafterthiscommandhavethelastcolorspecified.AfterdiscussingtheOpenGLdrawingprimitivesinaprecedingchapter,wecannowexpandthisdefinitionasfollows:TheglColorfunctionsetsthecurrentcolorthatisusedforallverticesdrawnafterthecommand.Sofar,allourexampleshavedrawnwireframeobjectsorsolidobjectswitheachfaceadifferentsolidcolor.Ifwespecifyadifferentcolorforeachvertexofaprimitive(point,line,orpolygon),whatcoloristheinterior?Let’sanswerthisquestionfirstregardingpoints.Apointhasonlyonevertex,andwhatevercoloryouspecifyforthatvertexistheresultingcolorforthatpoint.Easyenough.Aline,however,hastwovertices,andeachcanbesettoadifferentcolor.Thecolorofthelinedependsontheshadingmodel.Shadingissimplydefinedasthesmoothtransitionfromonecolortothenext.AnytwopointsintheRGBcolorspace(refertoFigure5.7)canbeconnectedbyastraightline.Smoothshadingcausesthecolorsalongthelinetovaryastheydothroughthecolorcubefromonecolorpointtotheother.Figure5.9showsthecolorcubewiththeblackandwhitecornersidentified.Belowitisalinewithtwovertices,oneblackandonewhite.Thecolorsselectedalongthelengthofthelinematchthecolorsalongthestraightlineinthecolorcube,fromtheblacktothewhitecorners.Thisresultsinalinethatprogressesfromblackthroughlightershadesofgrayandeventuallytowhite.62 华侨大学2014届本科生毕业论文基于OpenGL的飞机飞行动画模拟设计顾礼书FIGURE5.9Howalineisshadedfromblacktowhite.Youcandoshadingmathematicallybyfindingtheequationofthelineconnectingtwopointsinthethree-dimensionalRGBcolorspace.Thenyoucansimplyloopthroughfromoneendofthelinetotheother,retrievingcoordinatesalongthewaytoprovidethecolorofeachpixelonthescreen.Manygoodbooksoncomputergraphicsexplainthealgorithmtoaccomplishthiseffect,scaleyourcolorlinetothephysicallineonthescreen,andsoon.Fortunately,OpenGLdoesallthisworkforyou!Theshadingexercisebecomesslightlymorecomplexforpolygons.Atriangle,forinstance,canalsoberepresentedasaplanewithinthecolorcube.Figure5.10showsatrianglewitheachvertexatfullsaturationforthered,green,andbluecolorcomponents.ThecodetodisplaythistriangleisshowninListing5.1andinthesampleprogramtitledTRIANGLE.FIGURE5.10AtriangleinRGBcolorspace.LISTING5.1DrawingaSmooth-ShadedTrianglewithRed,Green,andBlue62 华侨大学2014届本科生毕业论文基于OpenGL的飞机飞行动画模拟设计顾礼书Corners//EnablesmoothshadingglShadeModel(GL_SMOOTH);//DrawthetriangleglBegin(GL_TRIANGLES);//RedApexglColor3ub((GLubyte)255,(GLubyte)0,(GLubyte)0);glVertex3f(0.0f,200.0f,0.0f);//GreenontherightbottomcornerglColor3ub((GLubyte)0,(GLubyte)255,(GLubyte)0);glVertex3f(200.0f,-70.0f,0.0f);//BlueontheleftbottomcornerglColor3ub((GLubyte)0,(GLubyte)0,(GLubyte)255);glVertex3f(-200.0f,-70.0f,0.0f);glEnd();SettingtheShadingModelThefirstlineofListing5.1actuallysetstheshadingmodelOpenGLusestodosmoothshading—themodelwehavebeendiscussing.Thisisthedefaultshadingmodel,butit’sagoodideatocallthisfunctionanywaytoensurethatyourprogramisoperatingthewayyouintended.TheothershadingmodelthatcanbespecifiedwithglShadeModelisGL_FLATforflatshading.Flatshadingmeansthatnoshadingcalculationsareperformedontheinteriorofprimitives.Generally,withflatshading,thecoloroftheprimitive’sinterioristhecolorthatwasspecifiedforthelastvertex.TheonlyexceptionisforaGL_POLYGONprimitive,inwhichcasethecoloristhatofthefirstvertex.Next,thecodeinListing5.1setsthetopofthetriangletobepurered,thelower-rightcornertobegreen,andtheremaininglower-leftcornertobeblue.Becausesmoothshadingisspecified,theinteriorofthetriangleisshadedtoprovideasmoothtransitionbetweeneachcorner.TheoutputfromtheTRIANGLEprogramisshowninFigure5.11.ThisoutputrepresentstheplaneshowngraphicallyinFigure5.10.62 华侨大学2014届本科生毕业论文基于OpenGL的飞机飞行动画模拟设计顾礼书FIGURE5.11TheoutputfromtheTRIANGLEprogram.Polygons,morecomplexthantriangles,canalsohavedifferentcolorsspecifiedforeachvertex.Intheseinstances,theunderlyinglogicforshadingcanbecomemoreintricate.Fortunately,youneverhavetoworryaboutitwithOpenGL.Nomatterhowcomplexyourpolygon,OpenGLsuccessfullyshadestheinteriorpointsbetweeneachvertex.ColorintheRealWorldRealobjectsdon’tappearinasolidorshadedcolorbasedsolelyontheirRGBvalues.Figure5.12showstheoutputfromtheprogramtitledJETfromthesamplecodeforthischapter.It’sasimplejetairplane,handplottedwithtrianglesusingonlythemethodscoveredsofarinthisbook.Asusual,JETandtheotherexampleprogramsinthischapterallowyoutospintheobjectaroundbyusingthearrowkeystobetterseetheeffects.FIGURE5.12Asimplejetbuiltbysettingadifferentcolorforeachtriangle.Theselectionofcolorsismeanttohighlightthethree-dimensionalstructureofthejet.Asidefromthecrudeassemblageoftriangles,however,youcanseethatthejetlookshardlyanythinglikearealobject.Supposeyouconstructedamodelofthisairplaneandpaintedeachflatsurfacethecolorsrepresented.Themodelwouldstillappear62 华侨大学2014届本科生毕业论文基于OpenGL的飞机飞行动画模拟设计顾礼书glossyorflatdependingonthekindofpaintused,andthecolorofeachflatsurfacewouldvarywiththeangleofyourviewandanysourcesoflight.OpenGLdoesareasonablygoodjobofapproximatingtherealworldintermsoflightingconditions.Todoso,itusesasimpleandintuitivelightingmodelthatisn’tnecessarilybasedonthephysicsofrealworldlight.IntheOpenGLlightingmodel,unlessanobjectemitsitsownlight,itisilluminatedbythreekindsoflight:ambient,diffuse,andspecular.Intherealworld,thereisofcoursenosuchthing.However,forourabstractionoflighting,thesethreekindsoflightallowustosimulateandcontrolthethreemainkindsofeffectsthatlighthaswhenshiningonmaterials.AmbientLightAmbientlightdoesn’tcomefromanyparticulardirection.Ithasanoriginalsourcesomewhere,buttheraysoflighthavebouncedaroundtheroomorsceneandbecomedirectionless.Objectsilluminatedbyambientlightareevenlylitonallsurfacesinalldirections.Youcanthinkofallpreviousexamplesinthisbookasbeinglitbyabrightambientlightbecausetheobjectswerealwaysvisibleandevenlycolored(orshaded)regardlessoftheirrotationorviewingangle.Figure5.13showsanobjectilluminatedbyambientlight.Youcanthinkofambientlightasaglobal“brightening”factorappliedperlightsource.InOpenGL,thislightingcomponentreallyapproximatesscatteredlightintheenvironmentthatoriginatesfromthelightsource.FIGURE5.13Anobjectilluminatedpurelybyambientlight.DiffuseLightThediffusepartofanOpenGLlightisthedirectionalcomponentthatappearstocomefromaparticulardirectionandisreflectedoffasurfacewithanintensityproportionaltotheangleatwhichthelightraysstrikethesurface.Thus,theobjectsurfaceisbrighterifthelightispointeddirectlyatthesurfacethanifthelightgrazesthesurfacefromagreaterangle.Goodexamplesofdiffuselightsourcesincludealamp,candle,orsunlightstreaminginasidewindowatnoon.Essentially,itisthediffusecomponentofalightsourcethatproducestheshading(orchangeincolor)acrossalitobject’ssurface.InFigure5.14,theobjectisilluminatedbyadiffuselightsource.62 华侨大学2014届本科生毕业论文基于OpenGL的飞机飞行动画模拟设计顾礼书FIGURE5.14Anobjectilluminatedbyapurelydiffuselightsource.SpecularLightLikediffuselight,specularlightisahighlydirectionalproperty,butitinteractsmoresharplywiththesurfaceandinaparticulardirection.Ahighlyspecularlight(reallyamaterialpropertyintherealworld)tendstocauseabrightspotonthesurfaceitshineson,whichiscalledthespecularhighlight.Becauseofitshighlydirectionalnature,itisevenpossiblethatdependingonaviewer’sposition,thespecularhighlightmaynotevenbevisible.Aspotlightandthesunaregoodexamplesofsourcesthatproducestrongspecularhighlights.Figure5.15showsanobjectilluminatedbyapurelyspecularlightsource.FIGURE5.15Anobjectilluminatedbyapurelyspecularlightsource.PuttingItAllTogetherNosinglelightsourceiscomposedentirelyofanyofthethreetypesoflightjustdescribed.Rather,itismadeupofvaryingintensitiesofeach.Forexample,aredlaserbeaminalabiscomposedofalmostapure-redspecularcomponentproducingaverybrightspotwhereitstrikesanyobject.However,smokeordustparticlesscatterthebeamallovertheroom,givingitaverysmallambientcomponent.Thiswouldproduceaslightredhueonotherobjectsintheroom.Ifthebeamstrikesasurfaceataglancingblow,averysmalldiffuseshadingcomponentmaybeseenacrossthesurfaceitilluminates(althoughinthiscaseitwouldbelargelyoverpoweredbythespecularhighlight).Thus,alightsourceinasceneissaidtobecomposedofthreelightingcomponents:62 华侨大学2014届本科生毕业论文基于OpenGL的飞机飞行动画模拟设计顾礼书ambient,diffuse,andspecular.Justlikethecomponentsofacolor,eachlightingcomponentisdefinedwithanRGBAvaluethatdescribestherelativeintensitiesofred,green,andbluelightthatmakeupthatcomponent(forthepurposesoflightcolor,thealphavalueisignored).Forexample,ourredlaserlightmightbedescribedbythecomponentvaluesinTable5.1.TABLE5.1ColorandLightDistributionforaRedLaserLightSourceNotethattheredlaserbeamhasnogreenorbluelight.Also,notethatspecular,diffuse,andambientlightcaneachrangeinintensityfrom0.0to1.0.Youcouldinterpretthistableassayingthattheredlaserlightinsomesceneshasaveryhighspecularcomponent,asmalldiffusecomponent,andaverysmallambientcomponent.Whereveritshines,youareprobablygoingtoseeareddishspot.Also,becauseofconditionsintheroom,theambientcomponent—likelyduetosmokeordustparticlesintheair—scattersatinybitoflightallabouttheroom.62 华侨大学2014届本科生毕业论文基于OpenGL的飞机飞行动画模拟设计顾礼书附录二:[中文翻译]OpenGL超级宝典(第四版)RichardS.Wright,Jr.BenjaminLipchakNicholasHaemel第五章颜色、材料和光照:基础知识在OpenGL中使用颜色读者们现在已经知道可以将一种特色的颜色分别由不同强度的红色、绿色及蓝色组成。读者们还知道了现代计算机硬件几乎能够显示所有这些颜色成分,有也部分硬件只能显示其中的一小部分。那么,我们如何根据通过红、绿、蓝成分来指定我们想要的颜色呢?颜色立方体由于颜色是由三个正的颜色值指定,所以我们可以为可用的颜色建立一个立方体的模型,称为RGB颜色空间。图5.6显示了在以红、绿、蓝为坐标轴的原点中心附近,颜色空间看起来是什么样子的。在原点中心(0,0,0),每种成分的相对强度为零,最终颜色为黑色。PC用来存储颜色信息的最大有效位为24位,所以每种成分都用8位来表示。我们可以认为一条最大值为255的坐标轴可以完整地表示该种颜色成分的饱和度。然后,我们便得到了一个每条边长度为255的立方体。位于黑色(其坐标为(0,0,0))直对的角是白色,它的坐标为(255,255,255)。从原点沿每条轴的方向,分别是红、绿、蓝纯色的饱和分布。图5.6RBG颜色空间的原点这种“颜色立方体”(参见图5.7)包含了所有可能的颜色,它们或者位于立方体的表面,或者位于立方体的内部。例如,所以可能的灰色都位于连接黑(255,255,255)白(0,0,0)两角的那条对角线上。62 华侨大学2014届本科生毕业论文基于OpenGL的飞机飞行动画模拟设计顾礼书图5.7RGB颜色空间图5.8通过本章的一个示例程序CCUBE显示了一个平滑着色的颜色立方体。这个立方体的表面显示了从黑色角到对面白色角的颜色变化。红、绿、蓝分别由离黑色255距离的角表示。此外,黄色、青色、洋红色在这个立方体的其他角里,显示了它们如何由其他三种基本颜色组成。读者还可以通过按下箭头键旋转这个立方体来查看它所有的面。图5.8CCUBE的输出就是这个颜色立方体设置绘图颜色让我们来回顾一下glColor函数。它的原型如下:voidglColor(ret,gren,blue,alpha);在这个函数名中,表示参数的数量,它可以是代表红色、绿色、蓝色这三个参数3,也可以是包含alpha成分的4。alpha成分指定了颜色的透明程度,我们将在下一章详细地对其进行讨论。现在,我们只使用这个函数三个参数的版本。62 华侨大学2014届本科生毕业论文基于OpenGL的飞机飞行动画模拟设计顾礼书在函数名中的指定参数的数据类型,它可以是b、k、f、i、s、ub、ui或us,分别表示byte、double、float、integer、short、unsighedbyte、unsignedinteger和unsignedshort数据类型。另一个版本的函数在其末尾包含了参数v,表示接受一个数组,其中包含了各个参数(v代表向量)。在附录C“API参考”中,读者可以找到关于glColor这个函数更多的细节。读者们可以发现大多数OpenGL程序通过用0.0表示0强度、1.0表示最高强度来指定每种颜色强度。但是,如果读者拥有Windows编程经验的话,用这个版本的glColor3ub函数会更简单一些。这个版本接受三个无符号字节,每个字节由0到255,分别代表红、绿、蓝的强度。使用这个版本的函数类似于使用Windows的RGB宏来指定颜色。glColor3ub(0,255,128)=RGB(0,255,128)事实上,这种方法可能会使读者更容易将OpenGL中的颜色与读者程序中其他非OpenGL绘图任务所使用的颜色相匹配。但是,我们还应该说明,在OpenGL内部是用浮点数来表示颜色值。这种方法可能会招致一些性能上的损失,由于必须进行整型到浮点型的常量转换。当然也有可能在未来更高的颜色分辨率缓存将得到使用(事实上,浮点颜色缓冲区已经开始出现),因此用浮点值来指定颜色值能够被颜色硬件更为事实地表示。着色我们先前对glColor的定义的是这个函数是用来设置当前绘图颜色的,之后所有的绘制图形行为都是用最后一次指定的颜色。在讨论了前面章节的OpenGL绘图图元之后,我们可以如下扩展这个函数的定义:glColor函数设置当前颜色后,便用其来完成所有的顶点绘制。到目前为止,我们所有的示例程序都是绘制线框图形或实心物体,每个面都有一种实心颜色来表示。如果我们为每个图元(点、线或多边开)指定一种不同的颜色,那么这个图元内部的颜色是怎样的呢?首先,让我们以点为代表来回来这个问题。点只有一个顶点,无论你为这个顶点指定了什么颜色,这个颜色都将最终成为点的颜色。这很容易就能明白。然而,一条线有两个顶点,并且每个顶点可以被设置成不同的颜色。线的颜色取决于着色的模式。着色可以简单地被定义为一种颜色到下一种颜色的渐变。任何两个点在RGB颜色空间(参见图5.7)中都能够补一条直线连接起来。平滑着色使直线的颜色能够沿一个颜色点到另外一颜色点的直线均匀变化。图5.9显示了带有黑白角标识的颜色立方体。在它的下面是一条带有两个顶点的直线,一个黑,一个白。沿这条直线所选择的颜色与颜色立方体的那条从黑色到白色的直线相匹配。这使得这条直线的颜色从黑色逐渐地变为更淡的灰色,并最终变成白色。62 华侨大学2014届本科生毕业论文基于OpenGL的飞机飞行动画模拟设计顾礼书图5.9一条直线如何从黑色过渡到白色读者可以通过寻找连接RGB颜色空间上两点的直线方程式来进行数学上的着色。然后,读者可以简单从线的一端到另一端进行遍历,以此提取当前的坐标值来表示屏幕上的每个像素颜色。许多优秀的计算机图形学书籍解释了实现这种效果的算法与如何通过缩放你的颜色线以此来匹配屏幕的物理线等内容。幸运的是,OpenGL为你完成这些工作。多边形的着色则显得稍微更复杂一些。例如,一个三角形也可以用颜色立方体的一个平面来表示。图5.10显示了一个三个顶点分别处于红色、绿色、蓝色饱和值的三角形。清单5.1给出了显示这个三角形的代码,并把这个示例程序命名为TRIANGLE。图5.10RGB颜色空间中的一个三角形62 华侨大学2014届本科生毕业论文基于OpenGL的飞机飞行动画模拟设计顾礼书程序清单5.1在红、绿、蓝三角中绘制一个平滑着色的三角形//启用平滑着色glShadeModel(GL_SMOOTH);//绘制三角形glBegin(GL_TRIANGLES);//红色顶点glColor3ub((GLubyte)255,(GLubyte)0,(GLubyte)0);glVertex3f(0.0f,200.0f,0.0f);//右下角的绿色顶点glColor3ub((GLubyte)0,(GLubyte)255,(GLubyte)0);glVertex3f(200.0f,-70.0f,0.0f);//左下角的蓝色顶点glColor3ub((GLubyte)0,(GLubyte)0,(GLubyte)255);glVertex3f(-200.0f,-70.0f,0.0f);glEnd();设置着色模型程序清单5.1的第一行实际设置了OpenGL用于平滑着色的着色模型——我们正在讨论的着色模型。这是默认的着色模型,但是一个很好地思路,显示地调用这个函数来保证你的程序按照你的意愿来进行操作。另外一种着色模型可以通过glShadeModel函数设置参数GL_FLAT来指定,即单调着色。单调着色指的是在图元内部没有进行着色计算。通常,在单调着色模式下,图元内部的颜色由最后一个顶点所指定的颜色决定。多边形图元是唯一的例外,它的颜色由它的第一个顶点颜色决定。接着,程序清单5.1的代码设置了上顶点的颜色为纯红,右下角为纯绿,左下角为纯蓝。因为平滑着色模型被指定,所以这个三角形的内部按照每个角之间的颜色的平滑过渡进行着色。示例程序TRIANGLE的输出结果由图5.11显示。这个在图5.11中的输出结果表示了图形方式显示的平面。62 华侨大学2014届本科生毕业论文基于OpenGL的飞机飞行动画模拟设计顾礼书图5.11程序TRIANGLE的输出结果比三角形更复杂的多边形也可以为每个顶点指定不同的颜色。这种情况下,它的着色底层逻辑变得犹为的复杂。幸运地是,你永远不用在OpenGL中担心这个问题。无论你的多边形多么的复杂,OpenGL依然能够成功地对其两顶点之间的点进行着色。现实中的颜色真实的物体不会根据它们唯一的RGB值以实体颜色或渐变颜色出现。图5.12显示了一个本章的示例程序JET的输出结果。这是一个简单的喷气式飞机,它由许多的三角形构成,只运用了到目前为止本书所讨论过的方法。如往常一样,JET和在本章的其他一些程序允许读者通过按下方向键来旋转物体来实现更好的观察其效果。图5.12通过为每个三角形设置不再的颜色所创建的一台简单喷气式飞机选择颜色是为了突出这台飞机的三维结构。然而,除了三角形粗糙的装配之外,读者会发现无论如何也很难将这台飞机看成是真实的物体。假设你创建了这个飞机模型,并为62 华侨大学2014届本科生毕业论文基于OpenGL的飞机飞行动画模拟设计顾礼书每个面刷上了不同的颜色。基于这样地使用颜色,这个模型看上去仍然会显示平滑或平坦。随着观察者的视角及光源影响,模型的每个面都会随之变化。OpenGL在根据光照条件来逼近现实世界这方面的工作确实做得不错。为此,它使用一个简单直观的不需要依赖于真实世界的物理光的光照模型。OpenGL的光照模型,除非一个物体能够自己发光,不然它将受到三种类型光的照射:环境光、漫反射光和镜面反射光。在真实的世界中,当然不存在这样的光。但是,作为对光照的抽象,这三种光允许我们模仿和控制当光照在物体表面时所产生的三种主要类型的效果。环境光环境光并不来自任何的特定方向。它有一个起源,但是光线在房间或场景里各种反射,致使它失去了方向。物体所有的表面被环境光均匀地照亮。读者可以认为本书之前所有的例程都被一明亮的环境光所照射,因为物体问题可见的及被均匀地着色,无关其旋转或观察角度。图5.13一个物体被环境光所照射。读者可以将环境光看成一种由所有光源共同产生的“全局”因素。在OpenGL中,这种光的成分其实很逼近环境中来自同一光源的散光。图5.13一个纯粹由环境光所照射的物体漫反射光OpenGL的光中漫反射部分是具有方向的,它似乎来自一个特定的方向,并成比例地根据其光照射在物体表面的角度进行强度的反射。因此,如果光线直接指向物体表面,而不是以更大的角度照射物体表面,此时,物体表面看上去会更亮一些。反映漫反射光的好例子包括台灯、蜡烛或是中午时照在窗户一侧的日光。从本质上来说,正是光源的漫反射部分照射在物体表面从而产生了着色(或颜色变化)。在图5.14中显示了一个物体被漫反射光照射。62 华侨大学2014届本科生毕业论文基于OpenGL的飞机飞行动画模拟设计顾礼书图5.14一个被纯粹漫反射光照射的物体镜面反射光如同漫反射光,镜面反射光有很强的方向性。但是它与物体的表面和特定的方向的互动更为强烈。一个高强度的镜面反射光(实质上是现实世界中的材质属性)趋向于在它所照射的物体表面形成一个亮点,称为镜面亮点。由于它高度的方向性质,取决于观察者的位置,镜面反射光可能看不见。聚光灯和太阳都是产生高强度镜面反射光的好例子。图5.15显示了一个被纯粹镜面反射光照射的物体。图5.15一个被纯粹镜面反射光照射的物体综合考虑没有一种光源是完全由上述的三种光源中的任一一种组成的。相反,它由不同强度的这三种光源共同组成。例如,一道红色激光是由大部分纯粹的红色镜面反射光组成的,它可以在它所照射的任何物体上形成一个非常亮的亮点。然而,烟或灰尘会将令激光发散向房间各处,产生十分微弱的环境光。这将会使房间内的其他物体带上一层微弱的红色。如果激光照射在一个倾斜的表面,通过被照射的表面,我们可以看到非常微弱的漫反射(尽管在本例中它可能很大程度上被镜面反射光所掩盖)。62 华侨大学2014届本科生毕业论文基于OpenGL的飞机飞行动画模拟设计顾礼书因此,一个光源被认为由环境光、漫反射光及镜面反射光这三种成分所组成。就好像颜色的组成一样,每个光成分是用一个RGBA值来定义的,描述组成这个光成分中的红光、绿光、蓝光的强度(由于光颜色的本质,其alpha值被忽略)。例如,我们前面说到的红色激光可以由表5.1中的成分值来描述。表5.1一种红色激光光源的颜色和光分布红光绿光蓝光深度镜面反射光0.990.00.01.0漫反射光0.100.00.01.0环境光0.050.00.01.0请注意红色激光中没有绿光与蓝光。另外,注意镜面反射光、漫反射和环境光的范围都是从0.0到1.0。读者将这个表理解为说明这束红色激光在相同的场景里拥有非常多的镜面反射光成分,极其微少的漫反射光成分和极其微少的环境光成分。只要当它照射,我们可能将会看到一个红色的亮点。另外,由于房间里的条件,激光中的环境光成分将激光中的微少量分散到房间的各处(由于房间中的烟和灰尘)。62 华侨大学2014届本科生毕业论文基于OpenGL的飞机飞行动画模拟设计顾礼书致谢在此感谢本次毕业设计的导师邱应强老师的帮助,如果没有邱老师的悉心指导及认真辅导相信本文不会如此顺利的完成。在本次毕业设计过程中,邱老师积极地联系同学与同学们交流,热心地为我们讲解我们所请教的学术难题。当我们遇到瓶颈时会细心地与我们探讨,结合各种专业知识引导我们看清解决问题的方向。十分地荣幸能够跟从邱老师进行这次毕业设计,对此再次衷心地感谢邱老师的帮助与指导。同时,在此还要感谢一些无私帮助过我的已经毕业的学长学姐们,因为本身毕竟不是计算机专业的学生,所以学长学姐在学习MFC知识的过程当中给予了我很好建设性的意见。最后,感谢所有负责本次答辩的老师们,感谢您们在百忙之中能够抽出时间对学生们进行考核指正。对于老师们提出的批评与指正,学生定然铭记在心,以此为动力继续在学术学习的道路上加强自我、提高自我。62'