Wie Nathan Reed und Teodron herausgestellt haben, lautet das Rezept zum Drehen eines Vektors v um eine Quaternion q von Einheitslänge :
1) Erstellen Sie eine reine Quaternion p aus v . Dies bedeutet einfach, eine vierte Koordinate von 0 hinzuzufügen:
p=(vx,vy,vz,0)⇔p=(v,0)
2) Multipliziere es vorab mit q und postmultipliziere es mit dem Konjugat q * :
p′=q×p×q∗
3) Dies führt zu einer weiteren reinen Quaternion, die in einen Vektor zurückverwandelt werden kann:
v′= ( p′x, p′y, p′z)
Dieser Vektor v′ ist v um q gedreht .
Das funktioniert aber alles andere als optimal . Quaternion-Multiplikationen bedeuten Tonnen und Tonnen von Operationen. Ich war neugierig auf verschiedene Implementierungen wie diese und entschied mich herauszufinden, woher diese kamen. Hier sind meine Erkenntnisse.
Wir können q auch als die Kombination eines dreidimensionalen Vektors u und eines Skalars s beschreiben :
q= ( ux, uy, uz, s ) ⇔ q= ( u , s )
Durch die Regeln der Quaternion-Multiplikation und da das Konjugat einer Quaternion mit Längeneinheit einfach umgekehrt ist, erhalten wir:
p′= qp q∗= ( u , s ) ( v , 0 ) ( - u , s )= ( s v + u × v , - u ⋅ v ) ( - u , s )= ( ( - u ⋅ v ) ( - u ) + s ( s v + u × v ) + ( s v + u × v ) × ( - u ) , … ) = ( ( u ⋅ v ) u + s2v + s ( u × v ) + s v × ( - u ) + ( u × v ) × ( - u ) , … )
Der skalare Teil (Ellipsen) ergibt Null, wie hier beschrieben . Interessant ist der Vektorteil, AKA unser gedrehter Vektor v ' . Es kann mit einigen grundlegenden Vektoridentitäten vereinfacht werden :
v′= ( u ⋅ v ) u + s2v + s ( u × v ) + s ( u × v ) + u × ( u × v )= ( u ⋅ v ) u + s2v + 2 s ( u × v ) + ( u ≤ v ) u - ( u ≤ u ) v= 2 ( u ⋅ v ) u + ( s2- u ⋅ u ) v + 2 s ( u × v )
Das ist jetzt viel optimaler ; Zwei-Punkt-Produkte, ein Kreuzprodukt und ein paar Extras: Etwa die Hälfte der Vorgänge. Was im Quellcode so etwas ergeben würde (unter der Annahme einer generischen Vektor-Mathematik-Bibliothek):
void rotate_vector_by_quaternion(const Vector3& v, const Quaternion& q, Vector3& vprime)
{
// Extract the vector part of the quaternion
Vector3 u(q.x, q.y, q.z);
// Extract the scalar part of the quaternion
float s = q.w;
// Do the math
vprime = 2.0f * dot(u, v) * u
+ (s*s - dot(u, u)) * v
+ 2.0f * s * cross(u, v);
}
vprime = v + ((cross(u, v) * s) + cross(u, cross(u, v)) * 2.0f
Handelt es sich um eine ähnliche Optimierung? Es sieht etwas ähnlich aus, ist aber nicht dasselbe - es werden nur Kreuzprodukte verwendet, keine Punktprodukte. Der ursprüngliche Quellcode kann in die gefunden werden offizielle GLM Repository type_quat.inl Datei in demoperator*
die eine Quaternion und einen Vektor nimmt (vec<3, T, Q> operator*(qua<T, Q> const& q, vec<3, T, Q> const& v)
)Erstens ist q ^ (- 1) nicht -q / Betrag (q); es ist q * / (Betrag (q)) ^ 2 (q * ist das Konjugat; das negiert alle Komponenten mit Ausnahme der realen). Natürlich können Sie die Division durch die Größe weglassen, wenn alle Ihre Quaternionen bereits normalisiert sind, was normalerweise in einem Rotationssystem der Fall ist.
Bei der Multiplikation mit einem Vektor erweitern Sie den Vektor einfach zu einem Quaternion, indem Sie die Realkomponente eines Quats auf Null und seine IJK-Komponenten auf das XYZ des Vektors setzen. Dann führen Sie die Quaternion-Multiplikationen durch, um v 'zu erhalten, und extrahieren dann die ijk-Komponenten erneut. (Der Realteil von v 'sollte immer Null plus oder minus eines Gleitkommafehlers sein.)
quelle
Erste Beobachtung: Das Gegenteil von
q
ist nicht-q/magnitude(q)
, das ist völlig falsch. Rotationen mit Quaternionen implizieren, dass diese 4D-Äquivalente für komplexe Zahlen eine einheitliche Norm haben und daher auf der S3-Einheitenkugel in diesem 4D-Raum liegen. Die Tatsache, dass ein Quat einheitlich ist, bedeutet, dass seine Norm istnorm(q)^2=q*conjugate(q)=1
und dass das Inverse des Quats sein Konjugat ist.Wenn ein Einheitsquaternion als
q=(w,x,y,z)
= (cos (t), sin (t) v ) geschrieben wird, dann ist sein Konjugatconjugate(q)=(w,-x,-y,-z)
= (cos (t), - sin (t) v ), wobei t die Hälfte des Drehwinkels und v ist ist die Rotationsachse (natürlich als Einheitsvektor).Als dieser Hamilton-Typ beschloss, mit komplexen Zahlenäquivalenten in höheren Dimensionen herumzuspielen, stieß er auch auf einige nette Eigenschaften. Wenn Sie zum Beispiel eine vollständig reine Quaternion verwenden
q=(0,x,y,z)
(kein skalarer Teil w !), Können Sie diesen Mist als Vektor betrachten (es ist tatsächlich eine Quat auf dem Äquator der S3-Kugel, die eine S2-Kugel ist!). ! - Wenn man bedenkt, wie technisch behindert die Menschen im 19. Jahrhundert sind, scheint uns eyePhone Cowboys heutzutage). Also nahm Hamilton diesen Vektor in seiner Quat-Form:v=(0,x,y,z)
und führte eine Reihe von Experimenten durch, in denen die geometrischen Eigenschaften von Quats untersucht wurden.woher
Beobachtung: Das q * (0, v) * Konj (q) muss ein anderes Quat der Form (0, v ') sein. Ich werde die scheinbar komplizierte Erklärung, warum dies geschieht, nicht durchgehen, aber wenn Sie eine rein imaginäre Quaternion (oder in unserem Fall einen Vektor!) Durch diese Methode drehen, müssen Sie eine ähnliche Art von Objekt erhalten: reines imaginäres Quat. und du nimmst seinen imaginären Teil als Ergebnis. Da haben Sie es, die wunderbare Welt der Rotationen mit Quaternionen in einer Nussschale.
ANMERKUNG : zu wem auch immer mit dieser überbeanspruchten Phrase einspringt: Quats sind gut, weil sie Kardansperren vermeiden. Sollten ihre Fantasie zuerst freisetzen !! Quats sind ein bloß "eleganter" mathematischer Apparat und können durch die Verwendung anderer Ansätze insgesamt vermieden werden, wobei derjenige, den ich als vollständig geometrisch äquivalent empfinde, der Achsenwinkelansatz ist.
CODE : Die C ++ - Bibliothek, die ich mir vorstelle, ist recht simpel, verfügt jedoch über alle Matrix-, Vektor- und Quat-Operationen, die ein 3D-Grafiker benötigen sollte, ohne mehr als 15 Minuten zum Erlernen zu verschwenden. Sie können die hier geschriebenen Dinge damit testen in 15 Minuten, wenn Sie kein C ++ - Neuling sind. Viel Glück!
quelle
Hier ist eine alternative Möglichkeit, einen Vektor durch eine Quaternion zu transformieren. Es ist die Art und Weise, wie MS es im xna-Framework tut. http://pastebin.com/fAFp6NnN
quelle
Ich habe versucht, dies von Hand herauszufinden und fand die folgende Gleichung / Methode:
Ich würde mich freuen, wenn sich jemand die MT-Ableitung ansieht, die ich unter http://pastebin.com/8QHQqGbv verwendet habe
In meiner Notation habe ich q ^ (- 1) verwendet, um konjugiert und nicht invers und verschiedene Bezeichner zu bedeuten, aber ich hoffe, dass es nachvollziehbar ist. Ich denke, dass die Mehrheit Recht hat, vor allem, wenn der reale Teil des Vektors verschwinden würde.
quelle