Ios 打开总账:将屏幕中的平移大小转换为世界大小
我在ios 3D应用程序中使用两个手指实现平移。我有屏幕坐标(x,y)中的平移值。现在我需要在右向量中移动眼睛和中心的位置。问题是,如何计算向量的大小——我需要在世界坐标系中移动多少位置?本质上,问题归结为反转转换管道。由于您在三维空间中操作,但屏幕坐标是二维的,因此必须确定z值以增加二维屏幕坐标;确定一个固定的参照平面,或在点击中点下获取场景的深度 在大多数情况下,转换管道是Ios 打开总账:将屏幕中的平移大小转换为世界大小,ios,opengl,graphics,Ios,Opengl,Graphics,我在ios 3D应用程序中使用两个手指实现平移。我有屏幕坐标(x,y)中的平移值。现在我需要在右向量中移动眼睛和中心的位置。问题是,如何计算向量的大小——我需要在世界坐标系中移动多少位置?本质上,问题归结为反转转换管道。由于您在三维空间中操作,但屏幕坐标是二维的,因此必须确定z值以增加二维屏幕坐标;确定一个固定的参照平面,或在点击中点下获取场景的深度 在大多数情况下,转换管道是 NDC_to_Viewport ∘ Homogenize ∘ ViewSpace_to_ClipSpace ∘ Mod
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中,视图和模型矩阵被合成为modelview矩阵MV=V·M
(请记住,操作顺序与矩阵有关,它们是非交换的)
同质化是透视变换工作的原因:它被定义为
Homogenization: r ⟼ r/r_w
NDC_to_视口将范围[-1;1]映射到给定的视口坐标
NDC_to_Viewport: r ⟼ viewport_offset + viewport_extent * r / 2
这些就是你必须逆转的行动。可以在glunproject
中找到一个实际的实现,该源代码可从Mesa获得
/* 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;
}
/*将窗口坐标(winx、winy、winz)中的点转换为模型空间*/
GLint GLUNPROJECT(GLdouble winx、GLdouble winy、GLdouble winz、,
常量GLdouble模型[16],常量GLdouble项目[16],
常量闪烁视口[4],
GLdouble*objx,GLdouble*objy,GLdouble*objz)
{
/*逆变换矩阵与向量*/
glm[16],A[16];
GLdouble-in[4],out[4];
/*将视口坐标映射到NDC范围[-1;1]*/
在[0]=(winx视口[0])*2/视口[2]-1.0;
在[1]=(winy视口[1])*2/视口[3]-1.0;
in[2]=2*winz-1.0;
in[3]=1.0;
/*求逆变换矩阵*/
matmul(A、项目、模型);
逆矩阵(A,m);
/*将NDC空间坐标转换为模型空间*/
变换_点(out,m,in);
if(晶圆厂(输出[3])<1e-6){
/*奇异变换,不能反变换*/
返回GL_FALSE;
}
*objx=out[0]/out[3];
*objy=out[1]/out[3];
*objz=out[2]/out[3];
返回GL_TRUE;
}
通过运动起点和终点的反向投影位置,可以得到一个微分向量,可以应用于相机的位置和目标点。透视投影还是正交投影?