`
whuthj
  • 浏览: 70244 次
  • 性别: Icon_minigender_1
  • 来自: 武汉
社区版块
存档分类
最新评论

OpenGL选择机制

阅读更多

      通常,当你打算使用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的选择机制使用,使用C++进行OpenGL的选择机制的使用

    OpenGL实例_了解OpenGL运行机制的最好实例_openGL实例_

    OpenGL的实例,进入OpenGL学习的第一步

    3DS文件读取,绘制与控制方法的研究与应用(PDF)

    通过平移、旋转和缩放这3种矩阵变换和OpenGL选择机制实现了对模型的交互控制。基于上述方法开发了井下作业操作仿真与演练系统,取得了良好的效果. 关键词:3DS文件;块结构;OpenGL;读取;绘制;交互控制 中图法...

    OpenGL的处理机制及其发展展望

    OpenGL的处理机制及其发展展望,高级图形界面的光明前景。

    OpenGL配置环境与OpenGL扩展机制

    open gl在各版本vs环境的配置与扩展(包括glew,glut,glee等库)

    使用OpenGL实现三维坐标的鼠标拣选

    使用OpenGL实现三维坐标的鼠标拣选,本文提出并实现一种用于...此方法对于正交投影或透视投影均有效,相对于OpenGL自带的选择与反馈机制,本方法无论是拣选精度还是算法实现效率均高出许多,是一种比较通用的解决方案。

    OpenGL ES应用开发实践指南(Android卷).pdf

    由资深Android开发专家根据OpenGLES2.0版本撰写,不仅系统地讲解了OpenGLES的核心概念、技术,以及Android的图形机制,还通过大量案例讲解了在Android上进行OpenGLES开发的方法和技巧。  《OpenGL ES应用开发实践...

    OpenGL-Shader封装

    采用C++的面向对象机制,OpenGL的Shader类封装。 采用C++的面向对象机制,OpenGL的Shader类封装。

    OpenGL编程指南(原书第7版)中文扫描版.pdf.rar

    《OpenGL编程指南(原书第7版)》继续对OpenGL着色语言(glsl)展开讨论,并解释了使用这种语言创建复杂图形效果并提升OpenGL计算威力的机制。OpenGL技术资料库(OpenGL technical library)提供了大量的OpenGL教程...

    OpenGL ES应用开发实践指南 Android卷

    由资深Android开发专家根据OpenGLES2.0版本撰写,不仅系统地讲解了OpenGLES的核心概念、技术,以及Android的图形机制,还通过大量案例讲解了在Android上进行OpenGLES开发的方法和技巧。  《OpenGL ES应用开发实践...

    Visual C++下OpenGL开发框架与应用2

    本篇文章主要针对初学者(最好要有图形方面的基础知识)而制作的,旨在通过对OpenGL 的整个知识结构的介绍,来具体剖析其内在运行机制,并且结合实际开发经验总结出在VC平台下的OpenGL开发框架,最后给出一个例程来...

    OpenGL橡皮筋多边形填充效果

    橡皮筋工作花了不少时间了,因为对OpenGL的窗体机制很不熟悉,还有很多东西都是陌生的,OpenGL里的鼠标事件处理,之后还要研究扫描先算法。 1.显示与点击是不一样的,点击后就要全部重新显示 2.标识变量不要放到绘制...

    OpenGL ES应用开. IOS卷

    由资深iOS开发专家根据OpenGL ES最新版本撰写,不仅详细讲解了OpenGL ES与GLKit的结合使用,而且还系统讲解OpenGL ES的核心概念、技术,以及iOS的图形机制,并通过大量案例讲解了在iOS上进行OpenGL ES开发的方法和...

    OpenGl 3.0 3.1

    opengl 最新教程3.0 3.1 ...同时,OGL3.0还引入了一些新的功能,例如顶点矩阵对象,全帧缓存对象功能,32bit浮点纹理和渲染缓存,基于阻塞队列的条件渲染,紧凑行半浮点顶点和像素数据,四个新压缩机制等等

    OpenGL的鼠标键盘事件

    OpenGL的鼠标键盘事件机制,简单的例子代码!

    3D引擎,渲染系统使用的OpenGL 及 OpenGL ES,Windows上OpenGL ES使用AMD的ES模拟器.zip

    这些扩展可以通过 OpenGL 的扩展机制被查询和使用。 4. 跨平台和跨语言:OpenGL 可以在所有主要的操作系统(如 Windows、macOS 和 Linux)上运行,并且有各种编程语言的绑定,包括 C、C++、Python、Java 和许多其他...

    MFC中使用OpenGL实现三维运动仿真

    讲述OpenGL处理机制,Windows环境下的OpenGL的处理流程,MFC构架下OpenGL运动仿真实现。

Global site tag (gtag.js) - Google Analytics