《基于opengl的屏幕对象拾取-本科毕业论文设计.doc》由会员分享,可在线阅读,更多相关《基于opengl的屏幕对象拾取-本科毕业论文设计.doc(32页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、论文题目: 基于OpenGL的屏幕对象拾取 毕业论文(设计)原创性声明本人所呈交的毕业论文(设计)是我在导师的指导下进行的研究工作及取得的研究成果。据我所知,除文中已经注明引用的内容外,本论文(设计)不包含其他个人已经发表或撰写过的研究成果。对本论文(设计)的研究做出重要贡献的个人和集体,均已在文中作了明确说明并表示谢意。 作者签名: 日期: 毕业论文(设计)授权使用说明本论文(设计)作者完全了解*学院有关保留、使用毕业论文(设计)的规定,学校有权保留论文(设计)并向相关部门送交论文(设计)的电子版和纸质版。有权将论文(设计)用于非赢利目的的少量复制并允许论文(设计)进入学校图书馆被查阅。学校
2、可以公布论文(设计)的全部或部分内容。保密的论文(设计)在解密后适用本规定。 作者签名: 指导教师签名: 日期: 日期: 注 意 事 项1.设计(论文)的内容包括:1)封面(按教务处制定的标准封面格式制作)2)原创性声明3)中文摘要(300字左右)、关键词4)外文摘要、关键词 5)目次页(附件不统一编入)6)论文主体部分:引言(或绪论)、正文、结论7)参考文献8)致谢9)附录(对论文支持必要时)2.论文字数要求:理工类设计(论文)正文字数不少于1万字(不包括图纸、程序清单等),文科类论文正文字数不少于1.2万字。3.附件包括:任务书、开题报告、外文译文、译文原文(复印件)。4.文字、图表要求:
3、1)文字通顺,语言流畅,书写字迹工整,打印字体及大小符合要求,无错别字,不准请他人代写2)工程设计类题目的图纸,要求部分用尺规绘制,部分用计算机绘制,所有图纸应符合国家技术标准规范。图表整洁,布局合理,文字注释必须使用工程字书写,不准用徒手画3)毕业论文须用A4单面打印,论文50页以上的双面打印4)图表应绘制于无格子的页面上5)软件工程类课题应有程序清单,并提供电子文档5.装订顺序1)设计(论文)2)附件:按照任务书、开题报告、外文译文、译文原文(复印件)次序装订3)其它目录摘要1ABSTRACT21 绪论31.1 课题的目的和意义31.2 拾取技术国内外研究31.3 本论文研究主要内容32
4、基于OPENGLMFC的建模基础52.1 OpenGL概括52.2 OpenGL渲染管线过程52.2.1顶点变换62.2.2图元组装62.2.3图元处理62.2.4片元处理62.2.5光栅化操作62.3 MFC概述62.4 MFC特点72.4.1封装72.4.2继承82.4.3虚拟函数和动态约束82.5 应用程序的构成82.6 基于OpenGL+MFC的三维模拟的编程环境配置93 拾取技术123.1 基于射线求交拾取技术123.1.1判断线段和包围盒的相对位置123.2 基于GPU的重绘式拾取技术143.3 各种拾取技术比较164 系统的设计及实现184.1 系统的选择机制184.1.1进入选
5、择模式之前184.1.2获取当前选择模式184.1.3退出选择模式204.1.4拾取204.2 拾取结果截图215 结论与展望255.1 结论255.2 展望25参考文献26致谢28IV摘要屏幕对象的拾取是计算机图形处理系统中一个重要的功能,在许多情况下,计算机图形处理系统不仅要绘制图形,而且要允许操作者能够通过输入设备(通常是鼠标)操纵屏幕上的物体(标识、移动和修改)。有时还需要获取物体上点的空间坐标或测量物体的几何特性如距离、角度、半径等,这些操作都需要以拾取作为实现的基础。OpenGL为了解决拾取问题,提供了一种基于名字堆栈和命中记录的选择机制。在OpenGL中,拾取物体是利用拾取矩阵和
6、投影变换,将拾取的范围限制在鼠标热点的有效区中,一旦触发鼠标事件就进入选择模式并将有效区初始化,最后利用拾取矩阵拾取有效区内的物体。有效区的定义由glPick2Matix()函数来完成。一旦拾取成功,就以记录的形式返回与拾取物体相关的信息,并生成一个记录表示一个物体被命中。这种物体拾取方法非常简单,不需要写很多代码。在使用OpenGL工具包开发图形处理系统时,物体的拾取有多种方法,其中包括OpenGL提供的选择机制、射线拾取法、重绘式拾取法等。本文采用OpenGL本身提供的选择机制来拾取对象,突出OpenGL工具包在屏幕对象的拾取方面的优势。关 键 词:OpenGL;计算机应用;拾取算法Abs
7、tractIn most cases, one important feature of graphics processing system is picking, which allow users to select objects by mouse, and to modify the their attributes, such as gemetry mesh or angle and so on. In order to solve the problem, pick OpenGL provides a name on the stack and hit record choice
8、 mechanism. In the OpenGL and pickobject is using the loot matrix and projection transformation, and will gather in the limits of the mouse, effective once entered the mouse event trigger mode choice and will be effective area, finally using initialization gleaned matrix pick objects in the area of
9、effective. The definition of effective glPick2Matix () function to finish. Once pick success, to return to pick the record object relevant information, and to create a record, says an object to be hit. This object pick method is very simple, need not write many code.In the use of graphics processing
10、 system development OpenGL toolkit objects, pick a variety of methods, including OpenGL provide choice mechanism, ray pick, redrawn type gather method, etc. Based on the mechanism of OpenGL itself to provide choice pickup, outstanding OpenGL toolkit objects in the screen in the object.Key words: Ope
11、nGL; computer application;picking281 绪论目前许多优秀的图形工具能为我们绘制惟妙惟肖的虚拟现实场景,在面对这些场景时候我们除了欣赏之外更多的是希望能与之互动,做为编程人员可以使用代码轻松的重新构造场景,但对于终端用户而言,他们也希望自己也能对造场景进行一些操作,如添加,删除等等。对于这些操作而言,首先我们要做的是能让用户使用鼠标来选择他所希望操作的对象,这就是本文要讨论的一个重点:拾取,这是一种在许多交互性程序中有基础地位的操作,是对屏幕中对象进行定位,并确定所选择的是哪个物体。然而该操作给我们提出了一些难题,首先,需要对对象进行届定。其次,必须对“拾取目标
12、”进行定义。这就需要终端用户确定单击的位置是构成对象的图元上,还是对象附近的位置以及考虑如果选取点落在两个以上物体交集部分如何处理等等问题,本文利用了OpenGL中的选择模式进行有效的对象判别和拾取。1.1 课题的目的和意义图形对象的拾取是计算机图形处理系统中一个重要的功能,很多图形系统需要用户通过输入设备与系统交互,如移动、旋转某个物体,或查询某个物体的状态信息,需要通过拾取来确定景中的操作对象。快速可靠的拾取被广泛地运用于各种系统中,如实时图形系统、虚拟现实、游戏和CAD系统等方面,拾取操作己成为这些系统的重要部分,它在计算机建模软件尤其重要,能够通过拾取操作对模型进行局部修改和编辑,提高
13、建模系统的灵活性和适用性。随着计算机软硬件的快速发展,人们对实时系统的交互的实时性要求也越发苛刻,而且三维场景复杂度也日益提高,这就要求系统提供快速的拾取操作。因此,高效的拾取算法能够决定拾取操作快与慢的关键所在,从而开发高效的拾取算法已成为当今一个的课题研究。1.2 拾取技术国内外研究随着网络科技越来越发达,拾取操作也越来越方便了,有的只要鼠标点点就可以。而拾取操作的关键是拾取算法。到目前为止,拾取算法大致上可以分三种。第一种是基于射线求交的拾取技术,1992年,Mark Segul,Carl Korobkin,Rolf van Widenfelt等人首次采用了基于射线求交的拾取技术原理实现
14、了对衣服的拾取1;1998年Michael Deering,Step hanie Winner and Bic Schediwy等也才采用了同样的技术成功做到了人物的拾取2;2005年,龚堰珏,颜敏等人采用了基于射线求交的拾取技术实现对几个简单物体的拾取3;同年,韦宇炜也是用此技术实现对游戏中各类的拾取,如对技能的释放,对地上物品的捡起来,对别的玩家人物属性的查看等等4;2006年,姚继权,李晓豁等人也采用了这种拾取技术成功地做到了对3D网游游戏中的各种各样的拾取5,等等。第二种是基于GPU的重绘式拾取技术,这种方法对硬件的依赖性大,不过拾取速度快。1997年,MasaakiOka,Kyoya
15、 Tsutsui,Akio Ohba等人第一次采用了基于GPU的重绘式拾取技术在房子中拾取到了房子主人与小孩子6;2006年,刘力强,周明全等多人采用基于GPU的重绘式拾取技术,在大规模室外地形中拾取到了地面某个区域7。第三种是OpenGL自带的拾取机制,1992年7月,SGI公司发布了OpenGL的1.0版本,随后又与微软公司共同开发了Windows NT版本的OpenGL,从而使一些原来必须在高档图形工作站上运行的大型3D图形处理软件也可以在微机上运用。1995年OpenGL的1.1版本面市,该版本较1.0性能提高许多,并加入了一些新的功能,如本身自带的拾取机制,这项功能使OpenGL在各
16、个领域都得到了应用8。随后出现的各个版本,使自带的拾取机制越来越完善,操作越来越方便,应用范围越来越广泛。1.3 本文研究的主要内容(一):综述本课题研究的意义以及国内外研究现状;(二):介绍了OpenGL与OpenGL渲染管道,分析MFC编程框架和基于OpenGL+MFC的三维模拟的编程环境配置;(三):各种拾取技术的实现原理,优缺点;(四):采用了OpenGL本身自带的拾取机制设计并实现简单的拾取操作;(五):总结本文并进一步给出了展望。2 基于OpenGLMFC的建模基础2.1 OpenGL概括 OpenGL(全写Open Graphics Library)是个定义了一个跨编程语言、跨平
17、台的编程软件接口的规格,该接口包括了大约250个不同的函数(其中核心OpenGL大约包括200个函数,另外还有50个左右位于OpenGL工具函数库),可以用这些函数指定物体和操作,创建交互性三维应用程序。它是个专业的图形程序接口,是一个功能强大,调用方便的底层图形库,Opengl用于三维图象(二维的亦可)。OpenGL的设计目标就是作为一种流线型的、独立于硬件的接口,可以在许多不同的硬件平台上实现。为了实现这个目标,OpenGL并未包含用于执行窗口任务或者获取用户输入之类的函数。反之,必须通过窗口系统控制所使用的特定硬件。类似地,OpenGL并没有提供用于描述三维物体模型的高层函数。这类函数可
18、能允许你指定相对较为复杂的形状,例如汽车、身体的某 个部位、飞机或分子等。在OpenGL中,必须根据少数几个基本几何图元(geometric primitive)(如点、直线和多边形)来创建你所需要的模型。当然,我们可以在OpenGL上创建能够提供这些特性的高级函数库。OpenGL 实用函数库(GLU)提供了许多建模特性,例如二次曲面以及NURBS曲线和表面。GLU是所有OpenGL实现的一个标准组成部分。1992年7月,SGI公司发布了OpenGL的1.0版本,随后又与微软公司共同开发了Windows NT版本的OpenGL,从而使一些原来必须在高档图形工作站上运行的大型3D图形处理软件也可
19、以在微机上运用。1995年OpenGL的1.1版本面市,该版本较1.0性能提高许多,并加入了一些新的功能。1997年,Windows 95下3D游戏的大量涌现,游戏开发公司迫切需要一个功能强大、兼容性好的3D图形接口,而当时微软公司自己的3D图形接口DirectX 3.0功能却是很糟糕。因而以制作雷神之锤等经典3D射击游戏而著名的id公司同其它一些游戏开发公司一同强烈要求微软在Windows95中加入对OpenGL的支持。微软公司最终在Windows95的OSR2版和后来的Windows版本中加入了对OpenGL的支持。这样,不但许多支持OpenGL的电脑3D游戏得到广泛应用,而且许多在3D图
20、形设计软件也可以运用支持OpenGL标准的3D加速卡,大大提高其3D图形的处理速度。2003年的7月28日,SGI和ARB公布了OpenGL 1.5。OpenGL 1.5中包括OpenGL ARB的正式扩展规格绘制语言“OpenGL Shading Language”。2004年8月,OpenGL2.0版本发布OpenGL 2.0标准的主要制订者并非原来的SGI,而是逐渐在ARB中占据主动地位的3Dlabs。2008年8月初Khronos工作组在Siggraph 2008大会上宣布了OpenGL 3.0图形接口规范,GLSL1.30 shader语言和其他新增功能将再次未来开放3D接口发展指明
21、方向。2009年3月又公布了升级版新规范OpenGL 3.1,也是这套跨平台免费API有史以来的第九次更新。2009年8月Khronos小组发布了OpenGL 3.2,这是一年以来OpenGL进行的第三次重要升级。Khronos旗下的OpenGL ARB(Architecture Review Board)工作组推出了GLSL 1.5OpenGLShading Language(OpenGL着色语言)的升级版,以及在OpenGL3.2框架下推出了两个新功能,可以让开发者在开发新程序时能够在使用流水线内核特性或兼容性特性之间做出选择,其中兼容性特性会提供与旧版OpenGL之间的兼容性。2.2 O
22、penGL渲染管线过程管线这个术语用于描述一种过程,它涉及两个或更多个独特的阶段或步骤。当应用程序进行OpenGL API 调用时,这些命令被放置在一个命令缓冲区中。这个缓冲区最终填满了命令、顶点数据、纹理数据等。当缓冲区被刷新时,命令和数据就被传递给管线的下一个阶段。通常,顶点数据首先进行转换和光照。在转换阶段,描述物体几何形状的点被重新计算,以确定这个物体的位置和方向。同时所进行的光照计算将确定每个顶点应该具有的颜色亮度。当这个阶段完成之后,数据就被输入到管线的光栅化部分。光栅阶段根据几何图形、颜色和纹理数据实际创建彩色图像。然后,图像被放入帧缓冲区中。帧缓冲区就是图形显示设备的内存,这意
23、味着这幅图像将会在屏幕上显示。图1显示了OpenGL工作流程图顺序,虽然并没有严格规定OpenGL必须采用这样的实现,但它却提供了一个可靠的指南方向,可以预测OpenGL将以什么样的顺序来执行这些操作。图 1 Opengl工作渲染流程图OpenGL渲染管线的操作过程主要包括以下几部分:1)顶点变换2)图元组装3)图元处理4)片元处理5)光栅化操作2.2.1顶点变换这个阶段主要是对输入的顶点进行逐个处理,这些顶点都包括很多属性(如位置、颜色、法线和纹理坐标等),经过处理后,输出是经过变换后的顶点属性及关联信息。 主要过程:顶点变换(几何变换和投影变换)、光照计算、纹理坐标变换和生成。2.2.2图
24、元组装这个阶段主要是按照输入的变换后的顶点属性和关联信息,组装形成图元。2.2.3图元处理这个阶段主要是对输入的图元进行处理,输出片元(帧缓存中更新象素属性的数据)信息,该片元信息是对顶点变换阶段得出的属性进行插值处理得到的。 主要过程:视景裁剪、背面剔除。2.2.4片元处理这个阶段的输入为经过插值计算后的最终片元信息,经过处理后,输出信息为片元的深度和颜色值。 主要过程:纹理、雾化、颜色汇总(包括纹理颜色,光照颜色,主颜色等)。2.2.5光栅化操作这个阶段的输入为像素位置和片元的深度、颜色值等信息,经过一系列的测试(剪切测试、Alpha测试、模板测试和深度测试)后形成像素的颜色。 主要过程:
25、剪切测试、Alpha测试、模板测试和深度测试、写入帧缓存。2.3 MFC概述MFC(Microsoft Foundation Class Library)中的各种类结合起来构成了一个应用程序框架,它的目的就是让程序员在此基础上来建立Windows下的应用程序,这是一种相对SDK来说更为简单的方法。因为总体上,MFC框架定义了应用程序的轮廓,并提供了用户接口的标准实现方法,程序员所要做的就是通过预定义的接口把具体应用程序特有的东西填入这个轮廓。Microsoft Visual C+提供了相应的工具来完成这个工作:AppWizard可以用来生成初步的框架文件(代码和资源等);资源编辑器用于帮助直观
26、地设计用户接口;ClassWizard用来协助添加代码到框架文件;最后,编译,则通过类库实现了应用程序特定的逻辑。 MFC是在1992年随微软的Microsoft C/C+ 7.0编译器发布的,用于面向16位Windows的软件开发。起初,MFC是作为一个应用程序框架开发的,所以定名为Application FrameworkX (AFX)。 Borland几乎同时发布了面向Turbo C编译器的OWL,并且在一开始比MFC更具有市场占有率,但是在Borland发布了一个不向下兼容的应用程序框架之后,它丧失了很多市场份额;在Borland从微软获得发布MFC的授权之后它的市场份额进一步减少。B
27、orland最终用Visual Component Library来作为OWL的后继者。 随着Visual Basic和Visual Studio .NET的发布,曾经一度被微软重点推荐的MFC被Visual Basic、C#、Windows Forms抢走了不少市场份额,但是MFC继续在非托管软件开发中占据重要地位。在托管开发方面,MFC中也包括对Windows Forms和托管非托管互操作的封装。微软在Windows Vista和Windows 7发布之后在MFC中增加了对新的Windows API支持。 很多商用类库在MFC的基础上进一步实现了皮肤、渐变风格、多顶层窗口程序、属性列表等较
28、受欢迎的功能;同时,在C+在线社区中,很大一部分开放的源代码也是基于MFC的。VC+产品版本与MFC版本如下:表格 1 VC+产品版本与MFC版本2.4 MFC 特点2.4.1封装构成MFC框架的是MFC类库。MFC类库是C+类库。这些类或者封装了Win32应用程序编程接口,或者封装了应用程序的概念,或者封装了OLE特性,或者封装了ODBC和DAO数据访问的功能,等等,分述如下:(1)对Win32应用程序编程接口的封装;(2)对应用程序概念的封装;(3)对COM/OLE特性的封装;(4)对ODBC功能的封装。2.4.2继承首先,MFC抽象出众多类的共同特性,设计出一些基类作为实现其他类的基础。
29、这些类中,最重要的类是CObject和CCmdTarget。CObject是MFC的根类,绝大多数MFC类是其派生的,包括CCmdTarget。CObject 实现了一些重要的特性,包括动态类信息、动态创建、对象序列化、对程序调试的支持,等等。所有从CObject派生的类都将具备或者可以具备CObject所拥有的特性。CCmdTarget通过封装一些属性和方法,提供了消息处理的架构。MFC中,任何可以处理消息的类都从CCmdTarget派生。 针对每种不同的对象,MFC都设计了一组类对这些对象进行封装,每一组类都有一个基类,从基类派生出众多更具体的类。这些对象包括以下种类:窗口对象,基类是CW
30、nd;应用程序对象,基类是CwinThread;文档对象,基类是Cdocument,等等。2.4.3虚拟函数和动态约束MFC以“C+”为基础,自然支持虚拟函数和动态约束。但是作为一个编程框架,有一个问题必须解决:如果仅仅通过虚拟函数来支持动态约束,必然导致虚拟函数表过于臃肿,消耗内存,效率低下。例如,CWnd封装 Windows窗口对象时,每一条Windows消息对应一个成员函数,这些成员函数为派生类所继承。如果这些函数都设计成虚拟函数,由于数量太多,实现起来不现实。于是,MFC建立了消息映射机制,以一种富有效率、便于使用的手段解决消息处理函数的动态约束问题。2.5 应用程序的构成图2解释了该
31、应用程序的结构与对象,箭头表示信息流向。图 2 应用程序的结构从CWinApp、CDocument、CView、CMDIFrameWnd、CMDIChildWnd类对应地派生出CTApp、CTDoc、CTView、CMainFrame、CChildFrame五个类,这五个类的实例分别是应用程序对象、文档对象、视对象、主框架窗口对象和文档边框窗口对象。主框架窗口包含了视窗口、工具条和状态栏。对这些类或者对象解释如下:(1)应用程序(CWinApp) 应用程序类派生于CWinApp。基于框架的应用程序必须有且只有一个应用程序对象,它负责应用程序的初始化、运行和结束。(2)边框窗口(CMDIFram
32、eWnd) 如果是SDI应用程序,从CFrameWnd类派生边框窗口类,边框窗口的客户子窗口(MDIClient)直接包含视窗口;如果是MDI应用程序,从CMDIFrameWnd类派生边框窗口类,边框窗口的客户子窗口(MDIClient)直接包含文档边框窗口。如果要支持工具条、状态栏,则派生的边框窗口类还要添加CToolBar和CStatusBar类型的成员变量,以及在一个OnCreate消息处理函数中初始化这两个控制窗口。 边框窗口用来管理文档边框窗口、视窗口、工具条、菜单、加速键等,协调半模式状态(如上下文的帮助(SHIFT+F1模式)和打印预览)。(3)文档边框窗口(CMDIChildW
33、nd) 文档边框窗口类从CMDIChildWnd类派生,MDI应用程序使用文档边框窗口来包含视窗口。(4)文档(CDocument) 文档类从CDocument类派生,用来管理数据,数据的变化、存取都是通过文档实现的。视窗口通过文档对象来访问和更新数据。(5)视(CView) 视类从CView或它的派生类派生。视和文档联系在一起,在文档和用户之间起中介作用,即视在屏幕上显示文档的内容,并把用户输入转换成对文档的操作。用图的形式可直观地表示所涉及的MFC类的继承或者派生关系,如下:图 3 MFC的层次2.6 基于OpenGL+MFC的三维模拟的编程环境配置用MFC调用OpenGL函数来进行三维模
34、拟的编程环境配置:(一)创建MFC项目(1) 创建项目文件:选择File/New 菜单选项,建立一个名为MyTest 的单文档 (SDI) 应用程序;(二)配置OpenGL开发环境(1)将91h,gluh,glauxh和gluth拷贝到(即盘符+路径)Microsoft Visual StudioVC98IncludeGL目录中;(2)将opengl321ib,glu321ib,glaux1ib和glut321ib拷贝到(即盘符+路径)Microsoft Visual StudioVc98Lib目录中;(3)将opengl32.dll,glu.dll,glu32.dll,glut.dll,gl
35、ut32.dll文件拷贝到操作系统安装目录C:WINDOWSsystem32目录下;(4)选择Project/Setting 菜单选项。在Link栏的Lib输入域中添加openg132.lib、glu32.lib,若需使用OpenGL的辅助库函数,则还需添加glaux.lib。到此,基于OpenGLMFC的开发环境就建立好。(三)初始化OpenGL具体编程步骤:第一步:修改窗口风格设置。需要在函数CGLView:PreCreateWindow中增加对Windows窗口风格的设置,以防止在窗口重叠时把图形绘制到子窗口和兄弟窗口。实现代码如下:csstyle l=WS_CLIPCHILDREN W
36、S CLIPSIBLINGS;第二步:设置像素格式。首先需要在视图类CGLView中添加一个成员函数,函数原型如下:BOOL CGLView:SetupPixelFormat(CDC*pDC);设置像素格式并向视图类CGLView中添加两个成员变量:CDC* m_pDC;OpenGL设备场境HGLRC m_hRC;OpenGL渲染场境在Windows中,使用结构PIXELFO腿ATDEscRIPTOR来设置像素格式,并提供ChoosePixelFormat()函数来选择最为匹配的像素格式以及SetPixelFormat()函数来为设备场境设置像素格式。设置像素格式的步骤如下:a.填写结构PIX
37、ELFORMATDESCRIPTOR,像素格式是用这个结构来描述的。b.调用函数ChoosePixelFormat(),将填写好的像素格式结构传递给该函数,函数ChoosePixelFormat()返回一个整型的序号。这个序号标识一个当前设备场境中所能提供的,且与所要求的像素格式最为匹配的像素格式。c将这个返回的像素格式序号传递给函数SetPixelFormat(),使之设置成为当前设备场境的像素格式。第三步:创建渲染场境。用wglreatecontext()函数来创建OpenGL的一个渲染场境;用wglMakeCurrent()函数使给定的渲染场境设置成为当前调用线程的渲染场境,而线程中随后
38、调用的OpenGL命令都将通过与该渲染场境相关联的设备场境来实现窗口的场景绘制。具体实现代码如下:HDC m hDC;HGLRC nl hglRC:m_hglRC=wglCreateContext(m_hDC);创建一个渲染场境wglMakecurrent(m_hDC,m hglRC);使成为当前调用线程的渲染场境第四步:添加消息处理函数。利用MFC ClassWizard为CGLView类添加消息:帐_CREATE、wM_DESTROY、m,t_SIZE和删_TIMER的响应函数,消息处理函数名依次为:OnCreate()、onDestroy()、OnSize()和OnTimer()。ACG
39、LView:OnCreate()函数该函数完成的功能是:在视图窗口创建完成后,进行OpenGLWindows的初始化工作。(四)清理工作CGLView:OnDestroy()函数该函数完成的功能是:在视图窗口被释放时,用于清除当前的渲染场境,并释放设备场境。具体实现代码如下:wglMakeCurrent(NULL,NULL);wglDeleteContext(m_hglRC);清除渲染场境:ReleaseDC(m_hWnd,m_hDC);释放设备场境CCGLView:OnSize()函数DCGLView:OnTimer()函数该函数完成的功能是:通过定时器每隔一定时间的消息驱动,来实现动态的场
40、景更新。3 拾取技术拾取算法的研究可大致分为两类:一类是基于三维空间的射线拾取算法,代表算法就是基于CPU的射线求交拾取技术;另一类是基于图像空间的拾取算法,例如:基于GPU的重绘式拾取技术。3.1 基于射线求交拾取技术其基本原理是:获取屏幕坐标并转换成图形系统的视口坐标,根据不同图形API(应用程序编程接口)的实现给该点加上适当的深度值(如OpenGL标准的深度值介于0-1),反算出该拾取点的世界空间坐标,将相机焦点坐标转换为屏幕坐标,过相机位置点向鼠标选中点作一条射线在三维空间中对射线和物体进行求交,离相机位置点最近的实体就是被选中的实体。算法的具体实现步骤如下:(1)初始化,获取鼠标点的
41、屏幕坐标(x,y),并将相机焦点坐标转换为屏幕坐标;(2)相机焦点深度值(z值)作为鼠标点的深度值(z值),并将鼠标点坐标转化为世界坐标(XW ,YW ,ZW);(3)过相机位置点向点(XW,YW,ZW)作一射线m,并分别求射线m 和投影空间近截面和远截面的交点A,B,得到线段AB。如果射线m垂直于视线,则射线m和投影空间不相交;(4)依次取出场景实体列表中的每个实体,获取该实体的转换矩阵,并利用该矩阵将A、B点的坐标转换为局部坐标;(5)计算实体的包围盒,并判断AB和包围盒的相对位置。如果AB和包围盒相交,则求该实体和AB交点的参数值,并将该实体标记为选中对象。如不相交,则进行下一个实体的处
42、理。在上述算法中,判断线段AB和实体包围盒的相对位置及线段AB和实体的求交是算法实现的关键。为了提高拾取速度,对传统的包围盒算法和求交算法进行了改进。3.1.1判断线段和包围盒的相对位置实体的最大包围盒是一个各表面平行于坐标平面的六面体,其左下顶点的x、y、z坐标值为实体所有顶点相应坐标值的最小值,其右上顶点的坐标值为实体所有顶点相应坐标值的最大值。采用向量法来判断线段和包围盒相对位置,该算法的基本思想为:将线段看成一个由起点指向终点的向量,求向量各分量和离起点最近的三个包围盒侧面所在平面的交点,如果各分量与平面的交点都在包围盒侧面上或者在包围盒内且在各分量上,则该线段和包围盒相交(本文中我们
43、把线段与包围盒相交和线段在包围盒内这两种情况统称为相交)。判断线段与包围盒相对位置的具体步骤如下:(1)判断起点A是否在包围盒内,如果在盒内,则线段AB和包围盒相交,判断结束;如果不在盒内,则记下该包围盒离起点A最近的三个侧面,这三个侧面必定共点且相互垂直;(2)过起点A向各侧面做垂线,得到三个垂足,连接点A和各垂足,得到三个向量a1、a2、a3(如图4所示),并求a1、a2、a3和向量AB各相应分量的比值ti=ai/AB(i=1,2,3)。如果AB的某个分量为零,则比值取-1。取t1、t2、t3中的最大值为tmax,如果tmax1,则AB和包围盒不相交,判断结束;(3)根据tmax值求出交点
44、坐标,判断交点是否在包围盒上。(此处最好给出交点坐标的计算式,以及交点是否在包围盒上的判断算式。)如果交点在盒上,则AB和包围盒相交,否则,AB和包围盒相离。图 4 线段AB 和包围盒的位置关系图判断线段与包围盒相对位置的算法流程如图5所示。图 5 向量法判断线段和包围盒相对位置算法流程图根据拾取对象的不同,线段和相关对象求交的方法和过程存在差别。设要和拾取对象求交的线段为AB,针对不同的情况,下面对两种求交过程分别加以描述。(1)拾取对象为点当拾取对象为点时,求交的实质就是以AB为轴线,以一个很小的浮点数tolerance(tolerance一般小于0.001)为半径做一个圆柱,在这个圆柱内
45、离视点最近的点就是所求的交点。具体做法是将实体的每一个顶点向AB投影,并求出投影点在线段AB上的参数坐标。在0到1的范围内,参数坐标的值越小,说明该点离视点越近。如果我们发现了某个实体顶点比当前的最近点离视点更近且该点到AB所在直线的距离小于tolerance,则把该点记录为当前的最近点。当所有的点处理完毕,当前的最近点就是该实体和线段AB的交点。(2)拾取对象为直线或复合线复合线一般指由多个直线段相连接所构成的单元体,在本文所述的三维图形浏览器系统中,曲线如NURBS曲线、圆弧等都存储为复合线的形式。对于线状图元,比较常用的方法是通过计算点线距离来进行拾取,这种方法简单易懂,易于实现。但当拾
46、取曲线、复杂折线等图元时,计算量会非常大。为此提出一种新的改进算法,其具体操作步骤如下:以拾取点为中心、两倍拾取精度(在本文中拾取精度一般为象素宽度的25倍)为边长,绘制一个以背景色为填充色的正方形作为“测试窗口”。 如图6所示图 6 测试窗口重绘图形对象。如果图元进入拾取范围,则必然在“测试区”中留下轨迹,重绘图形对象的目的是为了恢复可能被“测试窗口”遮蔽的图形对象。循环读取“测试窗口”中象素点颜色。当发现象素点颜色有别于背景色时,终止读点,标识拾取成功。若未发现有别于背景色的象素点时,则继续进行下一个图元的检测。如图7所示图 7 测试区中的轨迹3.2 基于GPU的重绘式拾取技术基本思路:重
47、绘式拾取法是在OpenGL绘图模式下,通过2次绘图来拾取并显示物体。第1次绘图为虚拟绘图,通过在OpenGL帧缓存中绘制一些辅助图形来帮助选取物体。这些辅助图形对于系统使用者是不可见的,因此在确定所选物体之后要将辅助图形从帧缓存中清除掉才能进行第2次绘图。第2次绘图为实际绘图,所绘图形为系统使用者看到的真实图形。在GPU上实现三维图元拾取的方法有两种,第一种方法与场景几何无关,第二种方法是场景几何依赖。下面介绍第一种方法:场景几何无关方法的应用一直受到限制:它需要GPU的可编程能力,需要ShaderModel2.0和浮点型纹理支持;其次是因为每次出发拾取程序的时候都要在后台绘制一张表面,等同于重复绘制了两次场景,不适合频繁连续的