Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/98.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 打开总账:将屏幕中的平移大小转换为世界大小_Ios_Opengl_Graphics - Fatal编程技术网

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

Ios 打开总账:将屏幕中的平移大小转换为世界大小,ios,opengl,graphics,Ios,Opengl,Graphics,我在ios 3D应用程序中使用两个手指实现平移。我有屏幕坐标(x,y)中的平移值。现在我需要在右向量中移动眼睛和中心的位置。问题是,如何计算向量的大小——我需要在世界坐标系中移动多少位置?本质上,问题归结为反转转换管道。由于您在三维空间中操作,但屏幕坐标是二维的,因此必须确定z值以增加二维屏幕坐标;确定一个固定的参照平面,或在点击中点下获取场景的深度 在大多数情况下,转换管道是 NDC_to_Viewport ∘ Homogenize ∘ ViewSpace_to_ClipSpace ∘ Mod

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

本质上,问题归结为反转转换管道。由于您在三维空间中操作,但屏幕坐标是二维的,因此必须确定z值以增加二维屏幕坐标;确定一个固定的参照平面,或在点击中点下获取场景的深度

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

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;
}

通过运动起点和终点的反向投影位置,可以得到一个微分向量,可以应用于相机的位置和目标点。

透视投影还是正交投影?