通常,当你打算使用OpenGL的选择机制时,你首先把你的场景画进帧缓冲,然后进入选择模式并重新绘制这个场景。然而,一旦你进入了选择模式,帧缓冲的内容将保存不变,直到你退出选择模式。当你退出时,OpenGL返回一个图元(premitives)清单,图元可能被视见体(viewing volume)分割(记住,视见体是由当前模式视见和投影矩阵及你定义的所有裁剪面定义,裁剪面详见"Additional Clipping Planes.")。每个被视见体图元引出一资选择命中(hit)。确切的说,图元清单是作为一个取整数值的名字(integer-valued names)数组和相关的数据-命中记录(hit record)-对应名字栈(name stack)的当前内容。当你在选择模式下发布图元绘制命令时向名字栈中加入名字就可建立起名字栈。这样,当名字清单被返回后,你就可以用它来确定屏幕上的哪个图元可能被用户选中了。
除了这个选择机制之外,OpenGL提供了一个工具例程,以便在某些情况下通过限定在视口(viewport)一个小区域内绘制来简化选择。通常你可以用这个例程决定哪个物体被画在光标附近了,这样你就能识别用户拾取了哪个物体。你也可以通过指定附加的裁剪面来界定一个选择区域;详见"Additional Clipping Planes"。因为拾取是选择的一个特殊情况,所以本章选讲选择,然后讲拾取。
基本步骤
建立名字矩阵
命中记录
一个选择的例子
拾取
关于编写使用选择的程序的提示
------------------------------------------------------------------------
基本步骤
为使用选择机制,你得作以下几步:
1、用glSelectBuffer()指定用于返回命中记录的数组。
2、以GL_SELECT为参数调用glRenderMode()进入选择模式。
3、用glInitName()和glPushName()初始化名字栈。
4、定义用于选择的视见体。通常它与你原来用于绘制场景的视见体不同。因此你或许会想用glPushMatrix()和glPopMatrix()来保存和恢复当前的变换矩阵。
5、交替发布图元绘制命令和名字栈控制命令,这样每个感兴趣的图元都会被指定适当的名字。
6、退出选择模式并处理返回的选择数据(命中记录)。
void glSelectBuffer(GLsizei size, GLuint *buffer);
指定用于返回选择数据的数组。参数buffer是指向无符号整数(unsigned integer)数组的指针,数据就存在这个数组中,size参数说明数组中最多能够保存的值的个数。要在进入选择模式之前调用glSelectBuffer()!
GLint glRenderMode(GLenum mode);
控制应用程序是否进入绚染(rendering)、选择或反馈模式。mode参数可以是GL_RENDER(默认)、GL_SELECT或GL_FEEDBACK之一。应用程序将保持处于给定模式,直到再次以不同的参数调用glRenderMode()。在进入选择模式之前必须调用glSelectBuffer()指定选择数组。类似的,进入反馈模式之前要调用glFeedbackBuffer()指定反馈数组。如果当前模式是GL_SELECT或GL_FEEDBACK之一,那么glRenderMode()的返回值有意义。返回值是当前退出当前模式时,选择命中数或放在反馈数组中的值的个数。(译者注:调用此函数就会退出当前模式);负值意味着选择或反馈数组溢出(overflowed)。你可以用GL_RENDER_MODE调用glGetIntegerv()获取当前模式。
-------------------------------------------------------------------------------
建立名字矩阵
正如前面提到的,名字栈是返回给你的选择信息的基础。要建立名字栈,首先用glInitNames()初始化它,这将简单地清空栈。然后当你发布相应的绘制命令时向其中加入整数名字。正如你可能想象,栈控制命令允许你压入名字(glPushName()),弹出名字(glPopName()),替换栈顶的名字(glLoadName())。
/********************************************************************/
Example 12-1: Creating a Name Stack
glInitNames();
glPushName(-1);
glPushMatrix(); /* save the current transformation state */
/*to do: create your desired viewing volume here */
glLoadName(1);
drawSomeObject();
glLoadName(2);
drawAnotherObject();
glLoadName(3);
drawYetAnotherObject();
drawJustOneMoreObject();
glPopMatrix (); /* restore the previous transformation state*/
/********************************************************************/
在这个例子中,前两个被绘制的物体有自己的名字,第三和第四个共用一个名字。这样,如果第三或第四个物体中的一个或全部引起一个选择命中,只有一个命中记录返回给你。如果处理命中记录时不想区分各个物体的话,可以让多个物体共享一个名字。
void glInitNames(void);
清空名字栈。
void glPushName(GLuint name);
将name压入名字栈。压入名字超过栈容量时将生成一个GL_STACK_OVERFLOW错误。名字栈深度因OpenGL实现(implementations)不同而不同,但最少要能容纳64个名字。你可以用参数GL_NAME_STACK_DEPTH调用glGetIntegerv()以获取名字栈深度。
void glPopName(void);
弹出名字栈栈顶的那一个名字。从空栈中弹出名字引发GL_STACK_UNDERFLOW错误。
void glLoadName(GLuint name);
用name取代名字栈栈顶的那个名字。如果栈是空的,刚调用过glInitName()后就是这样,glLoadName()生成一个GL_INVALID_OPRATION错。为避免这种情况,如果栈初始时是空的,那么在调用glLoadName()之前至少调用一次glPushName()以在名字栈中放上点东西。
如果不是在选择模式下,对glPushName()、glPopName()、glLoadName()的调用将被忽略。这使得在选择模式和正常的绚染模式下用相同的绘制代码大为简化。
-------------------------------------------------------------------------------
命中记录
在选择模式下,被视见体裁剪的每个图元引起一个选择命中。当前一个名字栈控制命令被执行或glRenderMode()被调用后,OpenGL将一个命中记录写进选择数组,如果从上一次名字栈操纵或glRenderMode()调用以来有了一个命中记录的话。这个过程中,共用同样名字的物体-例如:由多个图元组成的物体-不生成多个命中记录。当然,命中记录不保证会被写进数组中直到glRenderMode()被调用。
除图元之外,glRasterPos()产生的有效坐标也可以引起选择命中。在多边形的情况下,如果它已经被消隐掉的话不会有命中记录出现。
每个命中记录由四项组成,依次是:
当命中出现时名字栈中的名字数
至上次记录的命中以来,被视见体裁剪后的图元的所有顶点的窗口Z坐标的 最大和最小值
本次命中时名字栈的内容,最底元素最前。
当前你进入选择模式时,OpenGL初始化一个指针指向选择数组的起点。每写入一个命中记录,指针相应更新。如果写入一个命中记录会使数组中值的个数超过glSelectBuffer()的size参数时,OpenGL会写入尽可能多的记录并设置一个溢出标志。当用glRenderMode()退出选择模式时,这条命令返回被写入的记录的个数(包括一条部分记录如果有的话),清除名字栈,复位溢出标识,重置栈指针。如设定溢了出标识则返回值是-1。
分享到:
相关推荐
OpenGL选择机制是图形编程中的一个重要概念,特别是在交互式应用程序中,用户可能需要通过鼠标操作来选择屏幕上的特定对象。在“opengl选择机制,实现几个重叠物体的选择”这一主题中,我们将深入探讨如何在OpenGL中...
OpenGL的选择机制是在三维交互式应用程序中非常重要的功能,它允许用户通过鼠标在二维屏幕坐标空间中直接定位三维坐标空间的物体。这一机制通过将三维场景中的对象绘制到帧缓存中,然后在选择模式下重新绘制场景来...
通过分析和运行此程序,你可以更深入地理解OpenGL选择机制的工作原理。 总的来说,OpenGL的选择和交互技术为3D应用提供了强大的用户交互能力,使得用户能够轻松地与复杂的3D场景进行互动。在VC环境下,结合适当的...
### OpenGL配置环境与OpenGL扩展机制 #### 一、OpenGL配置环境概述 OpenGL(Open Graphics Library)是一种用于...同时,了解OpenGL不同版本之间的差异,有助于更好地选择合适的版本和扩展,以满足项目的特定需求。
OpenGL的实例,进入OpenGL学习的第一步
OpenGL选择模式是OpenGL库提供的一种高级特性,它允许用户在3D场景中...在实践中,需要注意选择模式对性能的影响,尤其是在大型场景中,可能需要寻找更高效的解决方案,如使用GPU编程技术或现代图形API提供的选择机制。
总的来说,通过理解OpenGL选择机制,以及如何在C++和MFC环境中实现这一机制,你可以为你的图形应用程序添加更丰富的用户交互功能,让用户能够方便地选择和操作屏幕上的对象。学习和掌握这些技术对于提升你的OpenGL...
OpenGL鼠标选择源码是计算机图形学领域中一个重要的实践应用,它允许用户通过鼠标交互式地选择场景中的特定对象。这个源码实现了一个基础的机制,使得在3D环境中,用户可以通过点击鼠标来识别和选择目标物体。在本文...
手册中会详细阐述OpenGL的函数调用、状态机机制、渲染管道工作原理,以及各种着色语言(如GLSL)的语法和用法。在本压缩包中,有中英文两个版本,这使得无论是中文使用者还是英文使用者,都能无障碍地理解和学习...
总之,OpenGL提供了一系列工具和技术来处理图像的选取和放大,包括深度测试、模板测试、多边形偏移、视口和投影变换,以及选择和选取机制。通过学习和实践这些内容,开发者能够创建出更加互动和精细的3D应用程序。...
OpenGL的处理机制主要涉及以下几个方面: 1. 基元与顶点:OpenGL将图形表示为一系列的基元,这些基元可以是点、线段或者多边形。每个基元由一个或多个顶点定义,顶点包含了如坐标值、颜色值、法线值和纹理坐标等...
- **扩展性**:通过扩展机制,开发者可以利用厂商特定的功能或最新的硬件特性。 - **现代特性**:如顶点数组对象、纹理数组、浮点纹理、混合模式等,为高级图形处理提供支持。 4. **与其他技术的对比**: - **...
8. 状态机机制:理解OpenGL的状态机模型,如何通过设置状态来影响后续的绘图行为。 9. 效果技术:如光照、雾化、镜面反射等,提升图形的真实感和视觉效果。 10. 高级特性:包括多重采样抗锯齿、帧缓冲对象(FBO)...
10. **错误检测**:OpenGL提供了错误检测机制,如glGetError函数,用于检查上一次调用是否出错。 OpenGL的编程流程通常包括初始化OpenGL上下文、加载着色器程序、设置模型视图投影矩阵、绘制图元、执行着色器计算、...
8. **错误检查与调试**:OpenGL提供了错误查询机制,如`glGetError()`,帮助开发者定位和解决问题。 9. **扩展**:OpenGL 2.1手册还会列出当时的可用扩展,这些扩展可能提供了额外的功能,比如硬件支持的顶点程序或...
开发过程中,开发者还需要了解OpenGL的上下文(Context)、帧缓冲对象(Framebuffer Object)、顶点数组对象(Vertex Array Object)、着色器(Shader)、状态机机制以及现代OpenGL的面向对象编程风格等概念。 最后,调试...
同时,了解状态机机制,比如如何设置渲染状态,以及如何使用缓冲区和纹理等资源,也是必不可少的。 此外,为了在实际项目中使用OpenGL,开发者还需要熟悉窗口系统和上下文管理,比如在Windows上使用GLUT或FreeGLUT...