Bitte beachten Sie, dass dies, obwohl es ähnlich klingt, nicht die übliche Frage ist, wie man einen Vektor auf eine andere dreht.
Ich möchte eine affine Transformation (entweder in Matrix oder in einer Quaternion + Vektorform) aus zwei Mengen von 3 Punkten ableiten. Diese können als "Markierungspunkte" auf starren Körpern oder als Endpunkte von "Vorwärts- und Aufwärts" -Vektoren betrachtet werden. Übersetzung und Rotation ist notwendig, Skalierung ist nicht notwendig. Außerdem wäre eine Quaternion + Vektorlösung ein Plus, da es mir erlauben würde, 1/3 mehr Instanzen in einen Zeichnungssatz zu stopfen (8 Uniformen statt 12). Die Absicht ist, ein System zu haben, um die Pose von (artikulierten oder nicht) befreiten Körpern auf eine intuitive Weise zu bestimmen, ohne eine komplizierte Hierarchie aufrechterhalten und gehen zu müssen.
Die erste naheliegende Vereinfachung besteht darin, den translationalen Teil zu eliminieren, indem man einen der Punkte auswählt und das "Ziel" von dem jeweiligen "Start" -Punkt subtrahiert. Jetzt müssen wir nur noch mit einer Rotation umgehen.
Es gibt eine wohlbekannte, kommerziell kostengünstige Lösung, eine Quaternion zu konstruieren, die einen Vektor auf einen anderen dreht, nämlich q (cross (v1, v2); sqrt (v1.len_sq * v2.len_sq) + dot (v1, v2) )) oder q (cross (v1, v2); 1 + Punkt (v1, v2)) für Einheitenlängenvektoren. Unglücklicherweise hat diese Methode keine Vorstellung von einer "Aufwärtsrichtung" und daher rotiert sie immer auf dem kürzesten Bogen (der Objekte fehlausrichten wird). Die naive Sache wäre, diese Methode einfach für beide Vektoren zu verwenden und die Quaternionen zusammen zu multiplizieren, aber es wird offensichtlich nicht so einfach funktionieren. Was man tun müsste, ist einen der beiden Vektoren auszuwählen (nennen wir das "vorwärts"), und eine Quaternion für diese zu erzeugen, dann den anderen ("oben") Vektor mit dieser Quaternion zu drehen, dann eine zweite Quaternion zu konstruieren für den gedrehten "Aufwärts" -Vektor (und den Ziel- "Aufwärts" -Vektor) und multipliziere schließlich die zweite mit der ersten Quaternion. Das wird, soweit ich das beurteilen kann, korrekt sein, aber es ist auch erschreckend kompliziert.
Nun ... wie bei Rotationsmatrizen ist mir die "Triadenmethode" bekannt, die ich wie folgt verstehe: - Orthonormalize die Vektorpaare (beide Anfang und Ende) - Dies ergibt zwei orthonormale Basen, die die jeweiligen Rotationsmatrizen für Start und Ende von einem "gemeinsamen Referenzrahmen" sind. Es spielt keine Rolle, welches Bezugssystem genau dies ist, wichtig ist nur, dass es für beide dasselbe ist. - S ist die Transformation von dem "gemeinsamen Rahmen" zu dem Startrahmen und D ist die Transformation zu dem Endrahmen. - Daher transformiert S -1 * D * v jeden Punkt vom Anfangs- bis zum Ende-Koordinatensystem (über den gemeinsamen Referenzrahmen). - S -1 == S T , da es eine orthonormale Matrix ist und S T * x = x * S - Also: S T * D * v = D * S * v
Das sollte funktionieren, aber es erscheint immer noch ziemlich kompliziert für etwas, das eigentlich wirklich sehr einfach sein sollte.
Gibt es eine einfachere und einfachere Lösung?
Um nur mit dem Rotationsteil zu arbeiten, wird Ihre zweite Methode funktionieren und ich vermute, dass sie gut funktionieren wird. Alternativ könnten Sie eine Hybrid der beiden Methoden verwenden, die ein bisschen einfacher sein könnte. Nehmen Sie die zwei Paare von zwei Vektoren an, die Sie oben konstruiert haben, jedes Paar in seinem eigenen Vektorraum. Berechne die orthogonale Basis jedes Paars und nenne sie X 0 und X 1 in einem Vektorraum und ihre entsprechenden Vektoren Y 0 und Y < sub> 1 im anderen Vektorraum. Sie müssen nun zwei Quaternion-Rotationen berechnen:
1) q 0 rotiert X <0> und X <1> bis X <0> und X << sub> 1 , so dass X '0 2) q 1 dreht X '1 bis X' '1 = Y1. Alles, was Sie tun müssen, ist den Winkel zwischen den Vektoren zu berechnen, da Sie bereits wissen, dass der Rotationsvektor nur X '1 Sie können q = q 1 <* q 0 berechnen, um die Rotation in einem einzigen Schritt durchzuführen.
Ihre "schrecklich komplizierte" Quaternion-Lösung würde im Allgemeinen nicht funktionieren. Sie müssten das zweite Paar Vektoren auf der Ebene orthogonal zur Achse der ersten Rotation projizieren, um sicherzustellen, dass die zweite Rotation orthogonal zur ersten ist.
Ich habe das Prinzip in meinem Blog beschrieben, wenn Sie interessiert sind: Ссылка
Vor der Drehung: u0, v0. Nach der Drehung: u2, v2.
%Vor%Ich bin mir nicht sicher, ob das die Lösung ist, die Sie wollen, aber der Code läuft überraschend schnell.
Wir müssen genau dieses Problem lösen. Hier ist, wie ich es mache:
Nennen Sie die Punkte P und W, also haben wir P1..P3 und W1..W3
Konstruiere drei Vektoren in jedem Raum wie folgt
%Vor%und
%Vor%Diese zwei Paare von drei Vektoren bilden jeweils eine nicht-orthogonale Basis, und Sie möchten herausfinden, wie Sie Ihre kartesischen Achsen (x y und z) in einem Raum darstellen, so dass Sie sie in einem anderen finden können. Um dies zu tun, konstruiere eine Matrix, so dass ihre Spalten die drei oben gefundenen Vektoren sind. Dann invertiere diese Matrix, wenn diese Inversion fehlschlägt, dann überspannt die nicht-orthogonale Basis den Raum nicht und das Problem kann nicht gelöst werden.
Ziehen Sie dann die drei Spalten aus der invertierten Matrix heraus. Diese Spalten sind die kartesischen Achsen in Bezug auf Ihre nicht-orthogonalen Basis (V1, V2 und V3). Daraus können wir eine orthogonale Basis rekonstruieren, die als Transformationsmatrix vom ersten Raum zum zweiten dient.
Wenn wir diese Matrix R nennen und R [row, column] als unsere Notation bezeichnen, dann lauten die Zeilen (oder Spalten, abhängig davon, wie Sie die Matrix verwenden) der endgültigen Transformationsmatrix:
%Vor%Nun, da eine der Spalten der ursprünglichen Matrix vor der Inversion das Kreuz der anderen zwei Spalten war, ist es wahrscheinlich möglich, die Inversion der Matrix zu optimieren. Ich habe mich nicht darum gekümmert - vor allem, weil sich in unserem Fall die drei Punkte P1..P3 nicht ändern und die invertierte Matrix zwischengespeichert werden kann.
Diese Methode hat den Vorteil, dass, wenn Sie eine halbwegs anständige Matrix / Vektor-Bibliothek haben, es sehr einfach zu implementieren ist. Und es verwendet keine Winkel, was immer eine gute Sache ist.
Tags und Links math