Không gian màn hình đến không gian thế giới


10

Tôi đang viết một trò chơi 2D trong đó thế giới trò chơi của tôi có trục x chạy từ trái sang phải, trục y chạy từ trên xuống dưới và trục z ra khỏi màn hình:

nhập mô tả hình ảnh ở đây

Trong khi thế giới trò chơi của tôi từ trên xuống, trò chơi được hiển thị ở độ nghiêng nhẹ:

nhập mô tả hình ảnh ở đây

Tôi đang làm việc để chiếu từ không gian thế giới sang không gian màn hình và ngược lại. Tôi có trước đây làm việc như sau:

var viewport = new Viewport(0, 0, this.ScreenWidth, this.ScreenHeight);
var screenPoint = viewport.Project(worldPoint.NegateY(), this.ProjectionMatrix, this.ViewMatrix, this.WorldMatrix);

Các NegateY()phương pháp khuyến nông thực hiện chính xác những gì nó giống như âm thanh, vì XNA của y trục chạy dưới lên trên thay vì trên xuống dưới. Ảnh chụp màn hình ở trên cho thấy tất cả điều này làm việc. Về cơ bản, tôi có một loạt các điểm trong không gian 3D mà sau đó tôi kết xuất trong không gian màn hình. Tôi có thể sửa đổi các thuộc tính máy ảnh trong thời gian thực và thấy nó hoạt hình sang vị trí mới. Rõ ràng trò chơi thực tế của tôi sẽ sử dụng các họa tiết thay vì điểm và vị trí camera sẽ được cố định, nhưng tôi chỉ cố gắng để có được tất cả các phép toán tại chỗ trước khi đến đó.

Bây giờ, tôi đang cố gắng chuyển đổi ngược lại theo cách khác. Nghĩa là, cho một điểm xy trong không gian màn hình ở trên, xác định điểm tương ứng trong không gian thế giới. Vì vậy, nếu tôi chỉ con trỏ vào, giả sử, phía dưới bên trái của hình thang màu xanh lá cây, tôi muốn có được một không gian đọc thế giới của (0, 480). Các tọa độ z là không liên quan. Hoặc, đúng hơn, tọa độ z sẽ luôn bằng 0 khi ánh xạ trở lại không gian thế giới. Về cơ bản, tôi muốn thực hiện chữ ký phương thức này:

public Vector2 ScreenPointToWorld(Vector2 point)

Tôi đã thử một vài thứ để làm việc này nhưng không gặp may. Suy nghĩ mới nhất của tôi là tôi cần gọi Viewport.Unprojecthai lần với các giá trị z gần / xa khác nhau , tính toán kết quả Ray, bình thường hóa nó, sau đó tính toán giao điểm của Raymột Planeđiểm cơ bản đại diện cho thế giới của tôi. Tuy nhiên, tôi đã bị kẹt ở bước cuối cùng và không chắc liệu tôi có quá phức tạp không.

Bất cứ ai có thể chỉ cho tôi đi đúng hướng về cách để đạt được điều này?

Câu trả lời:


4

Tôi nghĩ rằng ý tưởng của bạn là khá nhiều tại chỗ! Trước tiên, tính toán một tia cho con trỏ của bạn bằng cả mặt phẳng gần và mặt phẳng xa làm giá trị Z cho tọa độ 2D của bạn (tức là sử dụng 0 và 1 cho tọa độ Z của bạn). Đây là một phương thức trợ giúp để xử lý việc đó:

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

Tiếp theo bạn sẽ cần phải có một Planeví dụ phù hợp với mặt bằng của bạn. Cách dễ nhất để tính toán nó là sử dụng hàm tạo lấy ba điểm trên mặt phẳng và truyền cho nó ba đỉnh bất kỳ từ vật thể mặt đất. Ví dụ về cách tính mặt phẳng đất:

Plane groundPlane = new Plane(ground.Vertices[0], ground.Vertices[1], ground.Vertices[2]);

Và cuối cùng tìm điểm giao nhau giữa tia và mặt phẳng bằng phương pháp này . Bạn có thể sử dụng tham số kết quả ngoài để tính tọa độ giao nhau như trong ví dụ dưới đây:

float? result;
mouseRay.Intersects(ref groundPlane, out result);
if(result != null)
    Vector3 worldPoint = mouseRay.Position + mouseRay.Direction * result.Value;

Bạn có thể phải làm một cái gì đó về NegateYphương pháp quá nhưng tôi không chắc chắn ở đâu.


Điều này là siêu hữu ích - cảm ơn bạn rất nhiều. Đó là dòng cuối cùng tôi đã mất. Tôi không thể biết phải làm gì với chiếc phao một khi tôi đã có nó! Tôi nghĩ rằng tôi sẽ phải có tên của bạn trong các khoản tín dụng trò chơi của mình :)
tôi--

@ user13414 Thật vậy, tài liệu này hơi khan hiếm về phương pháp đó và không đưa ra bất kỳ ví dụ nào về cách sử dụng khoảng cách để lấy lại điểm giao nhau.
David Gouveia
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.