您当前的位置: 首页 >  qt

龚建波

暂无认证

  • 5浏览

    0关注

    313博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

OpenGL with QtWidgets:屏幕坐标转世界坐标

龚建波 发布时间:2022-04-04 23:50:06 ,浏览量:5

(本文是LearnOpenGL的学习笔记, 教程中文翻译地址https://learnopengl-cn.github.io/(备用地址https://learnopengl-cn.readthedocs.io/zh/latest/),写于 2022-04-04)

0.前言

在之前的图形绘制操作中,都是将模型顶点坐标转换为屏幕坐标进行显示。但在进行如人机交互时,可能需要将屏幕坐标转换到世界坐标,比如点击物体进行选中,如果采用射线拾取法,就需要将屏幕坐标系的点转到世界坐标系去。

1.知识点

先复习下顶点的坐标转换流程,图1来自LearnOpenGL,图2来自OpenGL编程指南

 

顶点坐标通过模型矩阵、视图矩阵、投影矩阵转换到裁剪空间。 转换到裁剪空间后经过GPU的裁剪处理就可以得到最终需要被渲染的物体顶点坐标了,接下来GPU会做透视除法(xyz都除以w)将顶点转换到标准化设备坐标(Normalized Device Coordinate, NDC)中,透视除法将裁剪空间中顶点的4个分量都除以w分量,就从裁剪空间转换到了NDC了,NDC是一个长宽高取值范围为[-1,1]的立方体。将顶点坐标都转换到NDC后,下一步就是屏幕映射,这个就取决于最终要渲染到的窗体分辨率。

现在要做的就是将上面的步骤反过来走一遍。

先是将屏幕坐标转为NDC坐标:

因为屏幕只有一个xy平面,所以z值任取[-1,1]一点。(两个不同z值的点连成一条线,和场景中的物体做相交检测后,可以获取到离屏幕最近的一个面的z值)

NDC到裁剪空间,加一个为1的w分量作为齐次坐标。

剩下就是裁剪坐标到世界坐标,直接用mvp转换矩阵的逆矩阵计算。 

2.代码实现

github链接(MyRayPick类):https://github.com/gongjianbo/OpenGLwithQtWidgets

float ndc_x = 2.0f * pos.x() / width() - 1.0f;
float ndc_y = 1.0f - (2.0f * pos.y() / height());
float ndc_z = 1.0f;

//view视图矩阵和projection投影矩阵取渲染时的值
QVector3D ndc_ray = QVector3D(ndc_x, ndc_y, ndc_z);
QVector4D clip_ray = QVector4D(ndc_ray, 1.0f);
QVector4D eye_ray = projection.inverted() * clip_ray;
QVector4D world_ray = view.inverted() * eye_ray;
//转笛卡尔坐标
if(world_ray.w() != 0.0f){
    world_ray /= world_ray.w();
}
3.参考

LearnOpenGL:坐标系统 - LearnOpenGL CN

书籍:《OpenGL编程指南》(原书第九版)第五章

博客:[OpenGL]射线拾取RayPicking---(1)生成射线_HELLO_IHAD的博客-CSDN博客

博客:屏幕坐标转世界坐标与射线生成 - 知乎 

博客:Clip Space、NDC、Screen Space - 简书

关注
打赏
1655829268
查看更多评论
立即登录/注册

微信扫码登录

0.0532s