[OpenGL]射线拾取RayPicking---(1)生成射线
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)生成射线相关推荐
- Android OpenGL射线拾取手势旋转(二)
上回分解-_-!,Android OpenGL射线拾取&手势旋转(一). 3)Renderer:RayPickRenderer.java OpenGL渲染器,比较多的东西都在这里面了. pub ...
- opengl es的射线拾取
2019独角兽企业重金招聘Python工程师标准>>> 在opengl中关于拾取有封装好的选择模式,名字栈,命中记录,实现拾取的功能,相对容易一些.但是到了opengl es里面就比 ...
- UE4 射线拾取三维画线
虽然有人建议UE4使用C++创建VR项目,能避免一些坑爹的错误,但是我用C++创建,竟然问题更多,还存在创建不了的情况,也不知道是不是我的操作问题,快疯了. 于是我还是选择了蓝图创建VR项目,但是.. ...
- 3D射线拾取算法揭秘
笔者介绍:姜雪伟,IT公司技术合伙人,IT高级讲师,CSDN社区专家,特邀编辑,畅销书作者,国家专利发明人;已出版书籍:<手把手教你架构3D游戏引擎>电子工业出版社和<Unity3D ...
- opengl作业三维虚拟场景_乱弹OpenGL选择-拾取机制
无论是游戏还是VR,三维世界总免不了与用户的交互.而这其中常也免不了"用户对场景中物件的选择(也就是,拾取)"这种需求.OpenGL本身就内置有一套拾取机制,这次就乱弹一下吧.(乱 ...
- threejs学习(十一)非全屏canvas下,射线拾取坐标错位问题
问题 在非全屏状态下,使用射线进行模型拾取,如果按照官方例子来做,会出现屏幕坐标转换三维坐标有误差,导致拾取模型错误: 非全屏canvas 解决方案 需要重新计算鼠标点击坐标位置 spriteClic ...
- unity3d VR手柄射线拾取,投掷,发射可拿去的物体
using UnityEngine; /// <summary> /// 手柄射线原代码要添加好1. SteamVR_LaserPointer 2.SteamVR_TrackedContr ...
- OpenGL鼠标拾取
1.OpenGL自带拾取功能.glSelectBuffer等函数完成. 大每一本OpenGL入门的书都会讲到OpenGL的Select模式,它采用一种方法使得可以获取当前鼠标点选的几何图形.简单的来说 ...
- 蒙特卡洛射线追踪_什么是射线追踪?
蒙特卡洛射线追踪 Recently a demo from Epic, the makers of the Unreal game engine, raised eyebrows for its ph ...
最新文章
- ASP.NET + SqlSever 大数据解决方案 PK HADOOP
- 位操作——整数用位存储
- form 表单字段 autocomplete 设置为off 后仍然无效的解决方法
- ListView 和 GridView应用详解-----本文转自博客园
- 大数据_Flink_Java版_数据处理_流处理API_Transform(5)_union合流---Flink工作笔记0034
- Visual Studio 2010如何利用宏
- 获取winform应用程序集信息
- c语言 算术平均滤波法_算术平均滤波C程序
- Chrome屏蔽广告
- 什么是设计模式,为什么要使用?
- word2vec利用词向量进行中文新闻标题相似度分析
- 升级iOS 16后续航时间变短了,如何提升续航?
- 面试题一(计算机基础、逻辑)
- 初探Log4j2-yaml配置坑
- h5画布动画_使用HTML5画布制作动画的漫画面板
- Lingo 基础知识
- 微信内浏览器或系统字体放大缩小,html页面布局错乱问题
- 软件工程导论——总体设计
- eclipse svn忽略classpath、target、.project等
- 介绍一种新的群智能算法---黏菌算法