Ich habe eine einfache Realisierung der Entity / Component Game Engine.
Transformationskomponenten verfügen über Methoden zum Festlegen der lokalen Position, der lokalen Rotation, der globalen Position und der globalen Rotation.
Wenn für die Transformation eine neue globale Position festgelegt wird, ändert sich auch die lokale Position, um die lokale Position zu aktualisieren. In diesem Fall wende ich nur die aktuelle lokale Matrix der Transformation auf die Transformationsweltmatrix der Eltern an.
Bis dahin habe ich keine Probleme, ich kann die lokale Transformationsmatrix aktualisieren.
Aber ich habe Probleme damit, die lokale Position und den Rotationswert in der Transformation zu aktualisieren. Die einzige Lösung, die ich im Sinn habe, besteht darin, Translations- und Rotationswerte aus localMatrix of transform zu extrahieren.
Für die Übersetzung ist es ganz einfach - ich nehme nur Werte für die 4. Spalte. aber was ist mit Rotation?
Wie extrahiere ich Eulerwinkel aus der Transformationsmatrix?
Ist eine solche Lösung richtig?:
Um die Drehung um die Z-Achse zu ermitteln, können wir den Unterschied zwischen dem X-Achsenvektor von localTransform und dem X-Achsenvektor von parent.localTransform ermitteln und das Ergebnis in Delta speichern. Dann gilt Folgendes: localRotation.z = atan2 (Delta.y, Delta .x);
Gleiches gilt für die Drehung um X & Y, Sie müssen nur die Achse tauschen.
Es gibt eine großartige Zusammenfassung zu diesem Prozess von Mike Day: https://d3cw3dd2w32x2b.cloudfront.net/wp-content/uploads/2012/07/euler-angles1.pdf
Es ist jetzt auch in glm ab Version 0.9.7.0 vom 02.08.2015 implementiert. Überprüfen Sie die Implementierung .
Um die Mathematik zu verstehen, sollten Sie sich die Werte in Ihrer Rotationsmatrix ansehen. Außerdem müssen Sie die Reihenfolge kennen, in der die Rotationen angewendet wurden, um Ihre Matrix zu erstellen, damit die Werte ordnungsgemäß extrahiert werden können.
Eine Rotationsmatrix aus Eulerwinkeln wird durch Kombinieren von Rotationen um die x-, y- und z-Achse gebildet. Zum Beispiel kann mit der Matrix eine Drehung von θ Grad um Z durchgeführt werden
Ähnliche Matrizen existieren für die Drehung um die X- und Y-Achse:
Wir können diese Matrizen miteinander multiplizieren, um eine Matrix zu erstellen, die das Ergebnis aller drei Rotationen ist. Es ist wichtig zu beachten, dass die Reihenfolge, in der diese Matrizen miteinander multipliziert werden, wichtig ist, da die Matrixmultiplikation nicht kommutativ ist . Das bedeutet das
Rx*Ry*Rz ≠ Rz*Ry*Rx
. Betrachten wir eine mögliche Rotationsreihenfolge, zyx. Wenn die drei Matrizen kombiniert werden, ergibt sich eine Matrix, die folgendermaßen aussieht:Wo
Cx
ist der Cosinus desx
Drehwinkels,Sx
ist der Sinus desx
Drehwinkels usw.Nun besteht die Herausforderung darin , das Original zu extrahieren
x
,y
undz
Werte , die in die Matrix ging.Lassen Sie uns zuerst den
x
Winkel herausholen. Wenn wir dassin(x)
und kennencos(x)
, können wir die inverse Tangentenfunktion verwendenatan2
, um unseren Winkel zurückzugeben. Leider erscheinen diese Werte nicht von alleine in unserer Matrix. Aber wenn wir uns die Elemente genauer ansehenM[1][2]
und sehenM[2][2]
, dass wir es-sin(x)*cos(y)
genauso gut wissen wiecos(x)*cos(y)
. Da die Tangentenfunktion das Verhältnis der gegenüberliegenden und benachbarten Seiten eines Dreiecks ist, führt die Skalierung beider Werte um den gleichen Betrag (in diesem Fallcos(y)
) zum gleichen Ergebnis. Somit,Jetzt lass uns versuchen zu bekommen
y
. Wir wissensin(y)
vonM[0][2]
. Wenn wir cos (y) hätten, könnten wir esatan2
wieder verwenden, aber wir haben diesen Wert nicht in unserer Matrix. Jedoch aufgrund der pythagoreischen Identität , wir wissen , dass:So können wir berechnen
y
:Zuletzt müssen wir berechnen
z
. Hier unterscheidet sich der Ansatz von Mike Day von der vorherigen Antwort. Da wir zu diesem Zeitpunkt den Betragx
und diey
Rotation kennen, können wir eine XY-Rotationsmatrix erstellen und denz
Rotationsbetrag ermitteln, der zur Anpassung an die Zielmatrix erforderlich ist. DieRxRy
Matrix sieht folgendermaßen aus:Da wir wissen, dass
RxRy
*Rz
unserer Eingabematrix entsprichtM
, können wir diese Matrix verwenden, um zu Folgendem zurückzukehrenRz
:Die Umkehrung einer Rotationsmatrix ist ihre Transponierung , daher können wir diese erweitern auf:
Wir können jetzt nach
sinZ
undcosZ
durch Ausführen der Matrixmultiplikation lösen . Wir müssen nur die Elemente[1][0]
und berechnen[1][1]
.Hier ist eine vollständige Implementierung als Referenz:
quelle
M[1][3]
mitM[1][2]
undM[2][3]
mit korrigiertM[2][2]
.