Vries的教程是我看过的最好的可编程管线OpenGL教程,没有之一。但没有讲关于拾取(Picking)的章节,而这个功能的确很重要,就自己试着写写看了。

这节有三个很重要的参考网址,基本可以算照抄了?:

1. https://blog.csdn.net/wind_hzx/article/details/40016619

2. https://blog.csdn.net/jeffasd/article/details/77944822

3. http://antongerdelan.net/opengl/raycasting.html

Tip1: 拾取分三节写完,第一节写生成射线,第二节(超链)写射线与三角面的检测,第三节写射线与包围盒(球)的检测

程序源代码链接:https://pan.baidu.com/s/119469EhYK3jLkKoZUFdJ_Q 提取码:2jef 

编译环境:Qt5.9.4

编译器:Desktop Qt5.9.4 MSVC2017 64bit

IDE:QtCreator

一,程序简介

  鼠标点击视口中的任何位置,会生成一条从摄像机(camera)位置,到鼠标点击位置的射线。

  • 在“发射射线”模式下,鼠标左键点击下图所示的位置,会由该摄像机位置生成一条指向该点的射线。
  •   在“普通模式”下,WASD控制摄像机前后左右移动,E控制上升,Q下降。鼠标左键按住不放课拖拽摄像机视线方向,

二,数学原理

  搞过OpenGL最基础管线流程的都知道,一个物体由3D坐标最终映射到屏幕上的2D坐标,需要经过五步坐标系变换,

  局部坐标系(local)→世界坐标系(world)→视点坐标系(view)→投影坐标系(projection)→设备标准坐标与剪切系(ndc &clip)→屏幕视口坐标系(viewport)

  当我们用鼠标左键点击屏幕上的一个点时,将以上的坐标变换全部逆回来,就可以得到一个2D点在三维世界坐标系(world)中的位置。

(1)2D屏幕坐标

  点击屏幕任一点,得到点的坐标(x, y)

(2)NDC坐标

  NDC标准化坐标的范围是[-1, 1],所以

//视口坐标转 NDC坐标 pos.x()为鼠标点击坐标的x坐标
//OGLMANAGER_WIDTH为窗口的宽度
float x = 2.0f * pos.x() / OGLMANAGER_WIDTH - 1.0f;
float y = 1.0f - (2.0f * pos.y() / OGLMANAGER_HEIGHT);
QVector3D ray_nds = QVector3D(x, y, 1.0f);

z = 1.0f 代表当前将鼠标的位置投影到远裁剪平面,如果设z的坐标为-1则代表将当前投影到近裁剪平面上。

(3) 裁剪坐标(clip)

因为后边需要讲view,projection矩阵的逆矩阵(4x4矩阵)与点的坐标相乘,所以,需要将点的坐标扩充至四元数

  QVector4D ray_clip = QVector4D(ray_nds, 1.0f);

(4)视点坐标(view)

//投影矩阵的逆矩阵左乘点的坐标
QVector4D ray_eye = projection.inverted() * ray_clip;

(5)世界坐标(world)

  QVector4D ray_world = view.inverted() * ray_eye;

 这时,我们就得到了鼠标点击的点在世界坐标系下的齐次坐标位置。

 最后一步,因为ray_world是四维的齐次坐标,需要将前三维的值除以第四个维度的值,以转换到笛卡尔坐标系下

  if(ray_world.w() != 0.0f){ray_world.setX(ray_world.x()/ray_world.w());ray_world.setY(ray_world.y()/ray_world.w());ray_world.setZ(ray_world.z()/ray_world.w());}

  现在,我们就可以将得到的点的世界坐标与摄像机的世界坐标,两个点相减得到射线的方向矢量了。

  QVector3D ray_dir = (QVector3D(ray_world.x(), ray_world.y(), ray_world.z()) - cameraPos).normalized();

[OpenGL]射线拾取RayPicking---(1)生成射线相关推荐

  1. Android OpenGL射线拾取手势旋转(二)

    上回分解-_-!,Android OpenGL射线拾取&手势旋转(一). 3)Renderer:RayPickRenderer.java OpenGL渲染器,比较多的东西都在这里面了. pub ...

  2. opengl es的射线拾取

    2019独角兽企业重金招聘Python工程师标准>>> 在opengl中关于拾取有封装好的选择模式,名字栈,命中记录,实现拾取的功能,相对容易一些.但是到了opengl es里面就比 ...

  3. UE4 射线拾取三维画线

    虽然有人建议UE4使用C++创建VR项目,能避免一些坑爹的错误,但是我用C++创建,竟然问题更多,还存在创建不了的情况,也不知道是不是我的操作问题,快疯了. 于是我还是选择了蓝图创建VR项目,但是.. ...

  4. 3D射线拾取算法揭秘

    笔者介绍:姜雪伟,IT公司技术合伙人,IT高级讲师,CSDN社区专家,特邀编辑,畅销书作者,国家专利发明人;已出版书籍:<手把手教你架构3D游戏引擎>电子工业出版社和<Unity3D ...

  5. opengl作业三维虚拟场景_乱弹OpenGL选择-拾取机制

    无论是游戏还是VR,三维世界总免不了与用户的交互.而这其中常也免不了"用户对场景中物件的选择(也就是,拾取)"这种需求.OpenGL本身就内置有一套拾取机制,这次就乱弹一下吧.(乱 ...

  6. threejs学习(十一)非全屏canvas下,射线拾取坐标错位问题

    问题 在非全屏状态下,使用射线进行模型拾取,如果按照官方例子来做,会出现屏幕坐标转换三维坐标有误差,导致拾取模型错误: 非全屏canvas 解决方案 需要重新计算鼠标点击坐标位置 spriteClic ...

  7. unity3d VR手柄射线拾取,投掷,发射可拿去的物体

    using UnityEngine; /// <summary> /// 手柄射线原代码要添加好1. SteamVR_LaserPointer 2.SteamVR_TrackedContr ...

  8. OpenGL鼠标拾取

    1.OpenGL自带拾取功能.glSelectBuffer等函数完成. 大每一本OpenGL入门的书都会讲到OpenGL的Select模式,它采用一种方法使得可以获取当前鼠标点选的几何图形.简单的来说 ...

  9. 蒙特卡洛射线追踪_什么是射线追踪?

    蒙特卡洛射线追踪 Recently a demo from Epic, the makers of the Unreal game engine, raised eyebrows for its ph ...

最新文章

  1. ASP.NET + SqlSever 大数据解决方案 PK HADOOP
  2. 位操作——整数用位存储
  3. form 表单字段 autocomplete 设置为off 后仍然无效的解决方法
  4. ListView 和 GridView应用详解-----本文转自博客园
  5. 大数据_Flink_Java版_数据处理_流处理API_Transform(5)_union合流---Flink工作笔记0034
  6. Visual Studio 2010如何利用宏
  7. 获取winform应用程序集信息
  8. c语言 算术平均滤波法_算术平均滤波C程序
  9. Chrome屏蔽广告
  10. 什么是设计模式,为什么要使用?
  11. word2vec利用词向量进行中文新闻标题相似度分析
  12. 升级iOS 16后续航时间变短了,如何提升续航?
  13. 面试题一(计算机基础、逻辑)
  14. 初探Log4j2-yaml配置坑
  15. h5画布动画_使用HTML5画布制作动画的漫画面板
  16. Lingo 基础知识
  17. 微信内浏览器或系统字体放大缩小,html页面布局错乱问题
  18. 软件工程导论——总体设计
  19. eclipse svn忽略classpath、target、.project等
  20. 介绍一种新的群智能算法---黏菌算法

热门文章

  1. android手机模拟器怎么连不上网,模拟器无法上网解决方法
  2. [学习心得]C# 登录验证码
  3. matlab:申请贷款问题
  4. 深度学习中适合长期租用的高性价比便宜的GPU云服务器有哪些?
  5. Tor 浏览器,中文名洋葱浏览器
  6. 马云是计算机专业的吗,大佬与高考:马云三次高考 马化腾弃天文选计算机
  7. JPG图像转存为NV12格式
  8. VS2022身份证号码信息验证器
  9. Django基础02 视图和模型
  10. UNIX网络编程第三版(卷1)读书笔记以及习题-章节1