A primeira coisa que você precisa entender é transformar pontos 3D em coordenadas de tela 2D e vice-versa. Aqui estão algumas respostas que eu dei sobre esse assunto; Entendendo 3D para tela , 3D para 2D .
Agora, para ir da coordenada do mouse em 2D para 3D, você precisa fazer uma transformação 3D em 2D para trás. Isto é bastante simples.
Uma coordenada objeto / local é transformada no espaço da tela multiplicando-a pela matriz mundial (obtenha a coordenada mundial), depois pela matriz de visualização (faça a coordenada mundial em relação à câmera) e depois pela matriz de projeção (obtenha a coordenada da tela) .
Fazer isso de trás para frente é fácil. Inverta todas as matrizes. Em seguida, multiplique pela projeção invertida e pela matriz de vista invertida. Agora, você não terá uma coordenada 3D para o mouse. O motivo é que estava faltando uma dimensão de dados. Então, o que você tem é um raio. Mas isso é bom. O raio terá uma coordenada de definição e será apontado na mesma direção que a câmera olha para o vetor. Você também pode perceber que não precisa inverter a matriz mundial de nenhum objeto. Isso é apenas porque você realmente não quer o raio no objeto / espaço local, não faz sentido, você provavelmente também tem seus volumes de colisão definidos no espaço do mundo.
Agora tudo o que você precisa fazer é o teste de interseção círculo / caixa / raio poli para descobrir se o raio se cruza com um objeto.
Encontre todos os objetos que estão cruzados e mantenha uma lista. Em seguida, calcule a distância de cada objeto da câmera. O mais próximo da câmera é aquele que o usuário deseja escolher.
Aqui está o código que você precisaria fazer isso no XNA. Essa solução também deve funcionar para outros tipos de projetos (desde que você a converta primeiro). Se você está renderizando apenas sprites 2D, provavelmente não está usando uma matriz de projeção, então entregue a função 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();
}
}
}