Ich muss Übersetzungs-, Skalierungs- und Rotations-Gizmos implementieren und habe Probleme mit dem Rotations-Gizmo. Grundsätzlich weiß ich nicht, wie ich die Mausbewegung übersetzen soll, um zu bestimmen, in welche Richtung das Objekt gedreht werden soll.
Mit Rotations-Gizmo (Widget) meine ich so etwas wie das Folgende:
Für die Übersetzungs- und Skalierungs-Gizmos, die als 3 Achsen dargestellt werden, mache ich Folgendes: Ich mache einen Vektor aus der Differenz zwischen der vorherigen und der aktuellen Mausposition im Bildschirmbereich. Dann multiplizieren Sie diesen Vektor mit der Umkehrung der Ansichts- und Projektionsmatrizen, was mir einen Vektor der Mausbewegung im Weltraum gibt. Dann nehme ich das Punktprodukt des Vektors im Weltraum mit der ausgewählten Achse. Auf diese Weise kann ich feststellen, ob die Mausbewegung mit der Achse übereinstimmt oder von der Achse entfernt ist.
Aber ich kann nicht dasselbe für das Rotations-Gizmo tun. Das Rotations-Gizmo wird als 3 Kreise dargestellt, die jeweils eine Rotation um eine Achse darstellen. Sobald auf einen Kreis geklickt wird, muss ich eine Möglichkeit finden, die Mausbewegung zu verschieben, um zu bestimmen, in welche Richtung das Objekt um die ausgewählte Achse gedreht werden soll. Ich weiß nicht, wie ich das machen soll. Bitte helfen Sie.
Es ist wichtig zu beachten, dass ich die Farbauswahl und nicht das Raycasting verwende, um festzustellen, wo auf das Gizmo geklickt wurde. Dies bedeutet, dass ich nicht den Punkt habe, an dem der Strahl auf das Gizmo im Weltraum trifft, um anzufangen. Ich erwähne dies, weil ich mir Beispiele angesehen habe, die Raycasting wie libgizmo verwenden, und ich glaube nicht, dass ich das Gleiche tun kann.
Vielen Dank im Voraus für jede Hilfe.
Antworten:
Ordnen Sie die Mausposition dem Kreis zu, indem Sie eine imaginäre Linie zwischen der Maus und dem Mittelpunkt des Gizmos in der Ebene des aktuellen Kreises zeichnen. Tun Sie dies für die Start- und aktuellen Positionen.
Dann können Sie leicht die Quaternion-Rotation um die Mitte vom Anfang bis zum Ende erhalten, indem Sie dies tun
normalize(quat(1+dot(v_1, v_2), cross(v_1, v_2)))
.Dies funktioniert, weil das Punktprodukt der cos des Winkels zwischen den Vektoren ist und das Kreuz der Vektor senkrecht zu den 2 Vektoren ist (auch bekannt als der Drehwinkel) und die Länge der Sünde des Winkels zwischen den Vektoren hat. Dies bedeutet, dass Sie die doppelte Quaternion daraus erstellen können. Dann können Sie diese doppelte Quaternion mit der Einheitsquaternion verknüpfen, um die Rotation zu erhalten, die Sie benötigen.
Mit diesen Informationen können Sie jedoch einen Arcball erstellen, indem Sie die Maus auf den Ball projizieren, der das Gizmo ist, und auf diese Weise die Start- und Endvektoren verwenden.
quelle
Die Antwort von Ratchet Freak könnte funktionieren. Ich bin mir nicht sicher, ich habe nicht viel Zeit damit verbracht, weil ich nicht wusste, wie ich die Quaternion aus dem Punkt- und Kreuzprodukt wie beschrieben erstellen kann.
Was wir letztendlich gemacht haben war:
Projizieren Sie die Mitte des Gizmos auf den Bildschirmbereich.
Ermitteln Sie den Winkel zwischen den Vektoren GizmoToLastMouse und GizmoToCurrentMouse mithilfe der Punktproduktformel: acos (Punkt (GizmoToLastMouse, GizmoToCurrentMouse) / (GizmoToLastMouse.Length () * GizmoToCurrentMouse.Length ()))
Ermitteln Sie das Vorzeichen des Winkels, indem Sie das Kreuz aus GizmoToLastMouse und GizmoToCurrentMouse nehmen und es mit dem normalen Bildschirm punktieren.
Erhalten Sie ein weiteres Zeichen (mal 1.0f oder -1.0f) basierend auf der Ausrichtung des Gizmos, indem Sie das Punktprodukt zwischen der gedrehten Achse und einem Vektor von der Mitte des Gizmos zur Kamera bringen
Wenden Sie die Drehung basierend auf dem Winkel und den beiden Vorzeichen auf die entsprechende Achse an
Es gibt vielleicht einen besseren Weg, dies zu tun, aber dies funktioniert ziemlich gut für unsere Bedürfnisse.
quelle
quat(cos(angle/2), axis*sin(angle/2))
und Sie wissen, dass das Punktprodukt uns gleich cos (Winkel) mal dem Produkt der Längen und das Kreuzprodukt die Achse mal sin (Winkel) mal das Produkt der Längen ist. Wenn Sie es normalisieren, erhalten Sie leicht die Quaternion derselben Drehung, jedoch mit doppeltem Winkel. Um die richtige quaternion erhalten Sie tun können ,slerp(unit, quat, 0.5)
die nach dem Ende nach oben als inliningnormalize(unit+quat);