質問

I have an OpenGL ES 2.0 scene which contains only 2D objects. I am applying the following two matrices :

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);

In the touches began method I am then trying to map the touch point coordinates to the OpenGL ES 2.0 scene co-ordinates :

-(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];
    }
}
}

This code works in that it returns OpenGL co-ordinates - for example clicking in the middle of the screen successfully returns 0,0. The problem is however (I think) is that I somehow need to account for the zoom scale of the scene, as an object drawn with an origin of 150,0 does not match with where I click on the iPad (which returns 112,0 using the above code). Can anyone suggest how I can correct this ?

Thanks !

役に立ちましたか?

解決

This might be overkill for a 2D app, but the way you typically would do this for a 3D app is to make two vectors, a "far point," and a "near point," unproject them both using GLKUnproject or whatever other math library you want, then subtract the near point from the far point to get a ray in object coordinates which you can use to test for intersection using only the geometry without having to worry about projection or modelview matrices. Here's an example

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

In your case projectionMatrix is probably the identity since you are working in two dimensions, and modelViewMatrix is the scales, translates, rotates, shears, etc you've applied to your object.

Also, in case you were unaware, what you are asking is often referred to as "picking," and if you enter "OpenGL picking," into Google you may find better info on the subject than what you might have gotten before with just "converting coordinates."

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top