Hallo zusammen.
Wie manche vielleicht wissen habe ich eine Vektoren- und Matrizenbibliothek namens MathUtils geschrieben, die funktioniert auch generell ganz einwandfrei.
Allerdings ist mir gerade ein seltsames Verhalten aufgefallen. Ich wollte ein Polygon mithilfe einer Matrix um seinen Mittelpunkt rotieren. Dafür muss man das Polygon ja erstmal so verschieben, dass der Mittelpunkt im Koordinatenursprung (also in 0,0) liegt, dann kann man rotieren und am Ende verschiebt man das Polygon wieder zurück in seine alte Position. Dies sollte eigentlich kein Problem sein, indem man erst eine Translationsmatrix erstellt, dann eine Rotationsmatirix damit multipliziert und dann die inverse der Translationsmatrix ebenfalls wieder damit multipliziert. Raus kommt dann eine Matrix, die das alles in einem Mal erledigt. So weit so gut mit der Theorie, aber in der Praxis funktioniert das nicht ganz so wie gedacht. Nachdem ich längere zeit falsche Ergebnisse erhalten habe und vergeblich versuchte habe, den Fehler zu finden, stellte sich heraus, dass die Reihenfolge der Matrizen im Programm genau umgekehrt sein muss. Also Die erste Matrix aus der Multiplikationskette muss im Programm die letzte sein usw. Jetzt frage ich mich halt, ob das so normal ist, oder ob ich bei meinen Implementierungen die Matrizen vertauscht habe.
Zur Demonstration, so dachte ich müsste es aussehen:
aber so muss es tatsächlich aussehen:
Ich hab hier statt der Inversen einfach eine neue Translationsmatrix mit den negativen Werten benutzt, da dies weniger Rechenintensiv ist.
Zur Kontrolle, dass das nicht etwa ein Vorzeichenfehler oder ähnliches ist, habe ich mal nur eine einzelne Translationsmatrix erstellt und diese angewendet, da war das Ergebnis wie erwartet.
Also, woran liegt es, dass die Matrizen von rechts nach links ausgewertet werden, statt von links nach rechts?
Ps:
Die Funktion zum Multiplizieren sieht übrigens so aus:
Spoiler anzeigen
Der *-Operator ruft dann einfach diese Funktion auf.
Wie manche vielleicht wissen habe ich eine Vektoren- und Matrizenbibliothek namens MathUtils geschrieben, die funktioniert auch generell ganz einwandfrei.
Allerdings ist mir gerade ein seltsames Verhalten aufgefallen. Ich wollte ein Polygon mithilfe einer Matrix um seinen Mittelpunkt rotieren. Dafür muss man das Polygon ja erstmal so verschieben, dass der Mittelpunkt im Koordinatenursprung (also in 0,0) liegt, dann kann man rotieren und am Ende verschiebt man das Polygon wieder zurück in seine alte Position. Dies sollte eigentlich kein Problem sein, indem man erst eine Translationsmatrix erstellt, dann eine Rotationsmatirix damit multipliziert und dann die inverse der Translationsmatrix ebenfalls wieder damit multipliziert. Raus kommt dann eine Matrix, die das alles in einem Mal erledigt. So weit so gut mit der Theorie, aber in der Praxis funktioniert das nicht ganz so wie gedacht. Nachdem ich längere zeit falsche Ergebnisse erhalten habe und vergeblich versuchte habe, den Fehler zu finden, stellte sich heraus, dass die Reihenfolge der Matrizen im Programm genau umgekehrt sein muss. Also Die erste Matrix aus der Multiplikationskette muss im Programm die letzte sein usw. Jetzt frage ich mich halt, ob das so normal ist, oder ob ich bei meinen Implementierungen die Matrizen vertauscht habe.
Zur Demonstration, so dachte ich müsste es aussehen:
aber so muss es tatsächlich aussehen:
Ich hab hier statt der Inversen einfach eine neue Translationsmatrix mit den negativen Werten benutzt, da dies weniger Rechenintensiv ist.
Zur Kontrolle, dass das nicht etwa ein Vorzeichenfehler oder ähnliches ist, habe ich mal nur eine einzelne Translationsmatrix erstellt und diese angewendet, da war das Ergebnis wie erwartet.
Also, woran liegt es, dass die Matrizen von rechts nach links ausgewertet werden, statt von links nach rechts?
Ps:
Die Funktion zum Multiplizieren sieht übrigens so aus:
C-Quellcode
- public static Matrix Multiply(Matrix left, Matrix right)
- {
- if (left.ColumnCount == right.RowCount)
- {
- var m = new Matrix(right.ColumnCount, left.RowCount); //Matrix mit richtigen Abmessungen erstellen
- for (int x = 0; x < m.ColumnCount; x++)
- for (int y = 0; y < m.RowCount; y++)
- {
- var value = 0.0;
- for (int i = 0; i < left.ColumnCount; i++)
- value += left[i, y] * right[x, i]; //Wert für diese Position berechnen
- m[x, y] = value; //Wert zuweisen
- }
- return m;
- }
- else //Matrizen sind nicht kompatibel
- throw new ArgumentException("Diese Matrizen können nicht miteinander multipliziert werden.");
- }