




已阅读5页,还剩27页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
论文题目 基于 OpenGL 的屏幕对象拾取 II 毕业论文 设计 原创性声明毕业论文 设计 原创性声明 本人所呈交的毕业论文 设计 是我在导师的指导下进行的研究工作及取得的研本人所呈交的毕业论文 设计 是我在导师的指导下进行的研究工作及取得的研 究成果 据我所知 除文中已经注明引用的内容外 本论文 设计 不包含其他个人究成果 据我所知 除文中已经注明引用的内容外 本论文 设计 不包含其他个人 已经发表或撰写过的研究成果 对本论文 设计 的研究做出重要贡献的个人和集体 已经发表或撰写过的研究成果 对本论文 设计 的研究做出重要贡献的个人和集体 均已在文中作了明确说明并表示谢意 均已在文中作了明确说明并表示谢意 作者签名 作者签名 日期 日期 毕业论文 设计 授权使用说明毕业论文 设计 授权使用说明 本论文 设计 作者完全了解本论文 设计 作者完全了解 学院有关保留 使用毕业论文 设计 学院有关保留 使用毕业论文 设计 的规定 学校有权保留论文 设计 并向相关部门送交论文 设计 的电的规定 学校有权保留论文 设计 并向相关部门送交论文 设计 的电 子版和纸质版 有权将论文 设计 用于非赢利目的的少量复制并允许论子版和纸质版 有权将论文 设计 用于非赢利目的的少量复制并允许论 文 设计 进入学校图书馆被查阅 学校可以公布论文 设计 的全部或文 设计 进入学校图书馆被查阅 学校可以公布论文 设计 的全部或 部分内容 保密的论文 设计 在解密后适用本规定 部分内容 保密的论文 设计 在解密后适用本规定 作者签名 作者签名 指导教师签名 指导教师签名 日期 日期 日期 日期 III 注 意 事 项 1 设计 论文 的内容包括 1 封面 按教务处制定的标准封面格式制作 2 原创性声明 3 中文摘要 300 字左右 关键词 4 外文摘要 关键词 5 目次页 附件不统一编入 6 论文主体部分 引言 或绪论 正文 结论 7 参考文献 8 致谢 9 附录 对论文支持必要时 2 论文字数要求 理工类设计 论文 正文字数不少于 1 万字 不包括图纸 程序清单等 文科 类论文正文字数不少于 1 2 万字 3 附件包括 任务书 开题报告 外文译文 译文原文 复印件 4 文字 图表要求 1 文字通顺 语言流畅 书写字迹工整 打印字体及大小符合要求 无错别字 不准请他人 代写 2 工程设计类题目的图纸 要求部分用尺规绘制 部分用计算机绘制 所有图纸应符合国家 技术标准规范 图表整洁 布局合理 文字注释必须使用工程字书写 不准用徒手画 3 毕业论文须用 A4 单面打印 论文 50 页以上的双面打印 4 图表应绘制于无格子的页面上 5 软件工程类课题应有程序清单 并提供电子文档 5 装订顺序 1 设计 论文 2 附件 按照任务书 开题报告 外文译文 译文原文 复印件 次序装订 3 其它 IV 目录目录 摘要 1 ABSTRACT 2 1 绪论 3 1 1 课题的目的和意义 3 1 2 1 2 1 2 拾取技术国内外研究 拾取技术国内外研究拾取技术国内外研究 3 1 3 本论文研究主要内容 3 2 基于 OPENGL MFC 的建模基础 5 2 1 OpenGL 概括 5 2 2 OpenGL 渲染管线过程 5 2 2 1 顶点变换 6 2 2 2 图元组装 6 2 2 3 图元处理 6 2 2 4 片元处理 6 2 2 5 光栅化操作 6 2 3 MFC 概述 6 2 4 MFC 特点 7 2 4 1 封装 7 2 4 2 继承 8 2 4 3 虚拟函数和动态约束 8 2 5 应用程序的构成 8 2 6 基于 OpenGL MFC 的三维模拟的编程环境配置 9 3 拾取技术 12 3 1 基于射线求交拾取技术 12 3 1 1 判断线段和包围盒的相对位置 12 3 2 基于 GPU 的重绘式拾取技术 14 3 3 各种拾取技术比较 16 4 系统的设计及实现 18 4 1 系统的选择机制 18 4 1 1 进入选择模式之前 18 4 1 2 获取当前选择模式 18 4 1 3 退出选择模式 20 4 1 4 拾取 20 4 2 拾取结果截图 21 5 结论与展望 25 5 1 结论 25 5 2 展望 25 参考文献 26 致谢 28 1 摘要摘要 屏幕对象的拾取是计算机图形处理系统中一个重要的功能 在许多情况下 计算机图形处理系 统不仅要绘制图形 而且要允许操作者能够通过输入设备 通常是鼠标 操纵屏幕上的物体 标识 移动和修改 有时还需要获取物体上点的空间坐标或测量物体的几何特性如距离 角度 半径等 这些操作都需要以拾取作为实现的基础 OpenGL 为了解决拾取问题 提供了一种基于名字堆栈和 命中记录的选择机制 在 OpenGL 中 拾取物体是利用拾取矩阵和投影变换 将拾取的范围限制在鼠 标热点的有效区中 一旦触发鼠标事件就进入选择模式并将有效区初始化 最后利用拾取矩阵拾取 有效区内的物体 有效区的定义由 glPick2Matix 函数来完成 一旦拾取成功 就以记录的形式 返回与拾取物体相关的信息 并生成一个记录表示一个物体被命中 这种物体拾取方法非常简单 不需要写很多代码 在使用 OpenGL 工具包开发图形处理系统时 物体的拾取有多种方法 其中包括 OpenGL 提供的 选择机制 射线拾取法 重绘式拾取法等 本文采用 OpenGL 本身提供的选择机制来拾取对象 突 出 OpenGL 工具包在屏幕对象的拾取方面的优势 关关 键键 词 词 OpenGL 计算机应用 拾取算法 2 AbstractAbstract In 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 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 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 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 KeyKey words words OpenGL computer application picking 3 1 1 绪论绪论 目前许多优秀的图形工具能为我们绘制惟妙惟肖的虚拟现实场景 在面对这些场景时候我们除 了欣赏之外更多的是希望能与之互动 做为编程人员可以使用代码轻松的重新构造场景 但对于终 端用户而言 他们也希望自己也能对造场景进行一些操作 如添加 删除等等 对于这些操作而言 首先我们要做的是能让用户使用鼠标来选择他所希望操作的对象 这就是本文要讨论的一个重点 拾取 这是一种在许多交互性程序中有基础地位的操作 是对屏幕中对象进行定位 并确定所选择 的是哪个物体 然而该操作给我们提出了一些难题 首先 需要对对象进行届定 其次 必须对 拾取目标 进行定义 这就需要终端用户确定单击的位置是构成对象的图元上 还是对象附近的 位置以及考虑如果选取点落在两个以上物体交集部分如何处理等等问题 本文利用了 OpenGL 中的 选择模式进行有效的对象判别和拾取 1 11 1 课题的目的和意义课题的目的和意义 图形对象的拾取是计算机图形处理系统中一个重要的功能 很多图形系统需要用户通过输入设 备与系统交互 如移动 旋转某个物体 或查询某个物体的状态信息 需要通过拾取来确定景中的 操作对象 快速可靠的拾取被广泛地运用于各种系统中 如实时图形系统 虚拟现实 游戏和 CAD 系统等方面 拾取操作己成为这些系统的重要部分 它在计算机建模软件尤其重要 能够通过拾取 操作对模型进行局部修改和编辑 提高建模系统的灵活性和适用性 随着计算机软硬件的快速发展 人们对实时系统的交互的实时性要求也越发苛刻 而且三维场景复杂度也日益提高 这就要求系统 提供快速的拾取操作 因此 高效的拾取算法能够决定拾取操作快与慢的关键所在 从而开发高效 的拾取算法已成为当今一个的课题研究 1 1 2 2 拾取技术国内外研究拾取技术国内外研究 随着网络科技越来越发达 拾取操作也越来越方便了 有的只要鼠标点点就可以 而拾取操作 的关键是拾取算法 到目前为止 拾取算法大致上可以分三种 第一种是基于射线求交的拾取技术 1992 年 Mark Segul Carl Korobkin Rolf van Widenfelt 等人首次采用了基于射线求交的拾取 技术原理实现了对衣服的拾取 1 1998 年 Michael Deering Step hanie Winner and Bic Schediwy 等也才采用了同样的技术成功做到了人物的拾取 2 2005 年 龚堰珏 颜敏等人采用了 基于射线求交的拾取技术实现对几个简单物体的拾取 3 同年 韦宇炜也是用此技术实现对游戏中 各类的拾取 如对技能的释放 对地上物品的捡起来 对别的玩家人物属性的查看等等 4 2006 年 姚继权 李晓豁等人也采用了这种拾取技术成功地做到了对 3D 网游游戏中的各种各样的拾取 5 等等 第二种是基于 GPU 的重绘式拾取技术 这种方法对硬件的依赖性大 不过拾取速度快 1997 年 Masaaki Oka Kyoya 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 在各个领域都得到了应用 8 随后出现的各个版本 使自 带的拾取机制越来越完善 操作越来越方便 应用范围越来越广泛 1 31 3 本文本文研究的主要内容研究的主要内容 一 综述本课题研究的意义以及国内外研究现状 二 介绍了 OpenGL 与 OpenGL 渲染管道 分析 MFC 编程框架和基于 OpenGL MFC 的三维模拟的编程 环境配置 三 各种拾取技术的实现原理 优缺点 四 采用了 OpenGL 本身自带的拾取机制设计并实现简单的拾取操作 4 五 总结本文并进一步给出了展望 5 2 2 基于基于 OpenGLOpenGL MFCMFC 的建模基础的建模基础 2 12 1 OpenGLOpenGL 概括概括 OpenGL 全写 Open Graphics Library 是个定义了一个跨编程语言 跨平台的编程软件接口 的规格 该接口包括了大约 250 个不同的函数 其中核心 OpenGL 大约包括 200 个函数 另外还有 50 个左右位于 OpenGL 工具函数库 可以用这些函数指定物体和操作 创建交互性三维应用程序 它是个专业的图形程序接口 是一个功能强大 调用方便的底层图形库 Opengl 用于三维图象 二维的亦可 OpenGL 的设计目标就是作为一种流线型的 独立于硬件的接口 可以在许多不同的硬件平台 上实现 为了实现这个目标 OpenGL 并未包含用于执行窗口任务或者获取用户输入之类的函数 反之 必须通过窗口系统控制所使用的特定硬件 类似地 OpenGL 并没有提供用于描述三维物体 模型的高层函数 这类函数可能允许你指定相对较为复杂的形状 例如汽车 身体的某 个部位 飞机或分子等 在 OpenGL 中 必须根据少数几个基本几何图元 geometric primitive 如点 直线和多边形 来创建你所需要的模型 当然 我们可以在 OpenGL 上创建能够提供这些特性的高 级函数库 OpenGL 实用函数库 GLU 提供了许多建模特性 例如二次曲面以及 NURBS 曲线和表面 GLU 是所有 OpenGL 实现的一个标准组成部分 1992 年 7 月 SGI 公司发布了 OpenGL 的 1 0 版本 随后又与微软公司共同开发了 Windows NT 版本的 OpenGL 从而使一些原来必须在高档图形工作站上运行的大型 3D 图形处理软件也可以在微 机上运用 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 图形设计软件也可以运用支持 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 接口发展指明方向 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 22 2 OpenGLOpenGL 渲染管线过程渲染管线过程 管线这个术语用于描述一种过程 它涉及两个或更多个独特的阶段或步骤 当应用程序进行 OpenGL API 调用时 这些命令被放置在一个命令缓冲区中 这个缓冲区最终填满了命令 顶点数 据 纹理数据等 当缓冲区被刷新时 命令和数据就被传递给管线的下一个阶段 通常 顶点数据 首先进行转换和光照 在转换阶段 描述物体几何形状的点被重新计算 以确定这个物体的位置和 6 方向 同时所进行的光照计算将确定每个顶点应该具有的颜色亮度 当这个阶段完成之后 数据就 被输入到管线的光栅化部分 光栅阶段根据几何图形 颜色和纹理数据实际创建彩色图像 然后 图像被放入帧缓冲区中 帧缓冲区就是图形显示设备的内存 这意味着这幅图像将会在屏幕上显示 图 1 显示了 OpenGL 工作流程图顺序 虽然并没有严格规定 OpenGL 必须采用这样的实现 但它却提 供了一个可靠的指南方向 可以预测 OpenGL 将以什么样的顺序来执行这些操作 图 1 Opengl 工作渲染流程图 OpenGL 渲染管线的操作过程主要包括以下几部分 1 顶点变换 2 图元组装 3 图元处理 4 片元处理 5 光栅化操作 2 2 12 2 1 顶点变换顶点变换 这个阶段主要是对输入的顶点进行逐个处理 这些顶点都包括很多属性 如位置 颜色 法线 和纹理坐标等 经过处理后 输出是经过变换后的顶点属性及关联信息 主要过程 顶点变换 几何变换和投影变换 光照计算 纹理坐标变换和生成 2 2 22 2 2 图元组装图元组装 这个阶段主要是按照输入的变换后的顶点属性和关联信息 组装形成图元 2 2 32 2 3 图元处理图元处理 这个阶段主要是对输入的图元进行处理 输出片元 帧缓存中更新象素属性的数据 信息 该 片元信息是对顶点变换阶段得出的属性进行插值处理得到的 主要过程 视景裁剪 背面剔除 2 2 42 2 4 片元处理片元处理 这个阶段的输入为经过插值计算后的最终片元信息 经过处理后 输出信息为片元的深度和颜 色值 主要过程 纹理 雾化 颜色汇总 包括纹理颜色 光照颜色 主颜色等 2 2 52 2 5 光栅化操作光栅化操作 这个阶段的输入为像素位置和片元的深度 颜色值等信息 经过一系列的测试 剪切测试 Alpha 测试 模板测试和深度测试 后形成像素的颜色 主要过程 剪切测试 Alpha 测试 模板测试和深度测试 写入帧缓存 2 32 3 MFCMFC 概述概述 MFC Microsoft Foundation Class Library 中的各种类结合起来构成了一个应用程序框架 7 它的目的就是让程序员在此基础上来建立 Windows 下的应用程序 这是一种相对 SDK 来说更为简单 的方法 因为总体上 MFC 框架定义了应用程序的轮廓 并提供了用户接口的标准实现方法 程序 员所要做的就是通过预定义的接口把具体应用程序特有的东西填入这个轮廓 Microsoft Visual C 提供了相应的工具来完成这个工作 AppWizard 可以用来生成初步的框架文件 代码和资源等 资源编辑器用于帮助直观地设计用户接口 ClassWizard 用来协助添加代码到框架文件 最后 编 译 则通过类库实现了应用程序特定的逻辑 MFC 是在 1992 年随微软的 Microsoft C C 7 0 编译器发布的 用于面向 16 位 Windows 的软 件开发 起初 MFC 是作为一个应用程序框架开发的 所以定名为 Application FrameworkX AFX Borland 几乎同时发布了面向 Turbo C 编译器的 OWL 并且在一开始比 MFC 更具有市场占有率 但是在 Borland 发布了一个不向下兼容的应用程序框架之后 它丧失了很多市场份额 在 Borland 从微软获得发布 MFC 的授权之后它的市场份额进一步减少 Borland 最终用 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 的基础上进一步实现了皮肤 渐变风格 多顶层窗口程序 属性列表等较 受欢迎的功能 同时 在 C 在线社区中 很大一部分开放的源代码也是基于 MFC 的 VC 产品版本与 MFC 版本如下 表格 1 VC 产品版本与 MFC 版本 2 42 4 MFCMFC 特点特点 2 4 12 4 1 封装封装 构成 MFC 框架的是 MFC 类库 MFC 类库是 C 类库 这些类或者封装了 Win32 应用程序编程接 8 口 或者封装了应用程序的概念 或者封装了 OLE 特性 或者封装了 ODBC 和 DAO 数据访问的功能 等等 分述如下 1 对 Win32 应用程序编程接口的封装 2 对应用程序概念的封装 3 对 COM OLE 特性的封装 4 对 ODBC 功能的封装 2 4 22 4 2 继承继承 首先 MFC 抽象出众多类的共同特性 设计出一些基类作为实现其他类的基础 这些类中 最 重要的类是 CObject 和 CCmdTarget CObject 是 MFC 的根类 绝大多数 MFC 类是其派生的 包括 CCmdTarget CObject 实现了一些重要的特性 包括动态类信息 动态创建 对象序列化 对程序 调试的支持 等等 所有从 CObject 派生的类都将具备或者可以具备 CObject 所拥有的特性 CCmdTarget 通过封装一些属性和方法 提供了消息处理的架构 MFC 中 任何可以处理消息的类都 从 CCmdTarget 派生 针对每种不同的对象 MFC 都设计了一组类对这些对象进行封装 每一组类都有一个基类 从 基类派生出众多更具体的类 这些对象包括以下种类 窗口对象 基类是 CWnd 应用程序对象 基类是 CwinThread 文档对象 基类是 Cdocument 等等 2 4 32 4 3 虚拟函数和动态约束虚拟函数和动态约束 MFC 以 C 为基础 自然支持虚拟函数和动态约束 但是作为一个编程框架 有一个问题 必须解决 如果仅仅通过虚拟函数来支持动态约束 必然导致虚拟函数表过于臃肿 消耗内存 效 率低下 例如 CWnd 封装 Windows 窗口对象时 每一条 Windows 消息对应一个成员函数 这些成 员函数为派生类所继承 如果这些函数都设计成虚拟函数 由于数量太多 实现起来不现实 于是 MFC 建立了消息映射机制 以一种富有效率 便于使用的手段解决消息处理函数的动态约束问题 2 52 5 应用程序的构成应用程序的构成 图 2 解释了该应用程序的结构与对象 箭头表示信息流向 图 2 应用程序的结构 从 CWinApp CDocument CView CMDIFrameWnd CMDIChildWnd 类对应地派生出 CTApp CTDoc CTView CMainFrame CChildFrame 五个类 这五个类的实例分别是应用程序对象 9 文档对象 视对象 主框架窗口对象和文档边框窗口对象 主框架窗口包含了视窗口 工具条和状 态栏 对这些类或者对象解释如下 1 应用程序 CWinApp 应用程序类派生于 CWinApp 基于框架的应用程序必须有且只有一个应用程序对象 它负责应 用程序的初始化 运行和结束 2 边框窗口 CMDIFrameWnd 如果是 SDI 应用程序 从 CFrameWnd 类派生边框窗口类 边框窗口的客户子窗口 MDIClient 直接包含视窗口 如果是 MDI 应用程序 从 CMDIFrameWnd 类派生边框窗口类 边框窗口的客户子 窗口 MDIClient 直接包含文档边框窗口 如果要支持工具条 状态栏 则派生的边框窗口类还要 添加 CToolBar 和 CStatusBar 类型的成员变量 以及在一个 OnCreate 消息处理函数中初始化这两 个控制窗口 边框窗口用来管理文档边框窗口 视窗口 工具条 菜单 加速键等 协调半模式状态 如上 下文的帮助 SHIFT F1 模式 和打印预览 3 文档边框窗口 CMDIChildWnd 文档边框窗口类从 CMDIChildWnd 类派生 MDI 应用程序使用文档边框窗口来包含视窗口 4 文档 CDocument 文档类从 CDocument 类派生 用来管理数据 数据的变化 存取都是通过文档实现的 视窗口 通过文档对象来访问和更新数据 5 视 CView 视类从 CView 或它的派生类派生 视和文档联系在一起 在文档和用户之间起中介作用 即视 在屏幕上显示文档的内容 并把用户输入转换成对文档的操作 用图的形式可直观地表示所涉及的 MFC 类的继承或者派生关系 如下 图 3 MFC 的层次 2 62 6 基于基于 OpenGL MFCOpenGL MFC 的三维模拟的编程环境配置的三维模拟的编程环境配置 用 MFC 调用 OpenGL 函数来进行三维模拟的编程环境配置 一 创建 MFC 项目 1 创建项目文件 选择 File New 菜单选项 建立一个名为 MyTest 的单文档 SDI 应用程序 二 配置 OpenGL 开发环境 1 将 91 h glu h glaux h 和 glut h 拷贝到 即盘符 路径 Microsoft Visual Studio VC98 Include GL 目录中 10 2 将 opengl32 1ib glu32 1ib glaux 1ib 和 glut32 1ib 拷贝到 即盘符 路径 Microsoft Visual Studio Vc98 Lib 目录中 3 将 opengl32 dll glu dll glu32 dll glut dll glut32 dll 文件拷贝到操作系统安装目 录 C WINDOWS system32 目录下 4 选择 Project Setting 菜单选项 在 Link 栏的 Lib 输入域中添加 openg132 lib glu32 lib 若需使用 OpenGL 的辅助库函数 则还需添加 glaux lib 到此 基于 OpenGL MFC 的开发环境就建立好 三 初始化 OpenGL 具体编程步骤 第一步 修改窗口风格设置 需要在函数 CGLView PreCreateWindow 中增加对 Windows 窗口风格的设置 以防止在窗口重叠 时把图形绘制到子窗口和兄弟窗口 实现代码如下 cs style l WS CLIPCHILDREN WS CLIPSIBLINGS 第二步 设置像素格式 首先需要在视图类 CGLView 中添加一个成员函数 函数原型如下 BOOL CGLView SetupPixelFormat CDC pDC 设置像素格式并向视图类 CGLView 中添加两个成员变量 CDC m pDC OpenGL 设备场境 HGLRC m hRC OpenGL 渲染场境在 Windows 中 使用结构 PIXELFO 腿 ATDEscRIPTOR 来设置像素格式 并提供 ChoosePixelFormat 函数来选择最为匹配的像素格式 以及 SetPixelFormat 函数来为设备场境设置像素格式 设置像素格式的步骤如下 a 填写结构 PIXELFORMATDESCRIPTOR 像素格式是用这个结构来描述的 b 调用函数 ChoosePixelFormat 将填写好的像素格式结构传递给该函数 函数 ChoosePixelFormat 返回一个整型的序号 这个序号标识一个当前设备场境中所能提供的 且与 所要求的像素格式最为匹配的像素格式 c 将这个返回的像素格式序号传递给函数 SetPixelFormat 使之设置成为当前设备场境的像素 格式 第三步 创建渲染场境 用 wglreatecontext 函数来创建 OpenGL 的一个渲染场境 用 wglMakeCurrent 函数使给定的渲 染场境设置成为当前调用线程的渲染场境 而线程中随后调用的 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 A CGLView OnCreate 函数 该函数完成的功能是 在视图窗口创建完成后 进行 OpenGLWindows 的初始化工作 四 清理工作 CGLView OnDestroy 函数 该函数完成的功能是 在视图窗口被释放时 用于清除当前的渲染场境 并释放设备场境 具体实 现代码如下 11 wglMakeCurrent NULL NULL wglDeleteContext m hglRC 清除渲染场境 ReleaseDC m hWnd m hDC 释放设备场境 C CGLView OnSize 函数 D CGLView OnTimer 函数 该函数完成的功能是 通过定时器每隔一定时间的消息驱动 来实现动态的场景更新 12 3 3 拾取技术拾取技术 拾取算法的研究可大致分为两类 一类是基于三维空间的射线拾取算法 代表算法就是基于 CPU 的射线求交拾取技术 另一类是基于图像空间的拾取算法 例如 基于 GPU 的重绘式拾取技术 3 13 1 基于射线求交拾取技术基于射线求交拾取技术 其基本原理是 获取屏幕坐标并转换成图形系统的视口坐标 根据不同图形 API 应用程序编 程接口 的实现给该点加上适当的深度值 如 OpenGL 标准的深度值介于 0 1 反算出该拾取点的世 界空间坐标 将相机焦点坐标转换为屏幕坐标 过相机位置点向鼠标选中点作一条射线在三维空间 中对射线和物体进行求交 离相机位置点最近的实体就是被选中的实体 算法的具体实现步骤如下 1 初始化 获取鼠标点的屏幕坐标 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 交点的参数值 并将该实体标记为选中对象 如不相交 则进行下一个实体的处理 在上述算法中 判断线段 AB 和实体包围盒的相对位置及线段 AB 和实体的求交是算法实现的关 键 为了提高拾取速度 对传统的包围盒算法和求交算法进行了改进 3 1 13 1 1 判断线段和包围盒的相对位置判断线段和包围盒的相对位置 实体的最大包围盒是一个各表面平行于坐标平面的六面体 其左下顶点的 x y z 坐标值为实 体所有顶点相应坐标值的最小值 其右上顶点的坐标值为实体所有顶点相应坐标值的最大值 采用向量法来判断线段和包围盒相对位置 该算法的基本思想为 将线段看成一个由起点指向 终点的向量 求向量各分量和离起点最近的三个包围盒侧面所在平面的交点 如果各分量与平面的 交点都在包围盒侧面上或者在包围盒内且在各分量上 则该线段和包围盒相交 本文中我们把线段 与包围盒相交和线段在包围盒内这两种情况统称为相交 判断线段与包围盒相对位置的具体步骤如下 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 值求出交点坐标 判断交点是否在包围盒上 此处最好给出交点坐标的计算式 以及 交点是否在包围盒上的判断算式 如果交点在盒上 则 AB 和包围盒相交 否则 AB 和包围盒相 离 13 图 4 线段 AB 和包围盒的位置关系图 判断线段与包围盒相对位置的算法流程如图 5 所示 图 5 向量法判断线段和包围盒相对位置算法流程图 根据拾取对象的不同 线段和相关对象求交的方法和过程存在差别 设要和拾取对象求交的线 段为 AB 针对不同的情况 下面对两种求交过程分别加以描述 1 拾取对象为点 当拾取对象为点时 求交的实质就是以 AB 为轴线 以一个很小的浮点数 tolerance tolerance 一般小于 0 001 为半径做一个圆柱 在这个圆柱内离视点最近的点就是所求 的交点 具体做法是将实体的每一个顶点向 AB 投影 并求出投影点在线段 AB 上的参数坐标 在 0 到 1 的范围内 参数坐标的值越小 说明该点离视点越近 如果我们发现了某个实体顶点比当前的 最近点离视点更近且该点到 AB 所在直线的距离小于 tolerance 则把该点记录为当前的最近点 当所有的点处理完毕 当前的最近点就是该实体和线段 AB 的交点 14 2 拾取对象为直线或复合线 复合线一般指由多个直线段相连接所构成的单元体 在本文所述的三维图形浏览器系统中 曲 线如 NURBS 曲线 圆弧等都存储为复合线的形式 对于线状图元 比较常用的方法是通过计算点线 距离来进行拾取 这种方法简单易懂 易于实现 但当拾取曲线 复杂折线等图元时 计算量会非 常大 为此提出一种新的改进算法 其具体操作步骤如下 以拾取点为中心 两倍拾取精度 在本文中拾取精度一般为象素宽度的 2 5 倍 为边长 绘制一 个以背景色为填充色的正方形作为 测试窗口 如图 6 所示 图 6 测试窗口 重绘图形对象 如果图元进入拾取范围 则必然在 测试区 中留下轨迹 重绘图形对象的目的 是为了恢复可能被 测试窗口 遮蔽的图形对象 循环读取 测试窗口 中象素点颜色 当发现象素点颜色有别于背景色时 终止读点 标识拾取成 功 若未发现有别于背景色的象素点时 则继续进行下一个图元的检测 如图 7 所示 图 7 测试区中的轨迹 3 23 2 基于基于 GPUGPU 的重绘式拾取技术的重绘式拾取技术 基本思路 重绘式拾取法是在 OpenGL 绘图模式下 通过 2 次绘图来拾取并显示物体 第 1 次绘图为虚拟绘 图 通过在 OpenGL 帧缓存中绘制一些辅助图形来帮助选取物体 这些辅助图形对于系统使用者是 不 可见的 因此在确定所选物体之后要将辅助图形从帧缓存中清除掉才能进行第 2 次绘图 第 2 次绘 图为实际绘图 所绘图形为系统使用者看到的真实图形 在 GPU 上实现三维图元拾取的方法有两种 第一种方法与场景几何无关 第二种方法是场景几 何依赖 下面介绍第一种方法 场景几何无关方法的应用一直受到限制 它需要 GPU 的可编程能力 需要 ShaderModel2 0 和 浮点型纹理支持 其次是因为每次出发拾取程序的时候都要在后台绘制一张表面 等同于重复绘制 了两次场景 不适合频繁连续的拾取动作 该方法的核心是把图元的几何信息 指针等相关信息作为它的颜色渲染到后台的一张 Render Target 型表面上对应帧缓冲做一次特殊的 渲染 在渲染后只要读取表面上相应像素坐标的颜色 值就可以得知它相对应图元的信息 整个算法分为在 CPU 上和在 GPU 上的两部分 在 CPU 上 C 程 序的任务是建立一个后台的表面 然后调用 GPU 上的程序对物体进行特殊的 RTT Rallderto Texture 渲染到纹理 再根据渲染结果读取表面某坐标的颜色并还原信息 具体实现时考虑到纹 理有 pow of two 和 non pow of two 之别 屏幕分辨率一般不为 pow of two 因此可以考虑采用 渲染到表面 RRS 用 Direct3D9 中的 CreateRenderTarget 创建一个 Render Target 型表面 CPU 上的主要流程如下 15 鼠标点击拾取事件触发下面流程 1 建立一张新的临时纹理 2 将当前设备屏幕的内容存入缓冲中 将设备的渲染对象设为该临时纹理 3 做好渲染前的准备 包括从 fx 文件中读入 effect 4 对于每个几何对象在 GPU 通过 Shader 进行特殊渲染 5 还原设备信息 设备的渲染对象指向帧缓冲 6 获取临时纹理上拾取区域的像素 7 将获得的像素按定义的格式解码 图 8 说明了上述整个流程 图 8 GPU 拾取流程 下面定义 Vertex Shader 的输出内容 定义了一个包括坐标和颜色的结构 struct 其中 pos 用于顶点转换 color 用于顶点信息存储 Struct VSResult Float4 pos POSITION Float4 color TEXCOORDO 在 Vertex Shader 中 输入某点的局部坐标 把坐标的值编码成一个颜色的 RGB 值后作为输出 颜色的 RGB 值 同时将输入坐标向量左乘世界矩阵 观察矩阵 投影矩阵后得到最终输出的坐标值 在 Pixel Shader 中 将物体指针信息作为颜色的 Alpha 值 加上 Vertex Shader 输出的颜色 输 出为最终的渲染颜色 在单个几何图元中 不同顶点有不同的坐标 在 Vertex Shader 中 根据坐标信息进行顶点转 换 同时将坐标信息作为颜色值存入 VSResult 中 主要如下 VSResult Vs main float3 pos POSITION VSResult ret 16 ret color float4 pos 1 of float4 worldpos mul float4 pos 1 worldmatrix ret pos mul worldpos ViewProjection return ret 对于 ret color 前 3 个 RGB 值表示输入的位置坐标 而第 4 个 Alpha 值用作存储其他信息 暂时填入 1 Of 后文将填充图元的指针 3 33 3 各种拾取技术比较各种拾取技术比较 各种拾取技术比较表如下 表 2 各种拾取技术比较 原理优点局限性 OpenGL 的选择机 制 先把场景画进帧缓冲 然后进 入选择模式并重新绘制这个场 景 当退出选择模式时 OpenGL 返回一个图元 premitives 清单 图元可能 被视见体 viewing volume 分 割 每个被视见体图元引出一 资选择命中 hit 确切的说 图元清单是作为一个取整数值 的名字 integer valued names 数组和相关的数据 命 中记录 hit record 对应名 字栈 name stack 的当前内容 当在选择模式下发布图元绘制 命令时向名字栈中加入名字就 可建立起名字栈 当名字清单 被返回后 可以用它来确定屏 幕上的哪个图元可能被用户选 中了 此算法简单 名字堆栈容量有限 不 能处理大规模场景中的 拾取 射线拾取 方法 获取屏幕坐标并转换成图形系 统的视口坐标 根据不同图形 API 应用程序编程接口 的实现 给该点加上适当的深度值 如 OpenGL 标准的深度值介于 0 1 反算出该拾取点的世界空间坐 标 并由视点向此点引一条射 线 在三维空间中对射线和物 体进行求交 对拾取对象为 点或简单的选 择体较为方便 速度快 1 因它假设所有的图 形变换矩阵必须可逆 经过一系列的逆运算可 得到图像空间某点的三 维坐标 但实际上这些 矩阵并非总是可逆 2 对于复杂的选择体 判断物体是否在选择体 内部的算法极其复杂 从而使整个处理过程耗 时巨大 且如此复杂的 算法也会给整个系统的 实现带来一定难度 1 没有采用 17 重绘式拾 取法 在 OpenGL 绘图模式下 通过 2 次绘图来拾取并显示物体 第 1 次绘图为虚拟绘图 通过在 OpenGL 帧缓存中绘制一些辅助 图形来帮助选取物体 这些辅 助图形对于系统使用者是不可 见的 因此在确定所选物体之 后要将辅助图形从帧缓存中清 除掉才能进行第 2 次绘图 第 2 次绘图为实际绘图 所绘图 形为系统使用者看到的真实图 形 OpenGL 选择机 制 整个拾取 过程都在 OpenGL 的绘图 模式下完成 因此不必要为 每个物体命名 同时 避免了 在绘图模式与 选择模式之间 的切换 2 灵活的拾取范 围 可以定义 各种形态的框 选 如圆形 方形 3 算 法简单 容易 实现 且容易 迁移到 GPU 上 利用硬件加速 拾取算法 依赖于硬件 与 GPU 的 性能息息相关 18 4 4 系统的设计及实现系统的设计及实现 有些图形应用程序只绘制两维和三维物体构成的静态图形 另一些允许用户识别屏幕上的物体 并移动 修改 删除或用其它方法操纵这些物体 OpenGL 正是设计用于支持这些交互式应用程序 的 因为绘制在屏幕上的物体通常经过多次旋转 移动和透视变换 所以确定用户选中了三维场景 中的哪
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
评论
0/150
提交评论