Das erste, was Sie verstehen müssen, ist die Umwandlung von 3D-Punkten in 2D-Bildschirmkoordinaten und wieder zurück. Hier sind einige Antworten, die ich zu diesem Thema gegeben habe. Grundlegendes zu 3D zu Bildschirm , 3D zu 2D .
Um von Ihrer Mauskoordinate in 2D zu 3D zu gelangen, müssen Sie eine 3D-zu-2D-Transformation rückwärts durchführen. Das ist ziemlich einfach.
Ein Objekt / eine lokale Koordinate wird in den Bildschirmraum umgewandelt, indem es mit der Weltmatrix multipliziert wird (Weltkoordinate ermitteln), dann mit der Ansichtsmatrix (Weltkoordinate relativ zur Kamera erstellen) und dann mit der Projektionsmatrix (Bildschirmkoordinate ermitteln). .
Dies rückwärts zu tun ist einfach. Invertieren Sie alle Matrizen. Dann multiplizieren Sie mit der invertierten Projektion und dann mit der invertierten Ansichtsmatrix. Jetzt haben Sie keine 3D-Koordinate mehr für Ihre Maus. Der Grund dafür ist, dass Ihnen eine Datendimension fehlte. Was Sie also haben, ist stattdessen ein Strahl. Aber das ist gut. Der Strahl hat eine definierende Koordinate und zeigt in die gleiche Richtung wie der Kamerablick auf den Vektor. Möglicherweise stellen Sie auch fest, dass Sie die Weltmatrix für kein Objekt invertieren müssen. Das liegt nur daran, dass Sie den Strahl nicht wirklich im Objekt- / lokalen Raum haben möchten. Es hat keinen Sinn. Wahrscheinlich haben Sie Ihre Kollisionsvolumina auch im Weltraum definiert.
Jetzt müssen Sie nur noch den Schnittpunkt von Kreisen, Kästchen und Polystrahlen testen, um herauszufinden, ob sich der Strahl mit einem Objekt schneidet.
Suchen Sie alle Objekte, die sich schneiden, und führen Sie eine Liste. Berechnen Sie dann den Abstand jedes Objekts von der Kamera. Diejenige, die der Kamera am nächsten ist, ist diejenige, die der Benutzer auswählen wollte.
Hier ist der Code, den Sie dazu in XNA benötigen würden. Diese Lösung sollte auch für andere Arten von Projekten funktionieren (solange Sie sie zuerst konvertieren). Wenn Sie nur 2D-Sprites rendern, verwenden Sie wahrscheinlich keine Projektionsmatrix. Geben Sie der Funktion einfach die 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();
}
}
}