您的位置:首页 > 运维架构

OpenGL—射线拾取(ray pick)

2014-10-12 13:18 183 查看

简介:

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坐标为:
float x = (2.0f * mouse_x) / width - 1.0f;
float y = 1.0f - (2.0f * mouse_y) / height;
float z = 1.0f;
vec3 ray_nds = vec3 (x, y, z);


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

4D裁剪坐标:

也就是为了将NDC坐标变换到四维齐次坐标,所以这步我们只需要加上w的值即可:
vec4 ray_clip = vec4 (ray_nds.xyz, 1.0);


视觉坐标:

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


世界坐标:

由世界坐标变换到视觉坐标,则将当前的世界坐标与视图矩阵做变换,所以为了得到世界坐标,则取得当前的视图矩阵,将当前的视觉坐标与视图矩阵的逆矩阵做变换,即可得到当前的世界坐标:
vec4 ray_world = inverse (view_matrix) * ray_eye;


由于我们当前的坐标是带w值的,所以我们除以w,然后取得当前摄像机的位置,即可得到当前的射线:
if (ray_world.w != 0.0)
{
ray_world.x /= ray_world.w;
ray_world.y /= ray_world.w;
ray_world.z /= ray_world.w;
}

vec3 ray_dir = normalise(ray_world.xyz - camera_position);


射线的起始位置就是摄像机的位置。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: