OpenGL程序中三维实体的选取技术
OpenGL是近几年发展起来的一个性能卓越的三维图形标准, 由于其开放性和独立于操作系统, 目前已成为业界应用最广泛的三维图形应用程序接口 (API) [1]。
OpenGL的优良性能使其成为三维人机交互程序开发的首选平台。然而, 在众多的介绍OpenGL程序开发的书籍中, 对如何使用鼠标选取程序中的三维实体并进行人机交互的方法介绍得很少。对三维实体的选取在很多交互式OpenGL程序中都是非常重要的人机交互手段, 本文将针对这一技术进行分析, 提出具体的实现方法。
1 三维实体的特殊性
现在的交互式OpenGL程序大多数都允许用户使用鼠标选择屏幕上的物体, 以便进行修改、移动、删除或其它的操作。然而对三维实体的选择因为其特殊性, 在实现上存在一定难度, 下面对平面和三维情况下选择物体的方式进行对比。
有过平面图形编程经验的人都知道, 一般情况下, 对平面区域的选择是比较简单的。当用户点击鼠标时, 程序根据事先定义的平面区域的坐标区间与鼠标点击时所处的坐标相比较, 立即可以判断出鼠标是否在平面区域内被点击, 从而确定平面区域是否被选中。
相比之下, 用鼠标选取三维实体就困难得多。这是因为, 最终显示在屏幕上的三维图像实际上只是三维实体的二维表示, 或者可以说是三维实体的投影。通常投影有两种方式, 即正交投影和透视投影。正交投影的特点是不受距离的影响, 投影的大小总是等于对象的实际大小, 这种投影方式多用于工程制图中。透视投影的特点是它受到距离的影响, 对象距离投影面越远, 其投影就越小, 这与真实世界是相符的。不论采用哪一种投影方式, 用鼠标选择物体时, 实际上点击的是物体的投影。而当物体经历多次旋转和平移变换时, 通常其投影的位置、大小和形状都将发生改变, 所以无法使用选择平面区域的方法去用鼠标选择三维实体。
2 OpenGL实用库 (GLU) 函数选取三维实体
通过使用OpenGL实用库函数[2], 我们可以比较容易地进行选择。其主要步骤是:
(1) 分配一个数组作为存放被选择实体信息的缓冲区, 使用glSelectBuffer () 函数选择这个数组。
(2) glRenderMode () 函数, 参数设为G L_S E L E C T, 使程序进入选择模式 (selection mode) 。
(3) glInitNames () 和glPushName () 函数, 初始化名字堆栈 (name stack) 。
(4) glu Pick Matrix () 和glu Perspective () 函数, 进行视图变换, 在此之前需要调用glPushMatrix () 函数保存变换状态。
(5) 绘制场景中的各个实体。
(6) gluPopMatrix () 恢复原来的变换状态, g l R e n d e r M o d e () 函数参数设为GL_RENDER, 使程序进入正常渲染模式, 同时得到被选中的实体数量。
(7) 如果被选中的实体数量多于1个, 则对其进行排序, 保证距离屏幕最近的实体被选择。
这些步骤中关键的在于第2步和第5步。OpenGL的选择模式是一种特殊的光栅化模式, 在这种模式下, 并不会在屏幕上画出任何东西, 而是将各个实体的信息存入缓冲区, 在这种模式中, 颜色、深度、模板和累积缓存的内容不受影响。由于选择模式的这个特点, 我们可以把各个实体的绘制单独编写成一个函数DrawObjects () , 这个函数既可以在普通模式下绘制屏幕上看得见的实体, 又可以在选择模式下绘制实体。
3 使用设备无关位图 (DIB) 和颜色查询表来选取三维实体
这种方法的思路是以下几点。
(1) 捕捉鼠标点击发生的位置 (x, y) 。
(2) 建立一个颜色查询表, 为场景中的每一个实体分配一种特定的颜色。
(3) 使用颜色查询表中指定的颜色在内存中画出所有实体, 结果并不显示在屏幕上。
(4) 找到点 (x, y) 位置对应的颜色, 根据这种颜色在颜色查询表中找到相对应的三维实体。
(5) 重新以各实体本来的颜色和纹理进行绘制, 并将结果输出至屏幕。
这种方法的实现要借助于DIB。在上述步骤的第 (3) 步中, 我们需要向内存中的DIB绘制专门用来选择实体的临时画面, 只有这样, 使用者才不会察觉到屏幕画面的变化;而在第 (5) 步中, 最终显示在屏幕上的画面也是事先绘制在D I B中, 然后通过BitBlt函数输出到屏幕。
4 结语
本文介绍的两种在OpenGL程序中选取三维实体的技术各有特点。从原理上来说, 第一种方法较难于理解, 第二种方法则浅显易懂;从实现上来说, 第一种方法的代码较少, 第二种方法的代码较多, 但如果将所需的设备无关位图及其相关操作封装成一个可重用的类, 则可以大大提高编程效率;从运行效率来看, 第二种方法因为需要在内存中预先绘制场景, 所以效率比第一种方法要低, 但在计算机硬件速度不断提升的当今, 这种差别并不明显。
本文所介绍的两种方法具有通用性, 可广泛适用于各类交互式OpenGL程序, 使用时可以根据需要选择其一。
摘要:本文分析了OpenGL程序中实现对三维实体实现选取的意义和难点, 提出了选取三维实体的两种具体方法, 并对这两种方法进行了比较。
关键词:OpenGL,三维实体,选取技术
参考文献
[1] Mason Woo, 等[著], 吴斌, 等[译].OpenGL权威编程指南[M].北京:中国电力出版社, 2001.
[2] Microsoft Corp.MSDN Library 6.0[CP/CD].Microsoft Corp, 1998.