OpenGL 射线 拾取

简介:

OpenGL中鼠标射线拾取,就是通过鼠标点击屏幕产生的坐标,通过变换到3D坐标空间,然后从摄像机原点与该3D空间坐标产生一个射线(ray),通过该射线与3D世界中的物体做相交检测,即可实现3D物体的拾取。

实现:

OpenGL—坐标变换中可以知道,当前鼠标的坐标属于视口坐标,所以需要取得当前鼠标点击的点在3D世界中的坐标位置,也就是要将当前鼠标的点通过逆变换,从视口坐标变换到世界坐标中,然后再与世界坐标中的物体做相交检测。


2D视图坐标:

对于当前鼠标在屏幕中点击的点的坐标就是2D的视图坐标,该坐标就是windowsd的窗口坐标,窗口左上角(0, 0), 右下角为(w,h)。

3D标准设备坐标(NDC):

也就是将当前的视图坐标转换为标准设备坐标即x的坐标从左往右为[-1, 1],y轴的坐标从上到下为[1, -1],z轴从外到里为[-1, 1],则将视图坐标转换为ndc坐标为:

[cpp]  view plain  copy
  1. float x = (2.0f * mouse_x) / width - 1.0f;  
  2. float y = 1.0f - (2.0f * mouse_y) / height;  
  3. float z = 1.0f;  
  4. vec3 ray_nds = vec3 (x, y, z);  

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

4D裁剪坐标:

也就是为了将NDC坐标变换到四维齐次坐标,所以这步我们只需要加上w的值即可:

[cpp]  view plain  copy
  1. vec4 ray_clip = vec4 (ray_nds.xyz, 1.0);  

视觉坐标:

由于从视觉坐标变换到裁剪坐标是通过一个投影矩阵来变换的,所以在这我们只需要取得当前的投影矩阵,对投影矩阵求逆即可将坐标从裁剪坐标变换回到视觉坐标:

[cpp]  view plain  copy
  1. vec4 ray_eye = inverse (projection_matrix) * ray_clip;  

世界坐标:

由世界坐标变换到视觉坐标,则将当前的世界坐标与视图矩阵做变换,所以为了得到世界坐标,则取得当前的视图矩阵,将当前的视觉坐标与视图矩阵的逆矩阵做变换,即可得到当前的世界坐标:

[cpp]  view plain  copy
  1. vec4 ray_world = inverse (view_matrix) * ray_eye;  

由于我们当前的坐标是带w值的,所以我们除以w,然后取得当前摄像机的位置,即可得到当前的射线:

[cpp]  view plain  copy
  1. if (ray_world.w != 0.0)  
  2. {  
  3.     ray_world.x /= ray_world.w;  
  4.     ray_world.y /= ray_world.w;  
  5.     ray_world.z /= ray_world.w;           
  6. }  
  7.   
  8. vec3 ray_dir = normalise(ray_world.xyz - camera_position);  

射线的起始位置就是摄像机的位置。

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值