教学文库网 - 权威文档分享云平台
您的当前位置:首页 > 精品文档 > 综合文档 >

基于Opengl的屏幕对象拾取 毕业论文(5)

来源:网络收集 时间:2026-08-10
导读: 4 系统的设计及实现 有些图形应用程序只绘制两维和三维物体构成的静态图形,另一些允许用户识别屏幕上的物体并移动、修改、删除或用其它方法操纵这些物体。OpenGL正是设计用于支持这些交互式应用程序的。因为绘制在

4 系统的设计及实现

有些图形应用程序只绘制两维和三维物体构成的静态图形,另一些允许用户识别屏幕上的物体并移动、修改、删除或用其它方法操纵这些物体。OpenGL正是设计用于支持这些交互式应用程序的。因为绘制在屏幕上的物体通常经过多次旋转、移动和透视变换,所以确定用户选中了三维场景中的哪个物体会很困难。为了解决这个问题,OpenGL提供了一个选择机制可惟自动告诉你哪个物体被绘制在窗口的提定区域里。

本文的拾取考虑到简单地拾取三个不同的物体,分别是一个一个拾取,而不是同时拾取的过程且拾取物体是简单的选择体,这些正好都不是OpenGL的选择机制的各种缺点且OpenGL的选择机制是OpenGL本身自带的因素,所以采用了OpenGL的选择机制的拾取方法,来实现对三个不同的物体拾取。拾取过程如下:

使用OpenGL的选择机制时,首先把场景画进帧缓冲,然后进入选择模式并重新绘制这个场景。然而,一旦进入了选择模式,帧缓冲的内容将保存不变,直到退出选择模式。当退出选择时,OpenGL返回一个图元(premitives)清单,图元可能被视见体(viewing volume)分割。每个被视见体图元引出一资选择命中(hit)。确切的说,图元清单是作为一个取整数值的名字(integer-valued names)数组和相关的数据-命中记录(hit record)-对应名字栈(name stack)的当前内容。当在选择模式下发布图元绘制命令时向名字栈中加入名字就可建立起名字栈。这样,当名字清单被返回后,就可以用它来确定屏幕上的哪个图元可能被用户选中了。

除了这个选择机制之外,OpenGL提供了一个工具例程,以便在某些情况下通过限定在视口(viewport)一个小区域内绘制来简化选择。可以用这个例程决定哪个物体被画在光标附近了,这样就能识别用户拾取了哪个物体,也可以通过指定附加的裁剪面来界定一个选择区域。 4.1系统的选择机制

选择机制分以下几个部分来进行: (1)进入选择模式之前; (2)获取当前选择模式; (3)退出当前选择模式; (4)拾取。

4.1.1进入选择模式之前

用glSelectBuffer()指定用于返回命中记录的数组; 下面描述glSelectBuffer()和glRenderMode()。

void glSelectBuffer(GLsizei size,GLuint *buffer);指定用于返回选择数据的数组。

参数buffer是指向无符号整数(unsigned integer)数组的指针,数据就存在这个数组中,size参数说明数组中最多能够保存的值的个数。要在进入选择模式之前调用glSelectBuffer() 4.1.2获取当前选择模式

以GL_SELECT为参数调用glRenderMode()进入选择模式;

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()获取当前模式。 定义用于选择的视见体

通常它与原来用于绘制场景的视见体不同,也可以用glPushMatrix()和glPopMatrix()来保存

18

和恢复当前的变换矩阵;在选择模式下,被视见体裁剪的每个图元引起一个选择命中。当前一个名字栈控制命令被执行或glRenderMode()被调用后,OpenGL将一个命中记录写进选择数组,如果从上一次名字栈操纵或glRenderMode()调用以来有了一个命中记录的话。这个过程中,共用同样名字的物体-例如:由多个图元组成的物体-不生成多个命中记录。当然,命中记录不保证会被写进数组中直到glRenderMode()被调用。

除图元之外,glRasterPos()产生的有效坐标也可以引起选择命中。在多边形的情况下,如果它已经被消隐掉的话不会有命中记录出现。 每个命中记录由四项组成,依次是: (1)当命中出现时名字栈中的名字数;

(2)至上次记录的命中以来,被视见体裁剪后的图元的所有顶点的窗口Z坐标的最大; (3)被视见体裁剪后的图元的所有顶点的窗口Z坐标最小值; (4)本次命中时名字栈的内容,最底元素最前。

进入选择模式时,OpenGL初始化一个指针指向选择数组的起点。每写入一个命中记录,指针相应更新。如果写入一个命中记录会使数组中值的个数超过glSelectBuffer()的size参数时,OpenGL会写入尽可能多的记录并设置一个溢出标志。当用glRenderMode()退出选择模式时,这条命令返回被写入的记录的个数(包括一条部分记录如果有的话),清除名字栈,复位溢出标识,重置栈指针。如设定溢了出标识则返回值是-1。

用glInitName()和glPushName()初始化名字栈

名字栈是返回给你的选择信息的基础,要建立名字栈,首先用glInitNames()初始化它,这将简单地清空栈。然后当发布相应的绘制命令时向其中加入整数名字。栈控制命令允许你压入名字(glPushName()),弹出名字(glPopName()),替换栈顶的名字(glLoadName())。 举个例子:

Example 12-1: Creating a Name Stack glInitNames(); glPushName(-1);

glPushMatrix(); /*保存当前的转型的状态*/ glLoadName(1); drawSomeObject(); glLoadName(2);

drawAnotherObject(); glLoadName(3);

drawYetAnotherObject(); drawJustOneMoreObject();

glPopMatrix (); /*恢复以前的转型的状态*/

在这个例子中,前两个被绘制的物体有自己的名字,第三和第四个共用一个名字。这样,如果第三或第四个物体中的一个或全部引起一个选择命中,只有一个命中记录返回给你。如果处理命中记录时不想区分各个物体的话,可以让多个物体共享一个名字。 void glInitNames(void); 清空名字栈。

void glPushName(GLuint name); 将name压入名字栈

压入名字超过栈容量时将生成一个GL_STACK_OVERFLOW错误。名字栈深度因OpenGL实现(implementations)不同而不同,但最少要能容纳64个名字。可以用参数GL_NAME_STACK_DEPTH调用glGetIntegerv()以获取名字栈深度。

void glPopName(void);弹出名字栈栈顶的那一个名字

19

从空栈中弹出名字引发GL_STACK_UNDERFLOW错误。

void glLoadName(GLuint name);用name取代名字栈栈顶的那个名字。如果栈是空的,刚调用过glInitName()后就是这样,glLoadName()生成一个GL_INVALID_OPRATION错。为避免这种情况,如果栈初始时是空的,那么在调用glLoadName()之前至少调用一次glPushName()以在名字栈中放上点东西。

交替发布图元绘制命令和名字栈控制命令,这样每个感兴趣的图元都会被指定适当的名字; 4.1.3退出选择模式

退出选择模式并处理返回的选择数据(命中记录)。 4.1.4拾取

用选择模式确定物体是否被拾取了,要做到这一点,用一个与投影矩阵相关联的拾取矩阵将绘制限制在视口的一个很小的区域里,通常是在光标附近。然后允许某种形式的输入,如点击鼠标的一个键,引发选择模式的初始化。建立起选择模式并使用特定的拾取矩阵,绘制在光标附近的物体引发选择命中。即,通常在拾取的时候确定哪个物体被画在 …… 此处隐藏:2808字,全部文档内容请下载后查看。喜欢就下载吧 ……

基于Opengl的屏幕对象拾取 毕业论文(5).doc 将本文的Word文档下载到电脑,方便复制、编辑、收藏和打印
本文链接:https://www.jiaowen.net/wendang/403874.html(转载请注明文章来源)
Copyright © 2020-2025 教文网 版权所有
声明 :本网站尊重并保护知识产权,根据《信息网络传播权保护条例》,如果我们转载的作品侵犯了您的权利,请在一个月内通知我们,我们会及时删除。
客服QQ:78024566 邮箱:78024566@qq.com
苏ICP备19068818号-2
Top
× 游客快捷下载通道(下载后可以自由复制和排版)
VIP包月下载
特价:29 元/月 原价:99元
低至 0.3 元/份 每月下载150
全站内容免费自由复制
VIP包月下载
特价:29 元/月 原价:99元
低至 0.3 元/份 每月下载150
全站内容免费自由复制
注:下载文档有可能出现无法下载或内容有问题,请联系客服协助您处理。
× 常见问题(客服时间:周一到周五 9:30-18:00)