我在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
我的数学错了或我的代码错了吗?
答案 0 :(得分:2)
你的坐标系有些混乱。投影矩阵将其输入坐标(在完整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的方程相同的方程式。