[Qt]"eyePos" aus ViewMatrix ermitteln

Design Patterns, Erklärungen zu Algorithmen, Optimierung, Softwarearchitektur
Forumsregeln
Wenn das Problem mit einer Programmiersprache direkt zusammenhängt, bitte HIER posten.
Antworten
joggel

[Qt]"eyePos" aus ViewMatrix ermitteln

Beitrag von joggel »

Hallo,

ich habe eine eher mathematische Frage, weil mich die mathematische Lösung dieses Problem interessiert. In der Implementation gehe ich einen anderen weg: ich speicher mir immer den eyeVector ab, und lasse ihn mir bei Bedarf zurück geben.

Es gibt diese Qt-Funktion: QMatrix4x4::lookAt(const QVector3D& eye, const QVector3D& center, const QVector3D& up)

Wie bekomme ich aus einer beliebigen QMatrix4x4 die eye-Position? Ich denke mal, es ist ein eher simpler mathematischer Weg, aber ich komme nicht recht darauf.

Weiß jemand wie ich dabei vorzugehen habe?

Gruß

[Edit]
Es ist leider nicht so einfach, dass der TranslationsVektor in der 4.-Spalte zu finden ist.
Ich habe so das Gefühl, dass ich den Eye-Vektor nicht mehr rekonstruieren kann. Dieses LookAt ist ja eigentlich eine Rotation + Translation.
Trotzdem wundert mich das, dass der EyeVec nicht in der 4. Spalte zu finden ist

Wie man hier sieht (Zeile 1010) scheint das keine "einfache" translation zu sein...
Zuletzt geändert von joggel am 12.08.2020, 21:21, insgesamt 1-mal geändert.
Benutzeravatar
Krishty
Establishment
Beiträge: 8229
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: "eyeVec" aus ViewMatrix ermitteln

Beitrag von Krishty »

Meinst du mit eyeVector die Richtung, in die das Auge schaut? Oder die Position des Auges?
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
joggel

Re: "eyeVec" aus ViewMatrix ermitteln

Beitrag von joggel »

Noch eine Frage: schaut euch mal bitte den Inhalt der Matrix an. Können die Werte denn stimmen?
QMatrix4x4.png
[Edit]
Sorry, hab zu schnell gepostet. Ich meine die Position des Auges/Kamera
Benutzeravatar
Krishty
Establishment
Beiträge: 8229
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: "eyeVec" aus ViewMatrix ermitteln

Beitrag von Krishty »

Ach verdammt: Ist EyeVec gar nicht die Position?^^ Sonder die Richtung?! :D
Keine Ahnung; ich spreche nur von der „Position des Betrachters“ und „seinen lokalen Achsen“. KA, wie Qt das jeweils nennt :)

Hmmm habe gerade auch keine fertige Funktion für die Position herumliegen.

Die ersten drei Zeilen (falls row-major) oder ersten drei Spalten (falls column-major) stellen die lokalen Achsen des Betrachters dar. Die Länge der Achsen entspricht der inversen Skalierung (also 0.5, falls von der Matrix alles aufs doppelte Skaliert wird). Die vierte Spalte/Zeile repräsentiert die negierte Verschiebung.

Im Idealfall solltest du also einfach die vierte Spalte/Zeile auslesen können und hättest darin die *negierte* Kameraposition. (Denn die Matrix muss die Welt ja so verschieben, dass die Kameraposition am Koordinatenursprung landet.)
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
joggel

Re: "eyeVec" aus ViewMatrix ermitteln

Beitrag von joggel »

Genau das dachte ich ja auch. Aber wenn ich mir die Werte der Matrix anschaue, dann stimmt das einfach nicht.

Ich habe noch mal in die Doku geschaut, und ich hatte das schon richtig gemacht. Also der erste wert eye ist die Kameraposition.
joeydee
Establishment
Beiträge: 1039
Registriert: 23.04.2003, 15:29
Kontaktdaten:

Re: [Qt]"eyePos" aus ViewMatrix ermitteln

Beitrag von joeydee »

Wie bekomme ich aus einer beliebigen QMatrix4x4 die eye-Position?
Ich ersetze mal "beliebig" durch "Abbildungsmatrix" ("Space") und "eye-Position" durch Position. Und gehe davon aus, dass die genannte Funktion die Orientierung eines "Spaces" so drehen soll, dass seine Z-Achse die Zielposition anvisiert. Dann kann man aus dem Ergebnis die Position auslesen.
Kommt aber auf die Engine an, was sie unter der Funktion wirklich versteht.
Denkbar wäre z.B. dass LookAt ausschließlich für "Kameraobjekte" gedacht ist, und dass da gleich die Projektionsmatrix mit reingewurschtelt wird um das Ergebnis ready-to-use zum Rendern zu machen.
Ebenso denkbar: Dass "Eye Matrix" gar nicht die Welt-Kamera-Matrix sondern die Inverse ist. Hieße dann korrekterweise eigentlich "View Matrix" und wird in der MVP-Gleichung (Model * View * Projection) benötigt.
Auch denkbar: verbuggt. Hatte ich auch schon bei irgendeiner Matrix-Lib, bzw. es war ums verrecken nicht herauszubekommen was die Funktion eigentlich wirklich tun will. Plan B: selbercoden.
weil mich die mathematische Lösung dieses Problem interessiert
Dann erstmal zum Normalfall.
Für die o.g. Neudefinition von "beliebig" stimmt das bereits im Thread Gesagte, denn im Detail passiert Folgendes: Wird ein Vektor (0,0,0,1) mit einer 4x4-Matrix transformiert, kommt ja ein Vektor (x,y,z,1) heraus, welcher an die "Nullposition" dieser Matrix, also in diesen Modelspace, transformiert wurde.
Wobei x,y,z in diesem Sonderfall direkt den ersten 3 Einträgen der letzten Spalte entsprechen (Spaltennotation s.u.), da laut Vektor ja bei der Transformation jeweils 0 mal die Werte aus den ersten 3 und 1 mal die der letzten Spalte addiert wurden, d.h. nur die letzte Spalte mit einem Faktor von 1 berücksichtigt wird.
Deshalb reicht es, diese Werte direkt ausuzulesen, anstatt die Transformation komplett durchzuführen.

Typisch für die oben genannte Art der der Abbildungsmatrizen (also "Spaces") ist immer:
- Die ersten 3 Spalten sind die lokalen Richtungsvektoren und spannen den lokalen Raum auf (daher der Begriff "Space").
- Sie haben üblicherweise (d.h. ohne vorher angewendete Skalierung) die Länge 1, also z.B. sqrt(m11*m11+m21*m21+m31*m31)==1.
- Sie sind üblicherweise (d.h. ohne vorher angewendete Verzerrung) senkrecht zueinander.
- Ohne Rotation steht in der ersten Spalte 1/0/0, in der zweiten 0/1/0 und in der dritten 0/0/1 (X-, Y- Z-Achse)
- Die letzte Spalte ist die Position. Ohne Transformation steht hier 0/0/0.
- m14, m24, m34 sind immer 0.
- m44 ist immer 1.

Dem Dump nach scheint bei QT die richtige Notation also zu sein:
m11 m12 m13 m14
m21 m22 m23 m24
m31 m32 m33 m34
m41 m42 m43 m44

interpretiert:
x1 y1 z1 px
x2 y2 z2 py
x3 y3 z3 pz
0 0 0 1

Die Position einer beliebigen 4x4-Matrix, die einen gültigen "Space" repräsentiert, wäre demnach (m14, m24, m34). Antwort auf die Eingangsfrage.

Wenn nach einer bestimmten Funktion nichts Brauchbares herauskommt, erstellt die Funktion evtl. gar keinen allgemeingültigen Space (mögl. Gründe s.o.), dann mach besser deine eigene.


Edit: Ergänzung:
Multiplies this matrix by a viewing matrix derived from an eye point.
Autsch. Mit "A viewing matrix" ist evtl. eine invertierte gemeint? Und "Multiplies this matrix by" würde dann sowas wie der MV-Teil in der MVP-Gleichung ergeben? Liest sich für mich so, dass die Ausgangsmatrix (also die aufrufende) gar nicht die Kamera sein darf, sondern eine Modelmatrix, zu welcher dann eine Viewmatrix "onTheFly" berechnet und gleich reinmultipliziert wird? Falls das stimmt: Alter, wer braucht denn sowas?
Hab mich schon gewundert warum man EyePos als Parameter braucht, die Kameramatrix hätte doch schon eine Position.
Teste evtl mal mit ner Identity-Matrix als Aufrufer, ob es dann mehr Sinn macht. Vielleicht steht dann die EyePos direkt oder negativ an besagter Stelle.
joggel

Re: [Qt]"eyePos" aus ViewMatrix ermitteln

Beitrag von joggel »

Erst mal danke für die Erklärung.

"Beliebige Matrix" ist ja hier etwas fehl am Platz; stimmt schon.
Plan B: selbercoden.
Ja, das dachte ich mir auch schon. Macht ja nicht sooo viel aufwand.
Teste evtl mal mit ner Identity-Matrix als Aufrufer, ob es dann mehr Sinn macht. Vielleicht steht dann die EyePos direkt oder negativ an besagter Stelle.
QMatrix4x4.png
Also für mich macht das alles irgendendwie immer weniger Sinn, was nach nem lookAt die Matrix enthält bzw verstehe ich es nicht...
joeydee
Establishment
Beiträge: 1039
Registriert: 23.04.2003, 15:29
Kontaktdaten:

Re: [Qt]"eyePos" aus ViewMatrix ermitteln

Beitrag von joeydee »

"Richtig" im Sinne einer brauchbaren Space-Matrix wäre bei deinen Parametern ja x=(-1,0,0,0), y=(0,1,0,0), z=(0,0,-1,0), pos=(0,0,-1,1) D.h. sie säße an der übergebenen Position (0,0,-1), und sie würde nach "hinten" schauen, d.h. die Koordinate (0,0,-1000) wäre anvisiert.
Hm, dein Ergebnis ist zumindest "ähnlich", wenn auch einige Werte negiert.

Die letzten beiden Zeilen im QT-Code this*=m und translate -eye machen das für allgemeine Verwendung irgendwie kaputt, da wird ja die alte Ausrichtung auch nochmal reingerechnet wenns keine Identity war.
Hatte die Funktion bei dir denn schonmal wie erwartet funktioniert, d.h. war beim Rendern das im Blick was du anvisiert hattest?

Ach ja, damit man nicht immer um 5 Ecken denken muss:
Benenne in deinem Beispiel die Variablen besser mal so wie die Parameter und deklariere sie auch in derselben Reihenfolge, "LookAt" wird bei dir zu "eye" und "Pos" zu "center", das ist verwirrend, und im ersten Beispiel war es irgendwie umgekehrt.
Und für eine brauchbare Debug-Ausgabe, mach dir am besten mal Hilfsfunktionen welche dir die Spaltenvektoren zurückgeben im Stil von "getXAxisFromMatrix(m) return v3d(m11, m21, m31, m41)" jeweils für x, y, z und pos. Damit man da nicht mehr die Werte einzeln zusammenklauben muss. Führt sonst alles nur zu Verwechslungsfehlern beim Debuggen.
joggel

Re: [Qt]"eyePos" aus ViewMatrix ermitteln

Beitrag von joggel »

Kurzes Update:
Die ViewMatrix (Kamera) macht tatsächlich was sie soll. Also ich spielte etwas mit den Parametern herum und es kommen sinnvolle Renderergebnisse dabei heraus.

Ach und ich hatte in meinem letzten Post die Position (position der Kamera) mit Center (Position auf die geschaut wird) vertauscht; wie du bemerktes.

Mir scheint es so, dass die Achsen zum Center hin ausgerichtet sind und dann irgendwie verschoben. Also erst eine rotation dann die translation... aber wie verstehe ich eben nicht genau.

Hier noch mal ein Dump von der CameraMatrix:
QMatrix4x4.png
joeydee
Establishment
Beiträge: 1039
Registriert: 23.04.2003, 15:29
Kontaktdaten:

Re: [Qt]"eyePos" aus ViewMatrix ermitteln

Beitrag von joeydee »

Ok, die Werte sehen richtig aus. Es ist wie vermutet eine View-Matrix, keine Space-Matrix.

Eine View-Matrix sagt ja über eine Space-Matrix: "Wenn dieser Space mit seiner Position und seinen Achsen die Welt wäre, wohin müsste ich alles andere drehen/verschieben, damit dasselbe Bild entsteht?". Was leider nicht intuitiv ist, was die auszulesenden Werte angeht.
Da bei deinem Beispiel alles auf der Y/Z-Ebene geblieben ist lässt sich die Richtigkeit aber grob überschlagen (nur Beträge ohne Vorzeichen und Kommawerte grob gerundet betrachtet, also die = Zeichen hier jetzt nicht überbewerten ;)):
- Wenn ich an Position 2/-5 bin und schaue Richtung 0, dann liegt der Nullpunkt genau auf meiner Z-Achse, und zwar sqrt(2*2+5*5) von mir entfernt, als Vektor ausgedrückt (0,0,5.385). Passt.
- Die Kamera ist bei diesem Vorgang nicht gerollt und blieb auf der Y/Z-Ebene, d.h. die X-Achse müsste parallel zur Alten sein (1,0,0). Passt.
- Y- und Z-Achse müssten mit der Steigung 2 zu 5 (bzw. umgekehrt) geneigt sein. 0.928/0.371=2.5 Passt.
- Der X-Betrag beider Achsen müsste 0 bleiben (da nicht aus der Y/Z-Ebene herausbewegt), d.h. die Werte dürften wechselseitig nur in den y- und z-Komponenten zu finden sein nach dem Schema (0,a,b) und (0,b,-a) (vgl. auch die Werteverteilung einer reinen Rotationsmatrix, oder die Bildung einer Senkrechten eines 2D-Vektors). Passt.
- Alle Achsen haben die Länge 1. X Passt sowieso, Y und Z: sqrt(0.928^2+0.371^2)=1 Passt auch.

Generiere mal die Inverse, und lies davon die Position aus. Das müsste dann dein reingesteckter Vektor sein, also die tatsächliche Welt-Kameraposdition.
Da die Inversenberechnung Aufwand ist, bleib natürlich bei deiner Lösung den Positionsvektor zu speichern.

In meiner Pipeline sind sämtliche Bewegungsfunktionen ausschließlich für Space-Matrizen ausgelegt, kein Modelview-Mix wie hier, und die Kamera ist selbst Space-Matrix (keine View, keine Projection). D.h. es ist egal ob ich etwas auf Kamera oder Modell anwende. Damit kann ich auch jederzeit jede Modellmatrix als Kamera nutzen und überall direkt Achsen und Positionen auslesen.
View-Matrizen (jeweils die Inverse einer Space-Matrix, sprich "Die Welt aus Sicht dieses Spaces") werden erst bei Bedarf generiert, also am Ende der Pipeline wenn die Kamera dem Shader übergeben wird, oder für KI aus Modellsicht.
Seit ich das konsequent so mache ist die Matrix-Welt ein klein wenig intuitiver geworden.
joggel

[gelöst]Re: [Qt]"eyePos" aus ViewMatrix ermitteln

Beitrag von joggel »

Okay, danke dir (erstmal^^)!

Und stimmt: Einfach die Kamera-(View-)Matrix invertieren, und man bekommt die KameraPosition ("eyePos") :)
Antworten