Umrechnung: Euler Angles -> Unit-Axis(Quaternion) -> Euler Angles?
-
Hallo erstmal. Am Freitag habe ich damit begonnen NVIDIA PhysX in meine Grafik Engine zu Implementieren. Bisher klappte auch alles super: Gegenstände Kollidieren & Fallen – Genau wie sie es sollen – dies Gilt zumindest für Positionen der Gegenstände. Die Rotationen machen mir Probleme, bzw. Nicht die Rotationen selbst sondern das Format in welchem PhysX sie erwartet und auch zurückgibt. Seit Gestern versuche ich nun meine Rotationen in Quaternion umzurechnen und zurück, aber das ganze klappt nicht so wirklich. Natürlich habe ich als erste Reference erstmal Google hinzugezogen. Ich muss aber sagen, dass ich Quaternion's schon früher nicht wirklich verstanden und dh. Für's erste Links liegen gelassen habe. (Eigentlich habe ich sie auch nie Benötigt, da ich immer Mit Eulerischen Winkeln und Matrizen gearbeitet habe).Nachdem ich jetzt fast den ganzen Abend versucht habe das Problem selber mit Hilfe der Formeln auf Wikipedia: http://en.wikipedia.org/wiki/Conversion_between_quaternions_and_Euler_angles zu lösen, habe ich mich nun doch dazu durch gerungen hier zu Fragen.
Als Erstes muss ich für PhysX Die Positionen und Rotationen fürdie Objekt Erstellung Setzen. Diese Werden in einem PxTransform Zwischengespeichert(Eigentlich nur Ein Positions Vector und ein Quaternion):
... PxVec3 Rot=PxVec3(DEGTORAD(-90),DEGTORAD(45),DEGTORAD(0));//Die Rotation ist einfach mal zbs. (-90,45,0) (im Realen Programm kommen die Werte natürlich direkt als Radian an) //heir müssten die Eulerischen Winkel zu Unit-Axis Konvertiert werden - Aber wie? PxTransform Transform=PxTransform(Pos,//Die Position der Objektes. PxQuat(Angle,Rot));//Hier ist das Problem: //Der Konstruktor erwartet für die Erstellung des Quaternion einen Angle und eine Unit Axis Rotation. Ich habe Zwar im Internet diverse Formeln dazu gefunden, bin aber nicht wirklich schlau daraus geworden :(
Später müssen die Werte dann von Quaternion wieder zurück gerechnet werden.
... PxTransform Transform=pActor->getGlobalPose();//Hohle Pos/rot als PxTransform float Angle; PxVec3 Rot; Transform.toRadiansAndUnitAxis(Angle,Rot); //hier müsste zurück in Eulerische winkel Konvertiert werden.
Also kurz gesagt: Könnte mir Bitte Jemand noch einmal Erklären was genau Unit-Axis sind, und wie ich sie von und in Eulerische Winkel Konvertiere? bzw. Direkt in Quaternion? Versucht dabei aber bitte das ganze etwas einfacher zu erklären,da ich auch erst 15 bin und einiges für mich noch nicht so leicht verständlich ist.Was jetzt nicht heißt das ich von der Materie absolut keine Ahnung habe, währe aber dennoch schön wenn ihr zbs. Formeln Etwas genauer Erklärt;).
Vielen Dank für eure Hilfe!
LG SK
-
Also ich hab aus irgendwelchen alten Sourcecodes von mir mal das hier raus gekramt:
template<typename T> matrix<T, 3, 3> to_matrix3(const quaternion<T>& q) { // |1-2y²-2z² 2xy-2zw 2xz+2yw 0| // | 2xy+2zw 1-2x²-2z² 2yz-2xw 0| // | 2xz-2yw 2yz+2xw 1-2x²-2y² 0| // | 0 0 0 1| Matrix<T, 3, 3> r; r(0, 0) = 1 - 2 * (q.y() * q.y()) - 2 * (q.z() * q.z()); r(0, 1) = 2 * q.x() * q.y() - 2 * q.z() * q.w(); r(0, 2) = 2 * q.x() * q.z() + 2 * q.y() * q.w(); r(1, 0) = 2 * q.x() * q.y() + 2 * q.z() * q.w(); r(1, 1) = 1 - 2 * (q.x() * q.x()) - 2 * (q.z() * q.z()); r(1, 2) = 2 * q.y() * q.z() - 2 * q.x() * q.w(); r(2, 0) = 2 * q.x() * q.z() - 2 * q.y() * q.w(); r(2, 1) = 2 * q.y() * q.z() + 2 * q.x() * q.w(); r(2, 2) = 1 - 2 * (q.x() * q.x()) - 2 * (q.y() * q.y()); return r; }
Wenn der Code das macht was drauf steht, sollte er dir helfen.
-
Der Unitvektor ist ganz einfach die Achse um die du rotierst.
Die einfachen Eulerwinkel rotieren um die X/Y oder Z-Achse. Wenn du aber mehrere dieser Rotationen hintereinander ausführst, kannst du das genauso als Rotation um eine beliebige andere Achse ausdrücken. Das "unit" im Namen steht nur dafür, dass die Achse auf Länge 1 normiert ist.
Das Thema ist etwas zu komplex um das hier im Forum in einen kurzen Beitrag zu pressen. Dazu gibt es auch viele TUtorials und Einführungstexte.. Schau dich einfach mal im Internet um.
-
otze schrieb:
Die einfachen Eulerwinkel rotieren um die X/Y oder Z-Achse. Wenn du aber mehrere dieser Rotationen hintereinander ausführst, kannst du das genauso als Rotation um eine beliebige andere Achse ausdrücken...
... und mit einer beliebig anderen Achse meine ich nicht X,Y oder Z, sondern einer die irgendwie durch den Raum geht. Dh, es gibt eine Achse - einen Vektor ω - um den du rotierst und der Vektor gleichbleibt, sich also nicht verändert.
Jetzt hast du deine Rotationsmatrix und wendest diese auf den Vektor - deiner Drehachse - ω an. Was passiert? ω ändert sich nicht, wir wollen ja um ω rotieren. Das heißt, wir suchen im Raum einen Vektor der sich durch die Rotation nicht beinflussen lässt. Das sieht dann mathematisch so aus:
Jetzt kannst du BrutoForce alle ω Kombinationen durchgehen, bis diese Gleichung erfüllt ist und du somit deine Drehachse gefunden hast. Oder du siehst das ω hier den Eigenvektor zum Eigenwert 1 ist. Sagen dir EV und EW etwas? Wenn nicht dann stoppen wir hier und klatschen dir die Endformeln hinWenn du dann ω hast, fehlt dir nur noch der Winkel, um den du um diese Achse rotiert, dein angle also.
-
Erstmal vielen Dank für die Antworten! Die Sache ist mir nun schon um einiges Klarer geworden! EV=Eigenvektor,EW=Eigenwert? ... meine ich zumindest schonmal gelesen zu haben. Sagt mir aber leider jetzt nicht wirklich viel ...
LG SK
-
puuhhh, ich sehe du hast noch nichtmal die Rotationsmatrix. Mir vergeht die Motivation... Weißt du wie du mit deinen Winkeln die R-Matrix bildest?
-
Warum genau willst du die Quaternion in Eulerwinkel zurückrechnen. Das ist nicht nur nicht sinnvoll, sondern auch sehr schwer bis prinzipiell unmöglich. Vergiss doch besser einfach Eulerwinkel, es gibt kaum eine weniger brauchbare Repräsentation von Rotationen in 3D...
-
Rotations Matrix Bilden Bekomme ich denke ich noch hin, wenn auch noch nie Aktiv gemacht.(Mir hat es immer gereicht zu wissen wälche DirectX Funktionen das für mich übernehemen...^^) Die Formeln sind Mir aber Bekannt und ich könnte das ganze denke ich auch in C++ Verwirklichen.
-dot
Selbst wenn ich die Engine Direkt auf Matrizen oder halt Quaternions umsatteln würde, müsste ich sie dennoch in Eulerische Winkel umrechnen - Allein Schon für den Level Editor, da jedes andere Format unnötig Kompliziert anzugeben Währe ... Also umrechnen muss ich so oder so irgentwann. Zudem Lassen Sich Eulerische Winkel natürlich Wesentlich leichter Händeln...
-
Ok, wenn du wirklich meinst, unbedingt Eulerwinkel zu brauchen, dann guck mal hier, hier bzw. hier...
-
Danke an alle antworten. Ich habe es jetzt geschafft,Werde aber nochmal an der Architektur Für meine Engine Feilen.
Anstadt der Euler angles werde ich eine Klasse einbauen Wälche mit Matrizen arbeitet, aber die Möglichkeit gibt Euler Angles vom Matrix zu hohlen und diesen auch von Euler Angles zu Setzen.(Also dann nur Für den Editor)
Das wird denke ich auch der Geschwindigkeit zu gute kommen.Gemacht habe ich das Ganze Jetzt Folgendermaßen, wird aber wie gesagt nicht so bleiben:
PxTransform Transform; PxVec3 Rod;//Rotation Als Euler angle D3DXMATRIX RotMxX,RotMxY,RotMxZ, RotMx; D3DXMatrixRotationX(&RotMxX,Rod.x);//Rotiere den Matrix Auf der X Achse D3DXMatrixRotationY(&RotMxY,Rod.y);//Rotiere den Matrix Auf der Y Achse D3DXMatrixRotationZ(&RotMxZ,Rod.z);//Rotiere den Matrix Auf der Z Achse RotMx=RotMxX*RotMxY*RotMxZ;//x,y,z in RotMx Multiplizieren Transform=PxTransform(DXVECTOPXVEC3(Pos),PxQuat(DXMATRIXTOPXMATRIX(RotMx)));//DXMATRIXTOPXMATRIX Konvertiert den Matrix nur in einen PxMatrix(ich hätte natürlich sofort einen solchen nehmen können, //Dann hätte ich aber die D3DX Funktionen nicht verwenden können und hätte alles selber machen müssen bzw. Erst nachsehen wie das ganze unter PhyX Klappt...So war's erstmal einfacher.) //Und Wir haben einen Fertigen Quaternion!
... Und Wieder Zurück nach Euler Angle:
PxTransform Transform=pActor->getGlobalPose();//Transform hohlen D3DXMATRIX RodMatrix; PxMat33 PxRodMatrix=PxMat33(Transform.q);//PxMatrix Aus Quaternion erstellen(Ist mir gerade eben Aufgefallen, das PhysX Das einem sogar abnimmt) RodMatrix=PXMATRIX33TODXMATRIX(PxRodMatrix);//Zurück Konvertieren PxVec3 Rod; Rod.z=atan(RodMatrix.m[0][1]/RodMatrix.m[0][0]); Rod.x=atan(RodMatrix.m[1][2]/RodMatrix.m[2][2]); Rod.y=asin(RodMatrix.m[0][2]); //Und wir haben Wieder die Euler Angles(Wenn auch leicht ungenau)
Die Lösung Obliegt also weniger Mathematischer Logik, als mehr einem Genauen Nachsehen in die NVIDIA PhysX Doku ...
Ich werde wie gesagt sowieso die Engine Nochmal ein Bischen umbasteln was das an geht. Jedenfalls Funktioniert es erstmal.Denke Für Alle Antworten!
LG SK