iOS将TouchBegan坐标转换为OpenGL ES坐标

4

我是一名新手,正在学习OpenGL ES。我正在使用以下代码来检测我在GLKView(OpenGL ES 2.0)中点击的位置。我想知道是否触摸到了我的OpenGL绘制对象。这都是2D的。

如何将我获取的坐标转换为OpenGL ES 2.0坐标,它们似乎基于-1.0到1.0?是否已经有内置函数可以实现此功能?

谢谢。

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    CGRect bounds = [self.view bounds];

    UITouch* touch = [[event touchesForView:self.view] anyObject];

    CGPoint location = [touch locationInView:self.view];

    NSLog(@"x: %f y: %f", location.x, location.y);

}

2
我可以这样做:*x = ((*x/(bounds.size.width)) * 2.0) - 1.0; *y = (((bounds.size.height-*y)/(bounds.size.height)) * 2.0) - 1.0; 但是既然这是一个频繁的任务,是否有内置函数可用? - lppier
1个回答

2

-1到1是剪裁空间。如果您的坐标空间在显示屏上时处于剪裁空间中,我会说您忘记使用投影矩阵转换空间。如果您正在使用GLKBaseEffect(我不建议后期使用,因为它容易导致内存泄漏),那么您需要将<baseEffect>.transform.projectionMatrix设置为能够正确转换空间的矩阵。例如,

GLKBaseEffect* effect = [[GLKBaseEffect alloc] init];
GLKMatrix4 projectionMatrix = GLKMatrix4MakeOrtho(0, <width>, 0, <height>, 0.0f, 1.0f);
self.effect.transform.projectionMatrix = projectionMatrix;

widthheight分别是设备屏幕/ GLKView/等的宽度和高度。这些值会自动应用于您传递的坐标,因此您可以在x轴上使用从0到<width>,在y轴上使用从0到<height>的常规坐标,原点位于屏幕左下角。

如果您使用像我一样的自定义着色器,则可以使用以下方式将投影矩阵作为统一变量传递: glUniformMatrix4fv(shaderLocations.projectionMatrix,1,0,projection.m)

其中projection是矩阵,shaderLocations.projectionMatrix是统一变量的标识符-它的名称。然后,您需要通过投影矩阵将您的位置乘以。

一旦您已经通过手动传递矩阵或在GLKBaseEffect上设置正确的属性来转换剪辑空间,OpenGL空间和UIKit空间之间唯一的区别就是y轴被翻转了。我会像这样转换我通过touches方法和手势识别器接收到的触摸。

CGPoint openGLTouch = CGPointMake(touch.x, self.view.bounds.size.height - touch.y);

我会尽力解释,如果你有任何问题,但请记住,我自己对OpenGL也相对较新。 :)


你好,感谢详细的解释。我应该如何在我的代码功能touchesBegan中使用projectionMatrix呢? 我只想检查触摸是否发生在屏幕上OpenGL绘图的边界内。此外,在您对GLKBaseEffect的警告后,我运行了instruments以检查内存泄漏。已经运行了一段时间,并且没有任何问题 - 或许Apple在iOS 6.1中已经修复了它? - lppier
@Ippier 在 touchesBegan 中你不需要使用投影矩阵;你可以通过使用我上面指定的代码将投影矩阵传递给你的基础效果。通常你会在创建 GLKBaseEffect 的地方(比如 viewDidLoad)这样做。这样可以避免你处理裁剪空间坐标,并且让 GLKBaseEffect 在渲染时将屏幕坐标转换为裁剪空间。例如,对于一个横向 iPhone 上的居中对象,它的位置应该是 {240,180} 而不是奇怪的 {0.0,0.0}。另外,关于 GLKBaseEffect,他们可能已经修复了它。 - Metabble
我理解了 - 这意味着在将 projectionMatrix 应用到 GLKBaseEffect 上后,现在使用普通坐标 {240, 180} 来绘制屏幕,是这样吗? - lppier
应用投影矩阵后,坐标空间与您所使用的相同,除了具有翻转的 y 轴。OpenGL 的原点位于左下角,而不是像 UIKit 一样位于左上角。坐标沿屏幕向上增加,而对于 UIKit,坐标沿屏幕向下增加。将触摸的 y 值减去 GLKView/屏幕的高度即可获得 OpenGL 等效值。您可以使用我发布的最后一行代码将 UIView 上的触摸转换为其在 OpenGL 空间中的等效值。 - Metabble
@Ippier 没问题。我知道这些东西有时可能会非常令人困惑。另外,Tick Tock Trainer做得很好!我在你的网站上看了视频,它看起来是一个不错的应用程序。 :) - Metabble

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接