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

OpenGL中的拾取(Picking)

2013-09-21 22:15 225 查看
OpenGL本身支持基于图像空间的拾取,这里指的是几何拾取,即由屏幕点击触发一条射线,然后和场景中的物体求交,进而判断是否拾取到物体。现在先把OpenGL的投影矩阵和视口变换矩阵列出来:

OpenGL的投影矩阵:



OpenGL的视口变换矩阵:



假设鼠标点击屏幕(X,Y)位置,现在把它逆变换到NDC空间,假设其坐标为(Xn,Yn),结合视口变换矩阵可以求得:

Xn = ( X - (Vr + Vl)/2 ) / (Vr-Vl)/2 = ( X - VP_Center_X ) / Half_VP_Width

Yn = ( Y - (Vt + Vb)/2 ) / (Vt-Vb)/2 = ( Y - VP_Center_Y ) / Half_VP_Height

上面的参数分别代表视口的中心以及视口的宽度和高度。

接下来要把NDC坐标(Xn,Yn)变换到投影面坐标P(Xp,Yp)以构造拾取射线,现在假设在视图空间中有某个点(Xe,Ye,Ze)刚好投影到P点,则根据投影矩阵可得到下式:

Xn = -2n/(r-l)Xe/Ze - (r+l) / (r-l) = 2/(r-l)Xp - (r+l)/(r-l)

Yn = -2n/(t-b)Ye/Ze - (t+b) / (t-b) = 2/(t-b)Yp- (t+b)/(t-b)

可以进一步解得Xp,Yp:

Xp = ( Xn*(r-l) + (r+l) ) / 2;

Yp = ( Yn*(t-b) + (t+b) ) / 2;

求得了投影面坐标P之后,就可以在视图空间从原点到点Q(Xp,Yp,-n)可连接得到一条射线,接下来就用这条射线与场景中的物体进行相交测试了;可以把所有物体都变换到视图空间,然后直接为OQ求交,也可以把射线变换到世界空间甚至模型空间进行求交;由于仅仅变换射线的开销比变换物体的所有顶点小,因此可以把射线直接变换到模型空间进行求交。假设某个物体的世界变换矩阵为W,当前的视图变换矩阵为M,则射线在模型空间中的坐标为:Q' = inverse(W)*inverse(M)*Q,只需用射线OO‘与模型的面片进行求交测试即可,为了加快速度,可以用一些空间数据结构表示物体,如八叉树,层次包围盒等。

过几天把实现程序以及源代码贴上来。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息