- 1、有哪些信誉好的足球投注网站(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。。
- 2、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载。
- 3、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
- 4、该文档为VIP文档,如果想要下载,成为VIP会员后,下载免费。
- 5、成为VIP后,下载本文档将扣除1次下载权益。下载后,不支持退款、换文档。如有疑问请联系我们。
- 6、成为VIP后,您将拥有八大权益,权益包括:VIP文档下载权益、阅读免打扰、文档格式转换、高级专利检索、专属身份标志、高级客服、多端互通、版权登记。
- 7、VIP文档为合作方或网友上传,每下载1次, 网站将根据用户上传文档的质量评分、类型等,对文档贡献者给予高额补贴、流量扶持。如果你也想贡献VIP文档。上传文档
查看更多
opengl选择机制详细解析
无论是游戏还是 VR ,三维世界总免不了与用户的交互。而这其中常也免不了“用户对场景
中物件的选择(也就是,拾取)”这种需求。OpenGL 本身就内置有一套拾取机制,这次就
乱弹一下吧。(乱弹不少了哦~ )——ZwqX
OpenGL 内置的拾取方法,应该是第三次要接触了。头次是课程作业,套例子糊里糊涂弄成
功了;第二次是去年 9 月,做一个 DEMO ,实现起来终于遇到了诸多麻烦,好不容易通过
艰辛调试得到了正确的结果,相关代码被我供奉捧信至今,但其实也不算真正理解了这套机
制。这次则是跟老师做的一个项目需要,虽说把之前的代码弄进来这个选取逻辑就差不多了,
但我觉得嘛,还是趁机作一次更深入的了解吧。
假设用户是通过鼠标左键单击来选择场景物件的。先说说一般游戏引擎里的“射线检测”实
现思路,也就是在用户拾取物件,点击渲染窗口(屏幕)上的相应的某一点的时候,激发一
条从相机位置(眼睛)过该点的射线,这条射线反映在世界空间中,就是“穿过”视像平面
发射到三维世界空间的光束。根据三维投影的知识(小孔成像原理)可知,该光速必然可以
“射中”用户所点击处的物件,问题转化为线面相交检测——检测通过则意味着“射中”该
面所属的三维物件。
1.名字标识
这“射线检测”比较好理解。好吧,请先认为 OpenGL 也遵循这种机制(可不要先入为主哦,
后面或许会否定这个假设的),那么,从工序的后端往前看,要解决些什么问题呢?恩,三
维物件知道自己身体某一部分的面被一条线叉中了,但它怎么通知应用程序“我被叉叉了”
呢?简单的就是给上头打报告,报告内容首项写上自己的姓名。好吧,在三维世界里允许长
一个样的但不允许有同样的识别码,换言之,你最好给场景中每样你在意的物件分配一个唯
一的 ID,好在它们打报告的时候不会弄混。于是,在这层意义上,ID 就是名字。
OpenGL 拾取机制觉得 ID 这太俗了,于是用名字(Name )来唯一表示每个可拾取物件。但
是我们作为应用者就该记住,这里的 Name 就是 ID,即使它真是一个名字Allan,那背后
肯定也有这么一句#define Allan 13之类的。OpenGL 拾取的名字机制也就是 ID 机制。当然,
它里面没有什么排斥不唯一性的,但你让两个物件拥有相同 Name 的时候,你起码得知道自
己在干嘛(是为了实现某些奇怪的效果吧,略谈~ )。
2.名字栈机制
上头不,应用程序怎么储存这些资料呢?啊,先说说应用程序怎么与那些被射中而打受伤
报告的物件沟通吧,它怎么拿到报告呢?答案是名字栈。
在 OpenGL 内部,有一种叫做HIT Record[击中记录]的数据,保存在一个特别的自设定缓存
区——Select Buffer[选择缓存]里。我们可以通过以下这个函数来设定 SelectBuffer,给予一
个已经分配好空间的 INT 数组作为参数(数组指针和具体大小):
glSelectBuffer (GLsizei size, GLuint *buffer);
至于我们到底应该给它多大的空间,下面讲述 HIT Record 数据结构的时候你就明白了。记
住,HIT Record 数据的填充是应用程序(上头)的任务,在拾取过程中我们无必要对它动手
脚。我们更应该关心的是之前所说的沟通问题。首先看看几个分配 Name(名字) 的函数:
//初始化名字栈
void glInitNames ();
// 向名字栈压入名字(ID)
void glPushName(GLuint name);
//从名字栈弹出名字(ID)
void glPopName();
//直接把名字(ID)放在栈头位置上
void glLoadName(GLunit name);
//相当于:
//glPopName();
//glPushName(name);
//初始化名字栈 void glInitNames ();// 向名字栈压入名字(ID)void glPushName(GLuint name);
// 从名字栈弹出名字 (ID)void glPopName();// 直接把名字 (ID) 放在栈头位置上 void
glLoadName(GLunit name); //相当于://glPopName();//glPushName(name);
一般来说,栈这种数据结构,是一种前入前出的形式。因此一般也只允许访问栈首元素。现
在不妨就假设场景中有三个物件好了,回头看看假设的 OpenGL 选择拾取逻辑:用户没有点
击屏幕的时候一切如常,一旦用户
文档评论(0)