2010-02-21 3 views
0

현재 스크린 공간에서 터치를 변환하려고합니다. 현재 작업중인 2D 게임에서 worldspace에있는 위치로 변경합니다.iPhone OS - 스크린 공간에서 월드 공간으로 변환

기본적으로 누군가 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을 초기화 코드를 게재 할 수 있습니까? –

+0

z를 -100으로 설정하지 마십시오. 투영 행렬은 실제 Z 값을 0과 1 사이의 값으로 변환합니다. 0은 가까운 평면이고 1은 먼 평면입니다. 0으로 설정하려고하면 원하는 것을 얻을 수 있습니다. – Sekhat

답변

0

처음에는 -[NSView convertPoint:toView:]을 사용하여 포인트를 얻고 싶다고 생각하고 가장 많이 본 피드를 먹습니다. 그러면 절대 좌표계가 표시됩니다.

그렇지 않으면 숫자가 올바른 배율을 잃어버린 곳을 볼 수 있도록 값 변환을보기 위해 중단 점/NSLogs를 설정하는 것이 좋습니다.

+0

화면 좌표가 정확하고 프로젝트의 유일한보기로 터치가 전송됩니다. 디버거에서 행렬과 벡터를 가져 와서 Mathematica의 알고리즘을 살펴보고 어딘가에서 오류가 없는지 확인했습니다. 현재 나의 추측은 내가 Z를 올바르게 고려하지 않는다는 것입니다. -2라고 말하면 작은 Z 값을 가졌다면 변환 후에 얻은 숫자는 의미가 있습니다. 그러나 -100에 그들은 이해가되지 않습니다. – longshot

+0

우리는 당신이 보는 것에 대한 느낌을 얻을 수 있도록 약간의 입출력을 제공해야합니다. 보고 싶은 출력의 예를 제공해야합니다. 수학은 매우 단순 해 보입니다. 그래서 나는 무엇이 잘못되었는지 명확하지 않습니다. – TechZen

0

투영 행렬의 반전을 사용하지 않는 해법을 제시하십시오.
인터넷 검색으로이를 발견 한 사람을위한 몇 가지 메모 - 여기에는 ID가 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]; 
} 
관련 문제