[OpenGL]射线拾取RayPicking---(1)生成射线

现代OpenGL学习教程 同时被 3 个专栏收录
40 篇文章 41 订阅
4 篇文章 0 订阅
6 篇文章 0 订阅

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();

 

  • 1
    点赞
  • 2
    评论
  • 5
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

©️2021 CSDN 皮肤主题: 技术黑板 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值