2010-02-21 50 views
0

我目前正在尝试将屏幕空间中的触摸转换为我正在处理的2D游戏在worldspace中的位置。iPhone操作系统 - 屏幕空间转换为世界空间

我正在使用的视图具有与屏幕几乎相同的坐标系,基本上,如果有人触摸屏幕上的x = 345,y = 500像素,它将在视图上相同,尽管y会向后,因为opengl使用左下角0而不是左上角。

“摄像头”在0,0,0向下看负Z.我说“相机”,因为我还没有编码一个。现在我只是将每个精灵Z翻译为-100。

的伪代码迄今我已经试过(和数学一直双重检查)是这样的 -

// scale the screen point into a value from 0 to 1 
point = { screenPoint.x/screenWidth, screenPoint.y/screenHeight, -100, 1 } 
// doing a full inverse here, not just swapping rows and cols 
out = Inverse(viewProjection) * point 
inverseW = 1/out.w 
finalWorldCoord = out * inverseW 

的问题是,这是给我的值是比他们应该是什么样的方式少,我不知道为什么。

这是在iPhone OS 3.2上的OpenGL ES 2.0。

有没有人知道这样做的正确方法?

+0

你能告诉你的OpenGL初始化代码? – 2010-02-22 21:42:57

+0

不要将你的z设置为-100。投影矩阵将实际的Z值转换为介于0和1之间的值,其中0为近平面,1为远平面。尝试将其设置为0,那么应该给你你想要的。 – Sekhat 2010-02-24 09:38:56

回答

0

我认为开始你想要得到最初使用-[NSView convertPoint:toView:]的积分,并在最顶端的视图中提供。这会给你绝对的屏幕坐标。否则,我建议设置断点/ NSLogs来观察值转换,以便您可以看到数字在哪里丢失了正确的比例。

+0

屏幕坐标正确,触摸被发送到项目中唯一的视图。 我从调试器中获取矩阵和向量,并通过Mathematica中的算法验证了某处没有错误。 我目前的猜测是我没有正确解释Z.如果我有一个小的Z值,让我们说-2或者什么的话,我在变换之后得到的数字是有意义的。但在-100时他们没有意义。 – longshot 2010-02-21 23:39:08

+0

您应该提供一些输入和输出,以便我们可以了解您的看法。你应该提供一个你希望看到什么样的输出的例子。数学看起来很简单,所以我不清楚发生了什么问题。 – TechZen 2010-02-22 12:43:29

0

想出了一个解决方案,它不使用投影矩阵的反转。
对于任何通过Google搜索找到此内容的人的注意事项 - 此处假定视图矩阵的身份为0,0,0。由于我没有相机,这意味着我只需计算近平面和远平面上的点,然后直接进行射线平面相交测试。 如果您有视图矩阵,则需要将近平面和远平面上的点乘以视图矩阵的逆。

-

(void) touchToWorld:(CGPoint*)screenLocation andZCoordForPlane: (GLfloat) zValue 
{ 
    BGAssert([[GameManager sharedInstance] renderer] != nil, @"renderer is nil"); 
    BGAssert(screenLocation != NULL, @"location is NULL"); 
    GLint screenWidth = [[[GameManager sharedInstance] renderer] backingWidth]; 
    BGAssert(screenWidth > 0.0f, @"screen width is <= 0"); 
    GLint screenHeight = [[[GameManager sharedInstance] renderer] backingHeight]; 
    BGAssert(screenHeight > 0.0f, @"screen height <= 0"); 
    GLfloat aspect = [[[GameManager sharedInstance] renderer] aspect]; 
    BGAssert(aspect > 0.0f, @"aspect ratio is <= 0"); 
    GLfloat fov = [[[GameManager sharedInstance] renderer] fov]; 
    BGAssert(fov > 0.0f, @"fov is <= 0"); 

    GLfloat near = [[[GameManager sharedInstance] renderer] nearplane]; 
    GLfloat far = [[[GameManager sharedInstance] renderer] farplane]; 

    // convert to GL coordinates 
    GLfloat newX = (screenLocation->x/(screenWidth/2.0f) - 1) * aspect; 
    GLfloat newY = 1.0f - (screenLocation->y/(screenHeight/2.0f)); 

    GLfloat fovInRadians = fov * (PI/180.0f); 
    GLfloat ratioX = tanf(fovInRadians/2.0f) * newX; 
    GLfloat ratioY = tanf(fovInRadians/2.0f) * newY; 

    ESVector3 pointOnNearPlane; 
    ESVector3 pointOnFarPlane; 

    memset(&pointOnNearPlane, 0, sizeof(ESVector3)); 
    memset(&pointOnFarPlane, 0, sizeof(ESVector3)); 

    pointOnNearPlane.v[0] = ratioX * near; 
    pointOnNearPlane.v[1] = ratioY * near; 
    pointOnNearPlane.v[2] = near; 
    pointOnNearPlane.v[3] = 1.0f; 

    pointOnFarPlane.v[0] = ratioX * far; 
    pointOnFarPlane.v[1] = ratioY * far; 
    pointOnFarPlane.v[2] = far; 
    pointOnFarPlane.v[3] = 1.0f; 

    ESVector3 lineBetweenNearAndFarPlane; 
    memset(&lineBetweenNearAndFarPlane, 0, sizeof(ESVector3)); 
    esVec3Sub(&lineBetweenNearAndFarPlane, &pointOnFarPlane, &pointOnNearPlane); 

    // we need to do ray to plane. Point on near plane is the rays origin 
    // normalized direction is the rays direction 
    ESVector3 normalizedDirection; 
    memset(&normalizedDirection, 0, sizeof(ESVector3)); 
    esVec3Normalize(&normalizedDirection, &lineBetweenNearAndFarPlane); 

    ESVector4 plane; 
    memset(&plane, 0, sizeof(ESVector4)); 

    plane.v[0] = 0.0f; 
    plane.v[1] = 0.0f; 
    plane.v[2] = 1.0f; 
    plane.v[3] = zValue; 


    GLfloat vd = esVec3Dot((ESVector3*)&plane, &normalizedDirection); 
    GLfloat v0 = -(esVec3Dot((ESVector3*)&plane, &pointOnNearPlane) + plane.v[3]); 
    GLfloat t = v0/vd; 
    ESVector3 intersectPoint; 
    memset(&intersectPoint, 0, sizeof(ESVector3)); 

    intersectPoint.v[0] = pointOnNearPlane.v[0] + normalizedDirection.v[0] * t; 
    intersectPoint.v[1] = pointOnNearPlane.v[1] + normalizedDirection.v[1] * t; 
    intersectPoint.v[2] = pointOnNearPlane.v[2] + normalizedDirection.v[2] * t; 

    point.x = intersectPoint.v[0]; 
    point.y = intersectPoint.v[1]; 
} 
相关问题