用过OpenGL的人,应该都知道,OpenGL是自带拾取功能的,但用过的人应该也知道,这功能确实不好用。

OpenGL自带的选择功能主要有两种,名字堆栈(拾取)和读深度值判断选择,但这两种方法在实际项目中,未必都好用。

方法一:名字堆栈的方法,需要切换渲染模式,操作命名堆栈,计算拣选矩阵,检查选中记录。当要渲染的数据量特别大或渲染的对象众多时,显然是不可取的。

方法二:glReadPixel方法,读深度值的方法,这种方法比前面一种方法在某些时候稍微好用些,但有一个致命的限制,你鼠标选择的时候,必须选择到绘有实体的地方,否则就得不到正确的深度值。例如你渲染一个三维地形图,地形以Tin的方式渲染,如果你想选择某个顶点,但鼠标落在空白区,你就无法得到正确的深度值,得不到正确的深度值,自然没法根据gluUnproject函数反算到真实的地形坐标点,而实际应用中应该是即使你没完全落在该顶点上,也应该可以根据一个缓冲,在所有缓冲区内部的点集中选择一个距离光标最近的点作为你选择的点。

本文介绍一种方法——射线选择,这种方法也是游戏界和三维地形编程普遍采用的选择方法。

首先介绍一个二维三维坐标转换函数: gluUnProject()

此函数的具体用途是将一个OpenGL视区内的二维点转换为与其对应的场景中的三维坐标。

转换过程如下图所示(由点P在窗口中的XY坐标得到其在三维空间中的世界坐标):

这个函数在glu.h中的原型定义如下:

代码

int APIENTRY gluUnProject (

GLdouble       winx,

GLdouble       winy,

GLdouble       winz,

const GLdouble modelMatrix[16],

const GLdouble projMatrix[16],

const GLint    viewport[4],

GLdouble       *objx,

GLdouble       *objy,

GLdouble       *objz);

其中前三个值表示窗口坐标,中间三个分别为模型视图矩阵(Model/View Matrix),投影矩阵(Projection Matrix)和视区(ViewPort),最后三个为输出的世界坐标值。

第二步,首先获得视图矩阵,投影矩阵,视区三个数组值。

代码

 GLint    viewport[4]; 
 GLdouble modelview[16]; 
 GLdouble projection[16];

glGetIntegerv(GL_VIEWPORT, viewport); // 得到的是最后一个设置视口的参数
 glGetDoublev(GL_MODELVIEW_MATRIX, modelview); 
 glGetDoublev(GL_PROJECTION_MATRIX, projection);

获取这三个变量的代码,应该放在绘制发生前,三个矩阵定以后。否则glPopMatrix之类的函数,可能导致你无法得到真正的投影矩阵和视图矩阵。

第三步,获取射线。因为两点确定一条线,所以,先通过计算视图最近点和最远点,得到该射线。

代码

 winX = point.x; 
 winY = screenHeight - point.y;

//获取像素对应的前裁剪面的点坐标
 bool bResult = gluUnProject(winX, winY, 0.0, modelview, projection, viewport, &posX, &posY, &posZ); 
 FPoint3 nearPoint;
 nearPoint.x = posX; nearPoint.y = posY; nearPoint.z = posZ;
 //获取像素对应的后裁剪面的点坐标
 bResult = gluUnProject(winX, winY, 1.0, modelview, projection, viewport, &posX, &posY, &posZ); 
 FPoint3 farPoint;
 farPoint.x = posX; farPoint.y = posY; farPoint.z = posZ;

第四步,计算待选择目标跟该的关系,将与射线距离最近的对象,作为选择对象。

第五步,本文绘制了分布在不同三维空间的5个点,用鼠标右键,可以进行点的选择,如果选中,点会变成黄色,鼠标左键可以随意对这些点进行旋转等。

程序源代码

转载于:https://www.cnblogs.com/yanhuiw/archive/2010/08/26/1809489.html

OpenGL环境下的射线选择相关推荐

  1. OpenGL环境下PLY三维模型的读入与显示

    相关链接 OpenGL环境下PLY三维模型的读入与显示的源码-CSDN下载 codeblocks配置OpenGL环境-CSDN博客 问题描述 仿照PLY格式点云读取代码,实现PLY格式三角形面片模型的 ...

  2. 当前的行业环境下 你会选择创业吗?

    2006.09.19  来自:CSDN人才频道   李颜芯 <script src="http://news.csdn.net/include/getkeys_js.aspx?id=9 ...

  3. opengl将bmp读成像素_在 opengl 环境下将 texture 保存为 bmp 图片

    首先说一下做这个功能的原因,是在应用里,有一个渲染线程,负责渲染出图,将最终的画面以texture形式传递给另一个线程,后者会再进行一些处理,然后渲染到屏幕上.那么在最后显示出来画面偶尔有花屏撕裂的现 ...

  4. 解决锐捷校园网环境下VMware虚拟机无法上网问题

    解决锐捷校园网环境下VMware虚拟机无法上网问题 1.介绍: 在介绍笨方法之前首先得说一下VMware虚拟机无法上网的原因,虚拟机要想要上网主机里的VMnetDHCP和VMware NAT Serv ...

  5. 单片机小精灵t2_搭建S5P4418 ARM环境下 GPU OPENGL ES开发环境(适用 NANOPI2,3,M2,M3,T2,T3)...

    本帖最后由 3guoyangyang7 于 2017-8-20 22:38 编辑 先说一下背景,这几天做一个摄像头处理的qt项目,摄像头的像素是1280*720的,25fps,用qt的painter重 ...

  6. VS2010/VS2012/VS2015下openGL环境配置(转)

    按:按照下述博文,三个例子均成功. https://blog.csdn.net/so_geili/article/details/51685005 请仔细阅读每一个字. 为了学习<OpenGL超 ...

  7. 单机环境下(双机或是分布式系统不用考虑这个问题),app_offline.htm是个不错的选择...

    单机环境下(双机或是分布式系统不用考虑这个问题),app_offline.htm是个不错的选择. 当asp.net看到应用程序中app_offline.htm文件时,它会关闭应用程序的app-doma ...

  8. 供应链环境下,制造企业物流运作模式该如何选择

    随着经济全球化的快速发展,市场竞争已由单个企业之间的竞争逐渐转变为供应链之间的竞争,企业要想获得竞争优势,必须实施供应链战略资源整合.作为一种新的管理思想和管理方法,供应链管理是通过管控(计划.组织. ...

  9. Learning in situ: 视频流媒体中真实环境下训练的自适应码率选择算法Fugu

    本文出自论文Learning in situ: a randomized experiment in video streaming,作者提出Fugu算法,通过结合经典控制策略和一个学习网络预测器,并 ...

最新文章

  1. 软件之最大全电子书免费版
  2. C#.Net 如何动态加载与卸载程序集(.dll或者.exe)6-----在不卸载程序域的前提下替换程序集文件。...
  3. C语言之父,UNIX之父丹尼斯·里奇去世 享年70岁
  4. (转载)Struts2源码粗略分析四:理解xwork工作原理
  5. c语言中常见的变量,C语言中的变量详解
  6. 公司使用360安全产品造成的CRM系统故障!
  7. 全面收紧!继新加坡后,又一地拟暂停数据中心建设
  8. (69)番外 —— 编写一个简易的反调试引擎
  9. 巧用 PHP 数组函数
  10. {在头值中找到无效的字符。} 发email的时候 遇到这个问题 老师解决
  11. Caffe: gflag编译出现问题汇总
  12. 国外好的软件测试网站
  13. SpringBoot默认的错误处理机制
  14. lvs/nginx/haproxy优缺点
  15. 如何打破线下流量瓶颈?三四线城市实体门店的生存之道
  16. POJ 3422 - Kaka's Matrix Travels(最小费用流)
  17. 从软件外包到阿里技术专家再到CTO,他究竟是如何一路晋升?
  18. 安卓android_rom定制,移植,安卓Android_ROM定制、移植:第一~~八篇(全)
  19. 计算机科学报数学竞赛,(word)首届全校数学竞赛.doc
  20. ktv服务器系统怎样加歌,明光市ktv点歌系统如何加歌

热门文章

  1. if(x1-x20) c语言,如何用if语句实现求方程a*x*x+b*x+c=0的根。
  2. linux安装socket.io,ubuntu – 如何在node.js npm服务器上查看socket.io版本
  3. mysql8 堆应该给多大_深入进阶:图解分析JVM内存堆布局
  4. JAVA二分查找-探讨思维与代码的一致性
  5. 百练OJ:3865和2677:肿瘤检测
  6. 2021年软考考试时间公布
  7. C#中怎样将数组的顺序打乱随机排序
  8. ElementUI项目中怎样引用Jquery
  9. C#中提示:System.Runtime.Serialization.SerializationException
  10. SpringBoot中实现批量文件上传