我正在ios 3D应用程序中使用两根手指实现平移。我在屏幕坐标(x,y)中有翻译值。现在我需要在右侧矢量中移动中心的眼睛和中心位置。问题是,如何计算向量的大小 - 我需要如何移动世界坐标中的位置?
答案 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;
}
使用机芯开始和结束点的后投影位置,您可以获得一个差分矢量,您可以将其应用于相机的位置和目标点。