Picking
Picking bezeichnet in der 3D Programmierung das auswählen von Objekten in einer 3D Szene durch anklicken mit dem Maus-Cursor. Prinzipiell gibt es verschiedene Ansätze wie dies umgesetzt werden kann. Die unterschiedlichen Möglichkeiten haben verschiedene Vor- und Nachteile, z.B. im Bezug auf Geschwindigkeit und Präzision.
Möglichkeiten für Picking
Ein möglicher Ansatz ist das Pixel-Picking. Bei dieser Methode wird die Szene über die Grafikhardware gerendert und anhand der Mauszeigerposition der ausgewählte Pixel bestimmt. Dann wird überprüft zu welchem Objekt der an dieser Stelle gerenderte Pixel gehört und dieses wurde dann "gepicked". Der Vorteil bei dieser Methode ist dass man die Hardware Beschleunigung der Grafikkarte nutzen kann, die Nachteile sind dafür dass die Genauigkeit des Picking von der Auflösung beim Render Vorgang abhängt, dass zusätzliche Render-Pässe notwendig werden und dass es nicht einfach ist das Objekt zu bestimmen zu dem der ausgewählte Pixel gehört.
Eine weiter Möglichkeit ist das Picking anhand von Ray Tracing. Dabei wird anhand der Position des Mauszeigers und der Kamera ein Strahl von der entsprechenden Kamera-Position in die Szene geschickt und anhand des Schnittpunkts des Strahls das ausgewählte Objekt bestimmt. Der Vorteil dieser Methode ist dass es beliebig genau sein kann, je nachdem ob man für die Berechnung des Schnittpunkts Bounding Volumes oder direkt die Triangles der Modelle verwendet. Zusätzlich ist es einfach das getroffene Objekt zu identifizieren und zusätzliche Informationen über den Auftreffpunkt zu berechnen, z.B. die Oberflächennormale am Schnittpunkt. Der Nachteil ist dafür dass die Strahlverfolgung nicht von einer Beschleunigung durch die Grafikkarte profitieren kann sondern nur auf der CPU läuft.
Picking mit Ray Tracing in XNA
Wir empfehlen aufgrund der Vorteile ein Picking mittels Ray Tracing zu implementieren. Wie dies in XNA sehr einfach gemacht werden kann zeigt das folgenden Code-Beispiel. Der CameraManager im Code Beispiel ist eine statische Klasse welche mehrere Kameras verwalten kann und besitzt eine Property ActiveCamera welche die aktuell verwendete Kamera liefert. Kameras werden durch eine Camera Klasse repräsentiert, welche die Bestandteile die im Kamera-Artikel aufgezählt sind besitzt.
//get the current mouse state for the mouse position on the screen
MouseState ms = Mouse.GetState();
//create two positions in screenspace using the mouse position
Vector3 nearSource = new Vector3(ms.X, ms.Y, 0f);
Vector3 farSource = new Vector3(ms.X, ms.Y, 1f);
//get the currently active camera
Camera activeCamera = CameraManager.ActiveCamera;
//unproject the screenspace positions into world space using the camera, it's Viewport struct and it's other properties
Vector3 nearPoint = activeCamera.Viewport.Unproject(nearSource, activeCamera.ProjectionMatrix, activeCamera.ViewMatrix, Matrix.Identity);
Vector3 farPoint = activeCamera.Viewport.Unproject(farSource, activeCamera.ProjectionMatrix, activeCamera.ViewMatrix, Matrix.Identity);
//create the direction vector for the ray from the calculated positions
Vector3 direction = farPoint - nearPoint;
direction.Normalize();
//create a ray with the calculated origin and direction
Ray pickingRay = new Ray(nearPoint, direction);
//now make a ray cast into the scene using this ray, the first hit object is the picked object
//...