假设在屏幕上单击,击中的位置为点s=(x,y)。由图可以看出,用户选中了茶壶。但是仅给出点s,应用程序还无法立即判断出茶壶是否被选中。所以针对这类问题,我们需要采用一项称为“拾
取(Picking)”的技术。
茶壶和屏幕点s之间的一种联系是茶壶被投影到了一个包含了s的区域中。更准确地说,茶壶被投影到了投影窗口中一个包含点p(点P位于投影窗口中)的区域中,其中点P对应于屏幕中的点s。
我们看到,如果自坐标原点发出一条拾取射线(picking ray)该射线将与那些其投影包围了点p的物体(即茶壶)相交。所以,一旦计算出了拾取射线,我们就可对场景中的每个物体进行遍历,并逐个测试射线是否与其相交,与射线相交的物体即为用户所拾取的物体。如果拾取射线不与场景中的任意物体相交,则用户便没有拾取到任何物体,而是选中了屏幕中的背景或些我们并不感兴趣的东西。
拾取原理步骤
- 给定所单击的屏幕点s,求出它在投影窗口中的对应点P。
- 计算拾取射线。即自坐标原点发出且通过点P的那条射线。
- 将拾取射线和物体模型变换至同一坐标系中。
- 进行物体/射线的相交判断。相交的物体即为用户所拾取的屏幕对象。
屏幕到投影窗口的变换
视口变换的矩阵为
(里面的参数为D3DVIEWPORT9中的参数)
对投影窗口中的点实施视口变换(将p放入1x4矩阵后与视口变换矩阵相乘),就得到了屏幕点。
,
视口变换之后z坐标并不作为2D图像的一部分进行存储,而是被保存在深度缓存中。解上面的方程后得到,