Ich versuche, einen Spieleditor zu erstellen, der derzeit nur verschiedene Arten von Formen und dergleichen platziert. Ich mache das in Windows Forms, während ich 3D mit XNA zeichne. Wenn ich also ein paar Formen auf dem Bildschirm habe und auf den Bildschirm klicke, möchte ich in der Lage sein, "welches" dieser Objekte zu identifizieren, auf die Sie geklickt haben.
Was ist die beste Methode dafür? Da zwei Objekte hintereinander liegen, sollte es in der Lage sein, das vordere und nicht das dahinter liegende zu erkennen, und auch wenn ich die Kamera drehe und auf das dahinterliegende klicke, sollte es es identifizieren und nicht das erste.
Gibt es dafür kluge Wege?
xna
c#
editors
map-editor
windows-forms
Deukalion
quelle
quelle
Antworten:
In diesem Video zeige ich, wie es mit Code gemacht wird ... die Projektion / Ansicht ist isometrisch, aber alle Berechnungen werden in 3D durchgeführt ...
http://www.youtube.com/watch?v=axHp1f3RlHM
Wenn ich den Mausstrahl berechne, überprüfe ich, ob eine Ebene kollidiert ... aber das Verfahren ist analog, um eine Liste von Begrenzungskugeln zu überprüfen, die Ihren Objekten zugeordnet sind.
Der Algorithmus sollte folgendermaßen aussehen:
quelle
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.
quelle
Normalerweise erstelle ich einfach ein Begrenzungsvolumen mit meiner Maus. Der Ursprung ist dort, wo ich geklickt habe. Führen Sie dann einen Schnittpunkttest durch, indem Sie alle Objekte in einer Schleife durchlaufen. Sortieren Sie dann die Liste, die Sie zurückerhalten, nach den gewünschten Kriterien und wählen Sie Element 0 aus.
quelle
Eine Idee, die ich überlegt, aber noch nicht ausprobiert habe:
Zeichnen Sie ein Offscreen-Bild genauso wie das reale Bild, aber keine Texturen usw. Zeichnen Sie einfach Ihre Objekte, jedes Objekt in einer anderen "Farbe", wobei die "Farbe" eigentlich nur eine Objektnummer ist. Um herauszufinden, was sich unter der Maus befindet, sehen Sie sich einfach die Farbe des Pixels auf dem alternativen Bild an.
Natürlich bedeutet dies viel verschwendete Arbeit, aber es ist die GPU, die dies tut, und nicht die CPU, und es ist sicher, dass die Dinge nach genau den gleichen Regeln gelöst werden.
quelle