Điều đầu tiên bạn cần nắm bắt tốt là chuyển đổi các điểm 3D thành tọa độ màn hình 2D và quay lại. Dưới đây là một vài câu trả lời tôi đã đưa ra về chủ đề đó; Hiểu 3D sang màn hình , 3D sang 2D .
Bây giờ, để chuyển từ tọa độ chuột của bạn thành 2D sang 3D, bạn cần thực hiện chuyển đổi 3D sang 2D. Điều này khá đơn giản.
Một tọa độ đối tượng / cục bộ được chuyển thành không gian màn hình bằng cách nhân nó với ma trận thế giới (lấy tọa độ thế giới), sau đó bằng ma trận xem (tạo thế giới tọa độ tương đối với máy ảnh) và sau đó là ma trận chiếu (lấy tọa độ màn hình) .
Làm điều này ngược là dễ dàng. Đảo ngược tất cả các ma trận. Sau đó nhân với phép chiếu ngược, sau đó là ma trận khung nhìn ngược. Bây giờ, bạn sẽ không có tọa độ 3D cho chuột. Lý do là vì bạn đã thiếu một thứ nguyên của dữ liệu. Vì vậy, những gì bạn có là một tia thay thế. Nhưng đó là tốt. Tia sẽ có tọa độ xác định và sẽ được chỉ cùng hướng với camera nhìn vào vectơ. Bạn cũng có thể nhận thấy rằng bạn không cần phải đảo ngược ma trận thế giới cho bất kỳ đối tượng nào. Đó chỉ là vì bạn không thực sự muốn tia trong không gian vật thể / cục bộ, không có điểm nào, có lẽ bạn cũng có khối lượng va chạm của mình được xác định trong không gian thế giới.
Bây giờ tất cả những gì bạn phải làm là kiểm tra giao điểm hình tròn / hộp / đa tia để tìm ra nếu tia giao nhau với một đối tượng.
Tìm tất cả các đối tượng được giao nhau và giữ một danh sách. Sau đó tính toán khoảng cách của từng đối tượng từ camera. Cái gần camera nhất là cái mà người dùng muốn chọn.
Đây là mã bạn sẽ cần để làm điều này trong XNA. Giải pháp này cũng sẽ hoạt động cho các loại dự án khác (miễn là bạn chuyển đổi nó trước). Nếu bạn chỉ hiển thị các họa tiết 2D thì có lẽ bạn không sử dụng ma trận chiếu, vì vậy chỉ cần sử dụng hàm Matrix.Identity.
using System;
using Microsoft.Xna.Framework;
namespace FluxPrototype
{
/// <summary>
/// Contains functions useful in working with XNA Vectors.
/// </summary>
static class VectorHelper
{
/// <summary>
/// Converts a Vector2 position into a 3D ray.
/// </summary>
/// <param name="Position">The 2D position.</param>
/// <param name="View">The view matrix for the camera.</param>
/// <param name="Projection">The projection matrix for the camera.</param>
/// <param name="Point">The returned point defining part of the 3D ray.</param>
/// <param name="Direction">The direction of the 3D ray.</param>
public static void Unproject(Vector2 Position, Matrix View, Matrix Projection, out Vector3 Point, out Vector3 Direction)
{
if (Position == null)
Position = Vector2.Zero;
// Create two 3D points from the position. The first one we will return.
Point = new Vector3(Position, 0);
Vector3 Point2 = new Vector3(Position, 1);
// Transform the points.
Matrix InvertedProjection = Matrix.Invert(Projection);
Point = Vector3.Transform(Point, InvertedProjection);
Point2 = Vector3.Transform(Point2, InvertedProjection);
Matrix InvertedView = Matrix.Invert(View);
Point = Vector3.Transform(Point, InvertedView);
Point2 = Vector3.Transform(Point2, InvertedView);
// Use the difference between the points to define the ray direction.
// This will only be the camera direction if the view frustum is orthographic.
Direction = (Point2 - Point);
Direction.Normalize();
}
}
}