2010-02-21 51 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]; 
} 
相關問題