我在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/