Ich lese gerade das Online-Buch "Learning Modern 3D Graphics Programming" von Jason L. McKesson
Ab sofort bin ich mit dem Gimbal-Lock-Problem beschäftigt und weiß, wie es mit Hilfe von Quaternionen gelöst werden kann.
Allerdings gleich hier auf der Quaternions-Seite .
Ein Teil des Problems ist, dass wir versuchen, eine Orientierung als eine Reihe von 3 akkumulierten axialen Rotationen zu speichern. Orientierungen sind Orientierungen, keine Rotationen. Und Orientierungen sind mit Sicherheit keine Rotationsserie. Wir müssen also die Ausrichtung des Schiffes als eine Ausrichtung behandeln, als eine bestimmte Größe.
Ich denke, dies ist der erste Punkt, an dem ich anfange, verwirrt zu sein. Der Grund dafür ist, dass ich den dramatischen Unterschied zwischen Orientierungen und Rotationen nicht sehe. Ich verstehe auch nicht, warum eine Orientierung nicht durch eine Reihe von Rotationen dargestellt werden kann ...
Ebenfalls:
Der erste Gedanke zu diesem Zweck wäre, die Orientierung als Matrix beizubehalten. Wenn die Zeit gekommen ist, um die Ausrichtung zu ändern, wenden wir einfach eine Transformation auf diese Matrix an und speichern das Ergebnis als neue aktuelle Ausrichtung.
Dies bedeutet, dass jedes Gieren, Nicken und Rollen, das auf die aktuelle Ausrichtung angewendet wird, relativ zu dieser aktuellen Ausrichtung ist. Welches ist genau das, was wir brauchen. Wenn der Benutzer ein positives Gieren anwendet, soll dieses Gieren sie relativ zu der Position drehen, auf die sie gerade zeigen, und nicht relativ zu einem festen Koordinatensystem.
Das Konzept verstehe ich, aber ich verstehe nicht, wie, wenn das Akkumulieren von Matrixtransformationen eine Lösung für dieses Problem ist, der Code auf der vorherigen Seite nicht genau das ist.
Hier ist der Code:
void display()
{
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClearDepth(1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glutil::MatrixStack currMatrix;
currMatrix.Translate(glm::vec3(0.0f, 0.0f, -200.0f));
currMatrix.RotateX(g_angles.fAngleX);
DrawGimbal(currMatrix, GIMBAL_X_AXIS, glm::vec4(0.4f, 0.4f, 1.0f, 1.0f));
currMatrix.RotateY(g_angles.fAngleY);
DrawGimbal(currMatrix, GIMBAL_Y_AXIS, glm::vec4(0.0f, 1.0f, 0.0f, 1.0f));
currMatrix.RotateZ(g_angles.fAngleZ);
DrawGimbal(currMatrix, GIMBAL_Z_AXIS, glm::vec4(1.0f, 0.3f, 0.3f, 1.0f));
glUseProgram(theProgram);
currMatrix.Scale(3.0, 3.0, 3.0);
currMatrix.RotateX(-90);
//Set the base color for this object.
glUniform4f(baseColorUnif, 1.0, 1.0, 1.0, 1.0);
glUniformMatrix4fv(modelToCameraMatrixUnif, 1, GL_FALSE, glm::value_ptr(currMatrix.Top()));
g_pObject->Render("tint");
glUseProgram(0);
glutSwapBuffers();
}
Nach meinem Verständnis wird das, was er tut (Ändern einer Matrix auf einem Stapel), nicht als Akkumulieren von Matrizen angesehen, da der Autor alle einzelnen Rotationstransformationen zu einer Matrix zusammengefasst hat, die oben auf dem Stapel gespeichert wird.
Ich verstehe eine Matrix so, dass sie verwendet wird, um einen Punkt, der relativ zu einem Ursprung ist (sagen wir ... dem Modell), und ihn relativ zu einem anderen Ursprung (der Kamera) zu machen. Ich bin mir ziemlich sicher, dass dies eine sichere Definition ist, aber ich habe das Gefühl, dass etwas fehlt, was mich daran hindert, dieses Gimbal-Lock-Problem zu verstehen.
Eine Sache, die für mich keinen Sinn macht, ist: Wenn eine Matrix den Unterschied zwischen zwei "Räumen" bestimmt, wie kommt es, dass eine Drehung um die Y-Achse zum Beispiel "rollen" den Punkt nicht in den "Rollenraum" setzt "die dann noch einmal in bezug auf diese Rolle transformiert werden können ... Mit anderen Worten, sollten keine weiteren Transformationen bis zu diesem Punkt in bezug auf diesen neuen" Rollenraum "erfolgen und daher darf die Rotation nicht in bezug auf die vorherige sein" Modellraum ", der die kardanische Verriegelung verursacht.
Das ist der Grund, warum die Kardansperre auftritt, richtig? Das liegt daran, dass wir das Objekt um die X-, Y- und Z-Achse drehen, anstatt es um seine eigenen relativen Achsen zu drehen . Oder liege ich falsch?
Da dieser Code, den ich verlinkt habe, anscheinend keine Ansammlung von Matrixtransformationen ist, können Sie bitte ein Beispiel für eine Lösung mit dieser Methode geben.
Also zusammenfassend:
- Was ist der Unterschied zwischen einer Drehung und einer Orientierung?
- Warum ist der Code in kein Beispiel für die Anhäufung von Matrixtransformationen eingebunden?
- Was ist der eigentliche, spezifische Zweck einer Matrix, wenn ich falsch lag?
- Wie könnte eine Lösung des Gimbal-Lock-Problems durch Akkumulation von Matrixtransformationen implementiert werden?
- Als Bonus: Warum sind die Transformationen nach der Rotation noch relativ zum "Modellraum"?
- Ein weiterer Bonus: Bin ich falsch in der Annahme, dass nach einer Transformation weitere Transformationen relativ zum Strom stattfinden werden?
Auch wenn es nicht impliziert wurde, verwende ich OpenGL, GLSL, C ++ und GLM, daher sind Beispiele und Erklärungen in Bezug auf diese sehr willkommen, falls dies nicht erforderlich ist.
Je mehr das Detail desto besser!
Danke im Voraus.
quelle
Matrixakkumulationen können in der Tat die Gimbal-Sperre lösen. Durch das Akkumulieren von Rotationen fügen Sie Kardanringe hinzu, die jede beliebige Rotation zulassen. Das von ktodisco bereitgestellte Diagramm zeigt eine Kardansperre im linken Diagramm. Die Matrix für diese Ausrichtung kann wie folgt definiert werden:
Aufgrund der Drehung des y-Kardans sind die X- und Z-Kardans jetzt gesperrt, sodass wir einen Bewegungsgrad verloren haben. Zu diesem Zeitpunkt haben wir kein Gieren (lokales y, globales z) unter Verwendung dieser drei Kardanringe. Durch Hinzufügen eines weiteren Kardanrahmens kann ich mich lokal um das y drehen:
Fügen Sie für jeden neuen Wurf, jede Neigung und jedes Gieren einen weiteren Kardanring hinzu, der sie in einer Matrix akkumuliert. Jedes Mal, wenn eine weitere lokale Drehung benötigt wird, wird eine Drehung erstellt und mit der Akkumulationsmatrix multipliziert. Wie im Kapitel erwähnt, gibt es immer noch Probleme, aber Gimbal Lock gehört nicht dazu.
quelle