# Reihenfolge von Matrixmultiplikationen



## h0b0 (20. Apr 2007)

Ich habe mir auf Basis des Codes von OrbitBehavior eine ähnliche Klasse nach meinen Bedürfnissen geschrieben. Um es mir erstmal einfach zu machen, habe ich die ganzen View-Transformationen nicht in eine TransformGroup gepackt, sondern mein SimpleUniverse mit mehreren (zum Schluss sieben) verketteten transformGroups  vor der ViewPlatform ausgestattet. Das funktionierte soweit gut.
Nun wollte ich das ganze wieder auf eine TransformGroup reduzieren, indem ich die entsprechenden Matrixoperationen von Hand ausführe. Ich habe den kompletten Vormittag gebraucht, um festzustellen, dass die Reihenfolge der Matrixmultiplikationen genau umgekehrt war, wie ich es vermutete. Es funktioniert jetzt; ich weiß nur nicht, warum.
Meine Erwartung wäre gewesen, dass die am weitesten rechts in der Multiplikationskette stehende Transformation als erste ausgeführt wird. Dies scheint nun aber genau anders herum zu sein. Wer kann mir dieses Phänomen erklären? Ist das am Ende eine Konsequenz daraus, dass ich den View und nicht die Welt bewege, die ich noch nicht erfasst habe?
Für klarheitstiftende Hinweise wäre ich dankbar.

P.S.: Noch eine Frage, die sich mir in diesem Zusammenhang stellt: Welche Aspekte sollte man eurer Meinung nach betrachten, wenn man erwägt, ob es günstiger ist, eine komplexe Transformation durch die Verkettung von TransformGroups oder manuell durchzuführen?


----------



## Gast (20. Apr 2007)

Bei spaltenorientieren Matrizen (wie z.B. bei OpenGL) ist es so, wie du sagst (die erste kommt zuletzt). Bei zeilenorientierten (DX, kontinentaleuropäische Schulmathematik) ist es anders herum, d.h. die letzte kommt auch zuletzt.


----------



## h0b0 (20. Apr 2007)

Mir wird nicht klar, was die lineare Anordnung der Elemente einer Matrix im Speicher mit der Multiplikationsreihenfolge zu tun hat.
Möglicherweise haben die Termini "zeilen-" und "spaltenorientiert" für dich eine andere Bedeutung als ich sie jetzt aufgefasst habe. Anders kann ich mir auch den Verweis auf die Schulmathematik nicht erklären; da hat man seine Matrizen im allgemeinen in einem zweidimensionalen Speicher aus Kästchenpapier;-)


----------



## Gast (21. Apr 2007)

Die Repräsentation im Speicher ist hier nicht wirklich relevant. Es geht mehr um die Art des Aufschreibens bzw. des Denkens. In der Schule sind die Matrizen "bei uns" üblicherweise zeilenorientiert, d.h. man betrachtet die Zeilenvektoren (d.h. eine 3x3-Matrix ist eine Matrix aus 3 Zeilenvektoren). Man kann aber auch genauso gut die Spalten als Vektoren betrachten. In dem Fall muss man die Matrix-Multiplikation (Zeilen*Spalte) in der anderen Reihenfolge durchführen, z.B. 

Zeilenorientiert:

```
0 0 2    1 0 0    0 0 4
0 0 0 * 0 1 0 = 0 0 0
1 0 0    0 0 2    1 0 0
```

Dasselbe spaltenorientiert:


```
1 0 0    0 0 1    0 0 1
0 1 0 * 0 0 0 = 0 0 0
0 0 2    2 0 0    4 0 0
```

Die Ergebnisvektoren sind jeweils: (0 0 4), (0 0 0) und (1 0 0). Würdest du letztere Operation zeilenorientiert (d.h. in anderer Reihenfolge) durchführen, wäre das Ergebnis 


```
0 0 1    1 0 0    0 0 2
0 0 0 * 0 1 0 = 0 0 0
2 0 0    0 0 2    2 0 0
```

und damit falsch. Gibt aber sicher Leute, die das besser erklären können als ich...


----------



## Gast (21. Apr 2007)

BTW: Auch OpenGL.org hat erkannt, das spaltenorientiert nicht so intuitiv ist...


> 9.005 Are OpenGL matrices column-major or row-major?
> 
> For programming purposes, OpenGL matrices are 16-value arrays with base vectors laid out contiguously in memory. The translation components occupy the 13th, 14th, and 15th elements of the 16-element matrix.
> 
> ...


----------



## h0b0 (26. Apr 2007)

Entschuldige, dass ich erst jetzt antworte; deine Ausführungen haben mich auf eine längere Reise durchs Web geschickt. Ich suchte nach der Quelle deines Zitats und war dann eine Weile beschäftigt, eine Haufen interessante Dinge zu lesen. Danke dafür.
Verstehe ich dich richtig, dass du einfach nur sagen willst, dass eine Vertex-Transformation wie folgt abläuft?

OpenGL: Ax (mit Spaltenvektor x)
Java 3D: x^1A^1 (mit Zeilenvektor x und transponierter Matrix A)

Das würde dann bedeuten, dass Java 3D tatsächlich mit der Transponierten meine verwendeten Matrix4d arbeiten würde.
Habe ich dich richtig verstanden? Und kannst du mir dazu eine Stelle in der Dokumentation nennen; ich bin bislang nicht fündig geworden.


----------



## Marco13 (26. Apr 2007)

Nur mal allgemein: Du mußt schon bedenken, dass (wenn ich micht nicht gerade aufgrund leichten Schlafmangels und so ziemlich irre) die Reihenfolge der Operationen für die View genau umgekehrt ist, wie die, für die Objekte?! Also, wenn du eine Matrix auf die View anwendest, dann hat das (wenn ich mich... nicht irre) genau den gleichen Effekt, wie wenn du die _invertierte_ Matrix auf das Objekt anwendest... In OpenGL gibt es ja auch die Modelview- und Perspective-Marizen, die dem entsprechen, und die werden am Ende irgendwie zusammenmultipliziert... Müßt ich mir jetzt aber auch erst nochmal genauer anlesen...


----------



## Guest (27. Apr 2007)

h0b0 hat gesagt.:
			
		

> OpenGL: Ax (mit Spaltenvektor x)
> Java 3D: x^1A^1 (mit Zeilenvektor x und transponierter Matrix A)
> 
> Das würde dann bedeuten, dass Java 3D tatsächlich mit der Transponierten meine verwendeten Matrix4d arbeiten würde.
> Habe ich dich richtig verstanden?


Ja genau. So war das gemeint. Das Zitat stammt von hier: www.opengl.org/resources/faq/technical/transformations.htm


----------



## Guest (27. Apr 2007)

Marco13 hat gesagt.:
			
		

> Nur mal allgemein: Du mußt schon bedenken, dass (wenn ich micht nicht gerade aufgrund leichten Schlafmangels und so ziemlich irre) die Reihenfolge der Operationen für die View genau umgekehrt ist, wie die, für die Objekte?! Also, wenn du eine Matrix auf die View anwendest, dann hat das (wenn ich mich... nicht irre) genau den gleichen Effekt, wie wenn du die _invertierte_ Matrix auf das Objekt anwendest... In OpenGL gibt es ja auch die Modelview- und Perspective-Marizen, die dem entsprechen, und die werden am Ende irgendwie zusammenmultipliziert... Müßt ich mir jetzt aber auch erst nochmal genauer anlesen...


Das stimmt zwar, hat aber mit der Fragestellung hier eigentlich nichts bzw. nur indirekt zu tun.


----------



## h0b0 (27. Apr 2007)

@Gast
Nachmal vielen Dank für deine Hilfe. Den Link hatte ich freilich schon gefunden. Vollkommen glücklich wäre ich, wenn ich das ganze noch in der Java 3D Hilfe so erklärt finden würde.

@Marco13
Um ganz genau zu sein: Die Reihenfolge der Operationen ist identisch; es ist die Richtung jeder einzelnen Operation, die sich jeweils umkehrt, wenn man die Inverse Bildet. Oder irre ich mich hier?


----------



## EgonOlsen (27. Apr 2007)

h0b0 hat gesagt.:
			
		

> @Gast
> Vollkommen glücklich wäre ich, wenn ich das ganze noch in der Java 3D Hilfe so erklärt finden würde.


Ich denke mal, das steht da nicht unbedingt drin. Steht in Mathebüchern ja meistens auch nicht explizit dabei. Jeder nimmt halt "seine" Form als einzig sinnige und logische an. jPCT muss diesen Spagat z.B. auch machen...es nutzt selber zeilenorientierte Matrizen, aber OpenGL nutzt nunmal spaltenorientiert, d.h. ich muss beim Hin- und Rückweg ab und an "drehen". Zusätzlich nutzt es noch ein anderes Koordinatensystem (quasi um 180° um X gedreht), was die Sache noch lustiger macht... :wink:

Meine persönliche Meinung zum Thema: Spaltenorientiert ist unlogisch und überflüssig.


----------

