在游戏及编辑器中经常用到pick拾取世界坐标系中的几何物体,今天周末有空整理下推导公式。
第一步:获取Picking Ray
给出窗口坐标W(x,y)、width、Height、Camera设置,返回射线原点及方向。
推导过程:窗口坐标->屏幕(视口)坐标->视平面坐标->世界坐标系中的射线原点及方向
1. 窗口坐标系到屏幕坐标系的转换公式:
sx = wx / width
sy = 1 – wy / height
2. 因为视口不一定是整个窗口区域,所以视口坐标:
px = (sx – port.left) / (port.right – port.left)
py = (sy – port.bottom) / (port.top – port.bottom )
3. 视口坐标系到视平面坐标系的转换公式:
fx = frustum.left + px * (frustum.right – frustum.left )
fy = frustum.bottom + py * (frustum.top – frustum.bottom )
frustum可以根据水平垂直fov视野及视平面d获得。
可以知道 frustum.left <=fx <= frustum.right; frustum.bottom <=fy <= frustum.top。
4. 根据视平面坐标及相机在世界坐标系中的dir轴、up轴、right轴,得到picking ray:
Pickray.origin = camera_worldlocation
Pickray.dir = camera_right * fx + camera_up * fy + camera_dir*1
第二步:根据pick ray跟世界坐标系中的物体进行相交测试,可以是包围盒测试或三角形测试。
主要是第一步获取世界空间坐标系中的射线原点及方向,容易出错;第二步容易理解就不详细描述了。
第一步:获取Picking Ray
给出窗口坐标W(x,y)、width、Height、Camera设置,返回射线原点及方向。
推导过程:窗口坐标->屏幕(视口)坐标->视平面坐标->世界坐标系中的射线原点及方向
1. 窗口坐标系到屏幕坐标系的转换公式:
sx = wx / width
sy = 1 – wy / height
2. 因为视口不一定是整个窗口区域,所以视口坐标:
px = (sx – port.left) / (port.right – port.left)
py = (sy – port.bottom) / (port.top – port.bottom )
3. 视口坐标系到视平面坐标系的转换公式:
fx = frustum.left + px * (frustum.right – frustum.left )
fy = frustum.bottom + py * (frustum.top – frustum.bottom )
frustum可以根据水平垂直fov视野及视平面d获得。
可以知道 frustum.left <=fx <= frustum.right; frustum.bottom <=fy <= frustum.top。
4. 根据视平面坐标及相机在世界坐标系中的dir轴、up轴、right轴,得到picking ray:
Pickray.origin = camera_worldlocation
Pickray.dir = camera_right * fx + camera_up * fy + camera_dir*1
第二步:根据pick ray跟世界坐标系中的物体进行相交测试,可以是包围盒测试或三角形测试。
主要是第一步获取世界空间坐标系中的射线原点及方向,容易出错;第二步容易理解就不详细描述了。
来源:https://www.cnblogs.com/winsonchen/archive/2008/03/16/1108461.html