我在iOS中设置了一个2D opengl视图,左上角为原点,右下角为(768,1366)

我的投影矩阵设置如下:

projectionMtx = GLKMatrix4MakeOrtho( 0, 768, 1366, 0, 10, -10);


发生触摸事件时,坐标位于物理坐标中,因此我需要将其转换为自己的逻辑坐标,因此我想像这样:

V_physical = M_projection * V_logical

所以V_logical = M_projection_invert * V_phsical

我实现了这样的代码:

(void)touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event
{
    UITouch* touch = [[event allTouches] anyObject];
    CGPoint location = [touch locationInView:self.view];

    GLKVector4 locationVector = {
        (float)location.x,
        (float)location.y,
        0,
        0,
    };

    GLKVector4 result = GLKMatrix4MultiplyVector4(GLKMatrix4Invert(projectionMtx, nullptr),locationVector);


    NSLog(@"touch %.2f %.2f", location.x, location.y);
    NSLog(@"vector %.2f %.2f", result.v[0], result.v[1]);
}


但是,这是我从测试中得到的:

touch 367.00 662.00

vector 140928.00 -452151.28

我的数学错误还是代码错误?

最佳答案

您的坐标系统有些混乱。投影矩阵将其输入坐标(在完整的3D管道中通常称为“眼睛坐标”)映射为裁剪坐标。对于平行投影,剪辑坐标与归一化设备坐标(NDC)相同,在x和y方向上的范围为[-1,1]。

这意味着您的正射投影:

projectionMtx = GLKMatrix4MakeOrtho( 0, 768, 1366, 0, 10, -10);


将[0,768]的x范围映射到[-1,1],将[1366,0]的y范围映射到[-1,1]。矩阵完成的映射为:

xNdc = (2.0 / 768.0) * xEye - 1.0
yNdc = (2.0 / -1366.0) * yEye + 1.0


与此相反的是:

xEye = (768.0 / 2.0) * (xNdc + 1.0)
yEye = (-1366.0 / 2.0) * (yNdc - 1.0)


应用此逆变换可得出:

(768.0 / 2.0) * (367.0 + 1.0) = 141312.0
(-1366.0 / 2.0) * (662.0 - 1.0) = -451463


由于目前无法解释的原因,这与您所得到的略有不同(看起来是一次性的差异),但是非常相似。

这显然是没有意义的。要使用反投影变换,您的输入坐标应在[-1,1]范围内。

在您的用例中,由于您设置了投影转换来以像素为单位转换坐标,并且接收到的触摸输入也以像素为单位,因此您真的不需要做任何事情就可以在OpenGL坐标系中获得触摸输入。它们已经在相同的坐标系(像素)中。

如果使用任何其他投影。您将首先将触摸坐标映射到[-1,1]范围,然后应用反投影变换。坐标映射将使用与上面将眼坐标映射到NDC相同的方程。

关于ios - 卡在矩阵运算错误中,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/28022387/

10-12 00:14
查看更多