게임 세계에 x 축이 왼쪽에서 오른쪽으로, y 축이 위에서 아래로, z 축이 화면에서 벗어난 2D 게임을 작성 중입니다.
내 게임 세계는 하향식이지만 게임은 약간 기울어 져 렌더링됩니다.
월드 공간에서 스크린 공간으로 또는 그 반대로 투영하는 작업을하고 있습니다. 나는 다음과 같이 일하고있다.
var viewport = new Viewport(0, 0, this.ScreenWidth, this.ScreenHeight);
var screenPoint = viewport.Project(worldPoint.NegateY(), this.ProjectionMatrix, this.ViewMatrix, this.WorldMatrix);
NegateY()
확장 방법은 XNA 년대 이후는, 같은 소리 정확히 않는 Y 축이 아래로 대신 상단의 상하로 실행됩니다. 위의 스크린 샷은이 모든 기능을 보여줍니다. 기본적으로 3D 공간에 많은 포인트가 있으며 화면 공간에서 렌더링합니다. 카메라 속성을 실시간으로 수정하여 새로운 위치로 애니메이션을 볼 수 있습니다. 분명히 내 실제 게임은 포인트 대신 스프라이트를 사용하고 카메라 위치는 고정되지만, 그에 도달하기 전에 모든 수학을 제자리에 넣으려고합니다.
이제 다른 방법으로 다시 변환하려고합니다. 즉, 위의 화면 공간에서 x 및 y 지점이 주어지면 월드 공간에서 해당 지점을 결정하십시오. 예를 들어 녹색 사다리꼴의 왼쪽 하단을 커서로 가리키면 (0, 480)의 세계 공간 값을 얻고 싶습니다. Z 좌표는 무관하다. 또는 월드 공간으로 다시 매핑 할 때 z 좌표는 항상 0이됩니다. 기본적 으로이 메소드 서명을 구현하고 싶습니다.
public Vector2 ScreenPointToWorld(Vector2 point)
이 작업을 수행하기 위해 여러 가지를 시도했지만 운이 없습니다. 내 최근 생각은 Viewport.Unproject
서로 다른 니어 / 파 z 값으로 두 번 호출 하고 결과 Ray
를 계산하고 정규화 한 다음 기본적으로 내 세계의 지상 수준을 나타내는 Ray
와의 교차점을 계산해야 Plane
한다는 것입니다. 그러나 나는 마지막 단계에 갇혀있어서 복잡한 일을하고 있는지 확실하지 않았습니다.
아무도 이것을 달성하는 방법에 대해 올바른 방향으로 나를 가리킬 수 있습니까?
답변
나는 당신의 생각이 꽤 자리 잡았다 고 생각합니다! 먼저 근거리 평면과 원거리 평면을 2D 좌표의 Z 값으로 사용하여 커서의 광선을 계산합니다 (예 : Z 좌표에 0과 1을 사용). 이를 처리하는 도우미 방법은 다음과 같습니다.
public Ray GetScreenRay(Vector2 screenPosition, Viewport viewport, Matrix projectionMatrix, Matrix viewMatrix, Matrix worldMatrix)
{
Vector3 nearPoint = viewport.Unproject(new Vector3(screenPosition, 0f), projectionMatrix, viewMatrix, worldMatrix);
Vector3 farPoint = viewport.Unproject(new Vector3(screenPosition, 1f), projectionMatrix, viewMatrix, worldMatrix);
return new Ray(nearPoint, Vector3.Normalize(farPoint - nearPoint));
}
다음으로 Plane
자신의 입장과 일치 하는 인스턴스가 있어야합니다 . 이를 계산하는 가장 쉬운 방법은 평면에서 3 개의 점을 취하는 생성자를 사용하고 지상 객체에서 3 개의 정점을 전달하는 것입니다. 접지면을 계산하는 방법의 예 :
Plane groundPlane = new Plane(ground.Vertices[0], ground.Vertices[1], ground.Vertices[2]);
마지막 으로이 방법을 사용하여 광선과 평면 사이의 교점을 찾으십시오 . 아래 예와 같이 교차 결과를 계산하기 위해 결과 결과 매개 변수를 사용할 수 있습니다.
float? result;
mouseRay.Intersects(ref groundPlane, out result);
if(result != null)
Vector3 worldPoint = mouseRay.Position + mouseRay.Direction * result.Value;
이 NegateY
방법에 대해서도 무언가를해야 할 수도 있지만 어디에서 잘 모르겠습니다.