OpenGL Kamera Problem
-
Nur kurz überflogen weil ich jetzt in die Falle muss
cooky451 schrieb:
mat4 rotation (vec4(right_[0], up_[0], forward_[0], 0.f), vec4(right_[1], up_[1], forward_[1], 0.f), vec4(right_[2], up_[2], forward_[2], 0.f), vec4(0.f, 0.f, 0.f, 1.f)); glUniformMatrix4fv(shader_cam_rotation_, 1, GL_FALSE, rotation[0]);
Versuche mal aus dieser Umrechnung deine MV-Matrix zu erstellen, statt right, up und forward direkt zu verwenden:
http://wiki.delphigl.com/index.php/gluLookAt
-
Hm.. also damit bekomme ich sehr eigenartige Effekte.
template<typename T> inline BlockMatrix4<T> lookAt(GeometricVector3<T> const& eye, GeometricVector3<T> const& lookat, GeometricVector3<T> up) { vec3 forward = lookat - eye; forward.normalize(); up.normalize(); vec3 side = cross(forward, up); side.normalize(); up = cross(side, forward); // up.normalize(); ? BlockMatrix4<T> mat (GeometricVector4<T>(side[0], side[1], side[2], 0.0), GeometricVector4<T>(up[0], up[1], up[2], 0.0), GeometricVector4<T>(forward[0], forward[1], forward[2], 0.0), GeometricVector4<T>(0.f, 0.f, 0.f, 1.0)); return mat; }
-
Das:
mat4 translate(vec3 v) { return mat4(vec4(1.0, 0.0, 0.0, 0.0), vec4(0.0, 1.0, 0.0, 0.0), vec4(0.0, 0.0, 1.0, 0.0), vec4(v.x, v.y, v.z, 1.0)); }
ist keine Translation wenn du von Rechts multiplizierst, sondern eine verzerrung entlang der w-koordinate. transponier das.
Ich war also mit meinem ersten Kommatar ganz nah ran:
So einen Effekt kannst du aber kriegen, wenn du row major/column major in der Projektionsmatrix vertauschst.
-
otze schrieb:
ist keine Translation wenn du von Rechts multiplizierst, sondern eine verzerrung entlang der w-koordinate. transponier das.
OpenGL erwartet diese Anordnung. Ist leider alles etwas nervig, weil man bei jeder Matrix aufpassen muss, welcher Ordnung die jetzt folgt. Wie gesagt, ist diese Matrix aber korrekt, falls du allerdings im restlichen Code eine nicht dazu passende Matrix findest, zeig sie gerne auf.
(Zeile 29 - 33 passen natürlich nicht dazu, deshalb hatte es mich anfänglich ja auch so gewundert, dass das so auf einmal "funktioniert". Da muss also irgendwie vorher ein Haken sein, ich komme nur nicht drauf. Muss jetzt leider kurz ~2 Stunden weg.)
-
Den Effekt hatte ich auch mal. Der ist auch logisch, wenn man sich überlegt, dass man beim Rotieren um die x-Achse die lokalte Y-Koordinate der Kamera nach vorne kippt. Sobald man dann um die y-Achse rotiert, wird die Kamera dann schief und dreht sich relativ gesehen zur globalen z-Achse.
Was man machen muss ist, dass man nicht um die lokale y-Achse der Kamera rotiert, sondern um die globale. D.h. man muss erst die globale y-Achse (0, 1, 0) in das lokalte Koordinatensystem der Kamera transformieren (Kamera-Matrix * (0, 1, 0)), dann aus dieser Matrix die die "Position" herausfiltern (also die ersten 3 Elemente der letzten Spalte), welche dann die Achse darstellen, um die man dann die Kamera rotieren muss.
-
Powerpaule schrieb:
D.h. man muss erst die globale y-Achse (0, 1, 0) in das lokalte Koordinatensystem der Kamera transformieren (Kamera-Matrix * (0, 1, 0)), dann aus dieser Matrix die die "Position" herausfiltern (also die ersten 3 Elemente der letzten Spalte), welche dann die Achse darstellen, um die man dann die Kamera rotieren muss.
Würde ich ja gerne testen, aber Matrix * Vektor gibt bei mir am Ende wieder einen Vektor. Was soll ich da rausfiltern? (Ich habe es natürlich auch mal mit dem Vektor als Rotationachse getestet, aber das funktioniert leider auch nicht so richtig.)
Edit:
Zumal logischerweise auch nichts an der Position geändert wird. So funktioniert es einigermaßen:void rotateY(f32 angle) { mat4 mat = vec4(0.f, 1.f, 0.f, 0.f) * rotation_; vec3 rot(mat[1][0], mat[1][1], mat[1][2]); rot.normalize(); rotation_ *= lin::rotate(rot, angle); }
Das alte Problem wird dadurch aber nicht gelöst, immer noch dasselbe Verhalten. Das mit dem "reinrotieren" war übrigens auch meine Ursprungsidee, aber irgendwas hat da nicht gestimmt..
-
cooky451 schrieb:
Powerpaule schrieb:
D.h. man muss erst die globale y-Achse (0, 1, 0) in das lokalte Koordinatensystem der Kamera transformieren (Kamera-Matrix * (0, 1, 0)), dann aus dieser Matrix die die "Position" herausfiltern (also die ersten 3 Elemente der letzten Spalte), welche dann die Achse darstellen, um die man dann die Kamera rotieren muss.
Würde ich ja gerne testen, aber Matrix * Vektor gibt bei mir am Ende wieder einen Vektor. Was soll ich da rausfiltern? (Ich habe es natürlich auch mal mit dem Vektor als Rotationachse getestet, aber das funktioniert leider auch nicht so richtig.)
Wenns bei dir schon einen Vektor ergibt, müsste das dann eigentlich der Vektor sein um den du rotieren musst... bei mir kommt da halt nur eine Matrix raus, da muss man halt den zusätzlichen schritt noch einbauen^^ Ansonsten müsste das eigentlich genau die Lösung sein, denn bei mir war das Problem genau das gleiche, und wenn man es sich wie beschrieben durchspielt (also gekippte y-Achse bei Rotation um x-Achse), dann sieht man ja doch ganz gut dass man da dann um die falsche Achse rotiert.
-
Powerpaule schrieb:
Wenns bei dir schon einen Vektor ergibt,
Also soweit ich informiert bin sollte das immer einen Vektor ergeben. Oder gibt es da irgendwie mathematische Ausnahmefälle?
Powerpaule schrieb:
müsste das dann eigentlich der Vektor sein um den du rotieren musst...
Habe ich wie gesagt schon getestet, das "funktioniert" dann genau so, als würde ich um die normalen (lokalen) Achsen rotieren.
Powerpaule schrieb:
bei mir kommt da halt nur eine Matrix raus,
Macht mich etwas stutzig.. hast du das selbst geschrieben oder nutzt du eine Mathe-lib?
Powerpaule schrieb:
(also gekippte y-Achse bei Rotation um x-Achse), dann sieht man ja doch ganz gut dass man da dann um die falsche Achse rotiert.
Hast du dir die Videos aus dem Einangspost angesehen? Ich habe irgendwie das Gefühl, dass du von einem anderen Problem sprichst. Es geht darum, dass bei den Rotationen links, oben, rechts, unten, eine Rotation um die Z-Achse stattfindet, die gar nicht da sein sollte. (Bzw. sich genau aufheben sollte.)
-
Folgender Vorschlag:
- Breche das Projekt mal auf ein Minimum herunter. Alles was nicht benötigt wird, sollte rausfliegen.
- Eliminiere jeden Shader-Code und programmiere rein klassisch
- Implementiere die Kamera 1:1 wie in dem Code von mir
- Wenn es dann immer noch nicht funktioniert lade das Projekt (kompilierbar in Visual Studio 2008, ohne Shader, ohne sonstigen problemfremden Code, nur das isolierte Problem mit minimaler Szene!) irgendwo hoch, ich würde es mir dann ansehen und den Fehler suchen. Mit etwas Gedult, bestimmt auch finden. Bin sehr hartnäckig was Rätsel betrifft
-
Vielen Dank für das Angebot, ich hätte es auch fast angenommen.
Die Lösung ist eigentlich ganz einfach, und irgendwie auch erschreckend logisch.
Ein Vektor (hier der up-Vektor) muss konstant bleiben. Diese Drehen muss immer gleich bleiben. Die anderen Beiden Vektoren müssen sich aber mitdrehen. Manchmal hilft nachdenken halt doch mehr als stumpfes Testen, ich hatte natürlich immer nur alle Vektoren global oder alle lokal gehalten.
(Bei einer Rotation um die Z-Achse muss man den "up"-Vektor natürlich ändern.)
Edit:
Na, das mit dem up-Vektor ändern klappt leider noch nicht so. Aber da bin ich auf dem richtigen Weg, leider muss ich jetzt erst mal eine Woche weg.Eine kleine Frage hätte ich aber noch: Ich nutze jetzt Quaternionen, welche ja angeblich recht performant sein sollen. Aber wenn ich die jetzt um eine eigene Achsen rotiere, muss ich ja erst eine Matrix aus dem Quaternion erstellen, dann die globale Achse über diese Matrix in das lokale Koordinatensystem drehen, nur um nachher wieder ein Quaternion um diese Achse zu erstellen. Das muss doch schneller möglich sein?