Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

stef

Treue Seele

  • »stef« ist der Autor dieses Themas

Beiträge: 246

Wohnort: Kassel

Beruf: Softwareentwickler

  • Private Nachricht senden

1

09.02.2019, 14:55

Warum unterschiedliche Anwendungsreihenfolge von Transformationen bei OpenGL und DirectX ?

Hallo Forum

Folgende Ausgagslage:
Ein Model, welches um den Koordinatenursprung entwickelt wurde, soll erst gedreht aund dann räumlich verschoben werden.

Frage:
Warum muss ich unter DirectX erst drehen und dann verschieben und unter OpenGL umgedreht ?
"In C++ it's harder to shoot yourself in the foot, but when you do, you blow off your whole leg." — Bjarne Stroustrup.

Tobiking

1x Rätselkönig

  • Private Nachricht senden

2

09.02.2019, 15:22


Warum muss ich unter DirectX erst drehen und dann verschieben und unter OpenGL umgedreht ?

Das ist Abhängig davon in welcher Reihenfolge multipliziert wird. Soweit ich weiß macht DirectX Vektor * Matrix und OpenGL Matrix * Vektor. Da steckt auch noch mit drin ob die Matrix in Reihen- oder Spaltenform im Speicher liegt (siehe https://de.wikipedia.org/wiki/Matrizenmu…trix_mal_Vektor)

birdfreeyahoo

Alter Hase

Beiträge: 756

Wohnort: Schorndorf

Beruf: Junior Software Engineer

  • Private Nachricht senden

3

09.02.2019, 15:47

Entsprechend ist der Vektor in OpenGL auch ein Spaltenvektor und in DirectX ein Zeilenvektor.

stef

Treue Seele

  • »stef« ist der Autor dieses Themas

Beiträge: 246

Wohnort: Kassel

Beruf: Softwareentwickler

  • Private Nachricht senden

4

09.02.2019, 16:02

Der Vollständigkeit halber sei noch erwähnt das die Transformationen nicht nacheinander angewand werden sondern vorher in einer Transformationsmatrix M kombiniert werden.

Also für DirectX:
M = M_rot * M_trans;
V' = V * M;

Für OpenGL:
M = M_trans * M_rot;
V' = V * M;

Das ist Abhängig davon in welcher Reihenfolge multipliziert wird. Soweit ich weiß macht DirectX Vektor * Matrix und OpenGL Matrix * Vektor.

Gerade mal Nachgeschlagen ... in der DirectX als auch in der OpenGL Literatur wird der Vektor immer mit der Matrix multipliziert ... nicht umgedreht ?( :?:
"In C++ it's harder to shoot yourself in the foot, but when you do, you blow off your whole leg." — Bjarne Stroustrup.

stef

Treue Seele

  • »stef« ist der Autor dieses Themas

Beiträge: 246

Wohnort: Kassel

Beruf: Softwareentwickler

  • Private Nachricht senden

5

09.02.2019, 16:21

Da steckt auch noch mit drin ob die Matrix in Reihen- oder Spaltenform im Speicher liegt


Entsprechend ist der Vektor in OpenGL auch ein Spaltenvektor und in DirectX ein Zeilenvektor.


Bedeutet also (bezogen auf Matrizen) das eine DirectX Matrix der Transponierten einer OpenGL Matrix entspricht ?
"In C++ it's harder to shoot yourself in the foot, but when you do, you blow off your whole leg." — Bjarne Stroustrup.

birdfreeyahoo

Alter Hase

Beiträge: 756

Wohnort: Schorndorf

Beruf: Junior Software Engineer

  • Private Nachricht senden

6

09.02.2019, 17:22

Wenn ich das richtig verstanden habe ist es etwas komplizierter. Im Grunde ist eine Matrix ja eine Matrix. Wie sie intern dargestellt wird (row/column major) hat keinen Einfluss auf ihre Bedeutung. Jetzt ist es so, dass ein Vektor auch eine Matrix ist, da gibt es aber 2 Möglichkeiten: 1x4 und 4x1, also Zeilenvektor und Spaltenvektor.
Bei einem Spaltenvektor musst du Matrix * Vektor machen und bei einem Zeilenvektor entsprechend umgekehrt. Das ist mathematisch notwendig, da nur diese Operationen definiert sind. Eine 4x4-Matrix mit einer 1x4-Matrix zu multiplizieren ist nicht erlaubt, da die Anzahl der Spalten des ersten Operanden der Anzahl der Zeilen des zweiten Operators entsprechen müssen.

Nun ist es aber so, dass diese Operationen aber nicht den gleichen Effekt haben. Das bedeutet wenn du denselben Vektor mit einer Matrix multiplizierst und zwar einmal als Spalten- und einmal als Zeilenvektor erhältst du nicht dasselbe Ergebnis. Du musst dafür mit der transponierten Matrix multiplizieren. Immerhin ist der Spaltenvektor auch ein transponierter Zeilenvektor. Das ganze lässt sich hübsch durch das mathematische Gesetz darstellen:

§§ (Mv)^{T} = v^{T}M^{T} \\ §§

Multiplizierst du eine Matrix M also mit einem Spaltenvektor erhältst du einen Spaltenvektor. Multiplizierst du nun den Zeilenvektor mit der transponierten Matrix erhältst du den entsprechenden Zeilenvektor.
Wie du bereits sagtest ist es ja so, dass die Matrix in diesem Fall zusammengesetzt ist und du brauchst jetzt in jedem Fall eine andere Matrix. Welche Auswirkung hat das transponieren auf eine zusammengesetzte Matrix?

§§ M = TRS \\ M^{T} = S^{T}R^{T}T^{T} §§

Die Reihenfolge der einzelnen Faktormatrizen wird also vertauscht und diese transponiert. Was bedeutet das jetzt? Nun so wie ich es kenne verwendest du in DirectX Zeilenvektoren und in OpenGL Spaltenvektoren und eine entsprechende Multiplikationsreihenfolge (Vektor-Matrix vs. Matrix-Vektor). Entsprechend brauchst du also unterschiedliche Matrizen um dasselbe Ergebnis zu erhalten (nicht exakt dasselbe, bei dem einen ist der transformierte Vektor dann ja ein Zeilenvektor bei dem anderen ein Spaltenvektor). Die einzelnen Matrizen (Scale, Rotation, Transform etc.) sind also transponiert und ihre Multiplikationsreihenfolge umgekehrt wenn du DirectX und OpenGL vergleichst.

Trotzdem bleibt eine Matrix immer dieselbe, du brauchst nur andere Matrizen wenn du eine andere Operation durchführst. Es ist auch möglich in DirectX z.B. Spaltenvektoren zu verwenden wenn du sie einfach als float4x1 definierst und damit dann die "OpenGL-Reihenfolge" zu verwenden. Das Ergebnis sollte aber trotzdem in einen Zeilenvektor transponiert werden, der in einen float4 passt, damit du das richtig in die Pipeline bekommst (zumindest die Clip-Space-Position) (?).

stef

Treue Seele

  • »stef« ist der Autor dieses Themas

Beiträge: 246

Wohnort: Kassel

Beruf: Softwareentwickler

  • Private Nachricht senden

7

09.02.2019, 17:45

@Birdfreeyahoo: Super Antwort :thumbsup: .. vielen Dank für die viele Arbeit
"In C++ it's harder to shoot yourself in the foot, but when you do, you blow off your whole leg." — Bjarne Stroustrup.

Jonathan

Community-Fossil

  • Private Nachricht senden

8

13.02.2019, 14:35

Bei einem Spaltenvektor musst du Matrix * Vektor machen und bei einem Zeilenvektor entsprechend umgekehrt. Das ist mathematisch notwendig, da nur diese Operationen definiert sind.


Schön ist es auch, Vektoren einfach als Matrizen mit nur einer Spalte, bzw. einer Zeile aufzufassen. Dann multipliziert man in allen Fällen immer nur Matrizen miteinander und es gelten die allgemeinen Regeln für A*B=C:

- A muss so viele Spalten haben wie B Zeilen hat.
- Das Ergebnis C hat so viele Zeilen wie A und so viele Spalten wie B.

Daraus folgt direkt, dass wenn man einen 4D Vektor mit einer 4x4 Matrix multiplizieren will, der Vektor links von der Matrix steht, wenn es ein Zeilenvektor ist und rechts, wenn es ein Spaltenvektor ist.

Es folgt auch, dass im allgemeinen A*B nicht gleich B*A sein kann, weil die Größen nicht in beiden Fällen kompatibel sein müssen.

Es folgt weiterhin unmittelbar das Skalarprodukt (bzw. Punktprodukt, bzw. inneres Produkt) zweier Vektoren, wenn man den ersten als Zeilenvektor und den zweiten als Spaltenvektor auffasst. Alles immer nur Matrizenmultiplikation.

Details und schöne Bilder auf:

https://de.wikipedia.org/wiki/Matrizenmu…ezialf%C3%A4lle

Einfach einmal aufmalen, das ganze ist eigentlich sehr anschaulich.
Lieber dumm fragen, als dumm bleiben!

Werbeanzeige

Ähnliche Themen