打开GL:将屏幕中的平移大小转换为世界大小

时间:2014-05-01 09:07:24

标签: ios opengl graphics

我正在ios 3D应用程序中使用两根手指实现平移。我在屏幕坐标(x,y)中有翻译值。现在我需要在右侧矢量中移动中心的眼睛和中心位置。问题是,如何计算向量的大小 - 我需要如何移动世界坐标中的位置?

1 个答案:

答案 0 :(得分:2)

基本上问题归结为逆转转换管道。由于您在3D空间中操作,但屏幕坐标是2D,您必须确定z值以增加2D屏幕坐标; ether决定固定的参考平面或在tap-midpoint下获得场景的深度。

在大多数情况下,转换管道是

NDC_to_Viewport ∘ Homogenize ∘ ViewSpace_to_ClipSpace ∘ ModelSpace_to_ViewSpace r

其中表示功能组成。

从模型空间到剪辑空间的映射

r ⟼ ViewSpace_to_ClipSpace ∘ ModelSpace_to_Viewspace r

通常是根据线性向量矩阵乘法实现的:

r_clip = P · V · M r

其中P表示投影,V表示M和模型矩阵。在OpenGL中,视图和模型矩阵复合到模型视图矩阵MV = V · M中(请记住,操作顺序与矩阵一致,它们是非交换的)。

同质化是使透视变换发挥作用的原因:它被定义为

Homogenization: r ⟼ r/r_w

NDC_to_Viewport将范围[-1; 1]映射到给定的视口坐标

NDC_to_Viewport: r ⟼ viewport_offset + viewport_extent * r / 2

这些是您必须撤消的操作。在gluUnProject中可以找到实际的实现,其源代码可从例如台面

/* transform a point in window coordinates (winx,winy,winz) into model space */
GLint gluUnProject(GLdouble winx,GLdouble winy,GLdouble winz,
                   const GLdouble model[16],const GLdouble proj[16],
                   const GLint viewport[4],
                   GLdouble *objx,GLdouble *objy,GLdouble *objz)
{
    /* inverse transformation matrices and vectors */
    GLdouble m[16], A[16];
    GLdouble in[4],out[4];

    /* map viewport coordinates to NDC range [-1;1] */
    in[0]=(winx-viewport[0])*2/viewport[2] - 1.0;
    in[1]=(winy-viewport[1])*2/viewport[3] - 1.0;
    in[2]=2*winz - 1.0;
    in[3]=1.0;

    /* determine inverse transformation matrix */
    matmul(A,proj,model);
    invert_matrix(A,m);

    /* transform NDC space coordinates to model space */
    transform_point(out,m,in);
    if( fabs(out[3]) < 1e-6 ) {
       /* singular transformation, can not back transform. */
       return GL_FALSE;
    }

    *objx=out[0]/out[3];
    *objy=out[1]/out[3];
    *objz=out[2]/out[3];

    return GL_TRUE;
}

使用机芯开始和结束点的后投影位置,您可以获得一个差分矢量,您可以将其应用于相机的位置和目标点。