0

我有一个仅包含 2D 对象的 OpenGL ES 2.0 场景。我正在应用以下两个矩阵:

width = 600;

CC3GLMatrix * projection = [CC3GLMatrix matrix];
height = width * self.frame.size.height / self.frame.size.width;
[projection populateFromFrustumLeft:-width/2 andRight:width/2 andBottom:-height/2 andTop:height/2 andNear:4 andFar:10];
glUniformMatrix4fv(_projectionUniform, 1, 0, projection.glMatrix);

CC3GLMatrix * modelView = [CC3GLMatrix matrix];
[modelView populateFromTranslation:CC3VectorMake(xTranslation ,yTranslation, -7)];
glUniformMatrix4fv(_modelViewUniform, 1, 0, modelView.glMatrix);

在 touches started 方法中,我尝试将触摸点坐标映射到 OpenGL ES 2.0 场景坐标:

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
NSLog(@"Touches Began");
UITouch *touch = [[event allTouches] anyObject];
CGPoint touchPoint = [touch locationInView:self];

float differentialWidth = (768-width)/2; //Accounts for if OpenGL view is less than iPad width or height.
float differentialHeight = (1024-height)/2;
float openGlXPoint = ((touchPoint.x - differentialWidth) - (width/2));
float openGlYPoint = ((touchPoint.y - differentialHeight) - (width/2));
NSLog(@"X in Scene Touched is %f", openGlXPoint);

CGPoint finalPoint = CGPointMake(openGlXPoint, openGlYPoint);

for (SquareObject * square in squareArray) {
    if (CGRectContainsPoint(stand.bounds, finalPoint)) {
        NSString * messageSquare = (@"Object name is %@", square.Name);
        UIAlertView *message = [[UIAlertView alloc] initWithTitle:@"Touched"
                                                          message:messageSquare
                                                         delegate:nil
                                                cancelButtonTitle:@"OK"
                                                otherButtonTitles:nil];
        [message show];
    }
}
}

此代码的工作原理是它返回 OpenGL 坐标 - 例如,单击屏幕中间成功返回 0,0。但是问题是(我认为)是我需要以某种方式考虑场景的缩放比例,因为以 150,0 为原点绘制的对象与我在 iPad 上单击的位置不匹配(返回 112,0使用上面的代码)。谁能建议我如何纠正这个问题?

谢谢 !

4

1 回答 1

2

这对于 2D 应用程序来说可能是多余的,但您通常会为 3D 应用程序执行此操作的方式是制作两个向量,一个“远点”和一个“近点”,使用 GLKUnproject 或任何其他数学库取消投影它们您想要,然后从远点减去近点,以获得对象坐标中的射线,您可以使用它仅使用几何图形来测试相交,而不必担心投影或模型视图矩阵。这是一个例子

bool testResult;
GLint viewport[4];
glGetIntegerv(GL_VIEWPORT, viewport);

GLKVector3 nearPt = GLKMathUnproject(GLKVector3Make(tapLoc.x, tapLoc.y, 0.0), modelViewMatrix, projectionMatrix, &viewport[0] , &testResult);

GLKVector3 farPt = GLKMathUnproject(GLKVector3Make(tapLoc.x, tapLoc.y, 1.0), modelViewMatrix, projectionMatrix, &viewport[0] , &testResult);

farPt = GLKVector3Subtract(farPt, nearPt);
//now you can test if the farPt ray intersects the geometry of interest, perhaps
//using a method like the one described here http://www.cs.virginia.edu/~gfx/Courses/2003/ImageSynthesis/papers/Acceleration/Fast%20MinimumStorage%20RayTriangle%20Intersection.pdf

在您的情况下,projectionMatrix 可能是标识,因为您在二维中工作,而 modelViewMatrix 是您应用于对象的比例、平移、旋转、剪切等。

此外,如果您不知道,您所询问的内容通常被称为“挑选”,如果您在 Google 中输入“OpenGL 挑选”,您可能会发现关于该主题的信息比您之前通过“转换坐标。”

于 2013-10-18T17:05:21.567 回答