DirectX: Sprite bei ortho.Projektion zum Mausklick verschieben?
-
Wie geht das? Bei mir funktioniert es nur solange die Kamera im Ursprung ist und nicht rausgezoomt. Wenn sie bewegt wird oder zoomt, dann wird mein Sprite weit weg vom Mauszeiger gezeichnet.(ziemlich genau um die Bewegung der Kamera versetzt, beim Zoom weiß ich nicht)
Was könnte hier das Problem sein?
Ich setze den world Transform einmal am Start, pro Frame erneuere ich view und projection Tranformationen. Der Sprite hat eine Matrix die pro Frame mit der Position des Mauszeigers geupdated wird, also mitD3DXMatrixTranslation(&matrix,mousepos.x,mousepos.y); sprite->SetTransform(&matrix);
Jemand ne Idee was ich hier übersehen habe? Meiner Ansicht nach müsste das so passen..
-
Der Mauszeiger bewegt sich ja auf der Projektionsebene der Kamera.
Die Translation muss also entlang der beiden Vektoren stattfinden die durch die Basisvektoren der Kameramatrix gegeben sind.
-
Klingt gut, du meinst also dass ich jedesmal wenn ich ein Objekt zum Mauszeiger translieren will, die Position des Objekts (die ebenfalls in eine Matrix gespeichert wird) mal der Viewmatrix rechnen muss? Oder mal der Projektionsmatrix?
Der Mauszeiger bewegt sich auch auf dem Bildschirm, ich dachte es würde reichen wenn ich von einer Bildschirmkoordinate zur nächsten transliere..
-
Der Mauszeiger bewegt sich auch auf dem Bildschirm, ich dachte es würde reichen wenn ich von einer Bildschirmkoordinate zur nächsten transliere..
Der "Bildschirm" ist ja die Front-Clipping-Plane im Kameraraum.
Wenn Du nun ein Objekt im World-Space in dieser Ebene verschieben moechtest, brauchst Du die zwei Basisvektoren x,y jener Matrix die vom Objekt-Raum in den Kamera-Raum transformiert - die Basisvektoren einer Matrix zeigen ja an, wo in diesem Koordinatensystem rechts/oben/hinten ist.
Daraus resultiert eine Translation MausDeltaX*BasisX + MausDeltaY*BasisY die Du dann einfach auf die Objektmatrix multiplizierst.
-
Hm ich hoffe dass ich das jetzt richtig kapiert habe, hier ein Bsp. das ich erkläre, bitte sag mir ob ich das so richtig verstanden hab: (implementieren dauert noch bisschen)
Angenommen ich will ein Ding im Weltkoordinatensystem positionieren, und zwar durch Klick auf meinen Bildschirm (=Projektionsebene).Dann muss ich ja irgendwie von meiner Projektionsebene zurück auf das Weltkoordinatensystem kommen. So wie ich das verstanden habe, muss die Bildschirmmausposition mit den Basisvektoren der Projektionsmatrix multipliziert werden.
(Frage: muss ich hier nicht die Projektionsmatrix zuerst invertieren, sonst würde sie mir die Mauskoordinaten ja als Weltkoordinaten interpretieren und in die Projektionsebene transformieren?)SO, jetzt hab ich Kamerakoordinaten, ganz im Sinne der verkehrten Pipeline. Diese Kamerakoordinaten nochmal mit der (invertierten? selbe Frage wie vorhin) Kameramatrix multiplizieren, und voila: ich habe Weltkoordinaten die meine Mausposition repräsentieren.
Dann ist es ein Leichtes mein Objekt zu diesen Weltkoordinaten zu translieren!
-
muss ich hier nicht die Projektionsmatrix zuerst invertieren
Du hast zwei Matrizen, eine transformiert vom Objekt- in den Welt-Raum, die andere vom Welt- in den Kamera-Raum; das Produkt beider erledigt beides auf einmal.
Betrachtet man der einfacheren Vorstellbarkeit halber die zweite Matrix, so transformiert diese zwar vom Welt- in den Kameraraum aber die Basisvektoren beinhalten die Koordinatenachsen des Kamera-Systems relativ zum Welt-Raum.
Du kannst also einfach entlang dieser Vektoren translieren.
-
Also ich hab schon 3 Matrizen in meinem DirectX Programm. Eine für die Weltkoordinatentransformation, eine für die Transformation ins Kamerakoordinatensystem und eine für die Transformation in die Projektionsebene.
Wenn ich irgendwo hinklicke, klicke ich also in den Kameraraum, soweit denk ich liege ich zu 100% richtig. Hab jetz noch mit einem Kollegen diskutiert, und es sieht so aus dass ich die Multiplikation mit der invertierten Projektionsmatrix streichen kann, und einfach mit 1/zoomfaktor multiplizieren kann, da bei einer orthographischen Projektion ohnehin nur simpel skaliert wird. Der Schritt ist aber wichtig soweit ich das mitbekommen hab.diese zwar vom Welt- in den Kameraraum aber die Basisvektoren beinhalten die Koordinatenachsen des Kamera-Systems relativ zum Welt-Raum.
Du kannst also einfach entlang dieser Vektoren translieren.Vielleicht eine naive Frage, aber inwiefern helfen mir die Koordinatenachsen der Kamera? Schon klar dass die im Weltkoordinatensystem liegen.
Beispiel: Ich hab ein Sprite auf Weltkoordinaten 100/100. Ich klick im Bildschirm auf Schirmposition 500/500. (was, wie du gemeint hast, dasselbe wie Kamerakoordinaten sind). Meine Kamera schaut auf 50/50 und hat Länge 1000, Höhe 1000. Zoomfaktor ist 2. (der Zoomfaktor bedeutet: Länge u. Breite des Kamerasichtfeldes durch diesen Faktor bei einer ortho. Projektion)Das heißt: ich multipliziere 500/500 erstmal mit 0,5. Jetzt müsste man nach deiner Methode ein Mausdelta berechnen und mit dem entsprechenden Basisvektor der Kameramatrix multiplizieren. Vielleicht ist es schon zu spät, aber das Mausdelta krieg ich wie? Ist das "Mausklickposition - Position des Sprites in Kamerakoordinaten"?
Meine Vorgehensweise wäre:
+Mausklick mit invertierter Kameramatrix multiplizieren
+dann den resultierenden Vektor mit 1/zoomfaktor multiplizieren.
Übersehe ich hier irgendeine Offensichtlichkeit?
-
inwiefern helfen mir die Koordinatenachsen der Kamera?
Die zeigen Dir in welche Richtung im World-Space auf Deiner Projektionsebene "rechts" und "oben" verlaeuft, also genau die Richtung in der Du die Maus bewegst.
das Mausdelta krieg ich wie?
Differenz zwischen vorheriger und aktueller Mausposition.
-
Ok habs jetzt sogut wie gelöst, für alle Interessierten:
Mein Ansatz war richtig, man muss einfach die Matrizen die man auf seine Objekte (auf alle seine Objekte eben) auch auf den Mauszeiger anwenden..und zwar in umgekehrter Reihenfolge und invertiert.
Da es aber Unmengen an zusätzlichen Sachen bei diesen Dingen zu beachten gibt, (in welcher Reihenfolge muss man multiplizieren, welche Art von Matrix (row-order, column-order) und wie werden sie gespeichert (row-major, column-major), und wie groß der Backbuffer ist)hab ich das Ganze nicht händisch gemacht sondern glücklicherweise die von D3DX gelieferte Funktion D3DXVec3Unproject
verwendet.
Ich hoffe ich verschrei's nicht, -ganz funktionieren tuts ja noch nicht-
aber das sollte der richtige Weg sein.@hellijib: Grundsätzlich: danke für deine Geduld! Zu deinem Ansatz: Er würde vielleicht für reine Verschiebung auf der Kameraebene funktionieren, lässt aber die Projektion aus. Ohne dir zu Nahe treten zu wollen, aber du bist außerdem auf die Mehrzahl meiner Fragen nicht eingegangen.
-
Er würde vielleicht für reine Verschiebung auf der Kameraebene funktionieren, lässt aber die Projektion aus.
Oder man verwendet sinnvollerweise die finale Matrix World*View*Projection...
Du transformierst jetzt entlang der inversen Matrizen von der Projektionsebene in den Objekt-Raum. Die daraus resultierende Translation wird im Weiteren wieder mit World-, View- und Projections-Matrix transformiert, die Invertierung faellt wieder raus und Du erhaelst einen Vektor den Du schon hast.
Aber schoen dass Du Dein Problem loesen konntest.