Matrizenmultiplikation falsch?

  • Allgemein

Es gibt 11 Antworten in diesem Thema. Der letzte Beitrag () ist von jvbsl.

    Matrizenmultiplikation falsch?

    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:

    C-Quellcode

    1. Matrix3x3.Translation(-obj2.Center) * Matrix3x3.Rotation(Math.PI) * Matrix3x3.Translation(obj2.Center);

    aber so muss es tatsächlich aussehen:

    C-Quellcode

    1. Matrix3x3.Translation(obj2.Center) * Matrix3x3.Rotation(Math.PI) * Matrix3x3.Translation(-obj2.Center);

    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

    C-Quellcode

    1. public static Matrix Multiply(Matrix left, Matrix right)
    2. {
    3. if (left.ColumnCount == right.RowCount)
    4. {
    5. var m = new Matrix(right.ColumnCount, left.RowCount); //Matrix mit richtigen Abmessungen erstellen
    6. for (int x = 0; x < m.ColumnCount; x++)
    7. for (int y = 0; y < m.RowCount; y++)
    8. {
    9. var value = 0.0;
    10. for (int i = 0; i < left.ColumnCount; i++)
    11. value += left[i, y] * right[x, i]; //Wert für diese Position berechnen
    12. m[x, y] = value; //Wert zuweisen
    13. }
    14. return m;
    15. }
    16. else //Matrizen sind nicht kompatibel
    17. throw new ArgumentException("Diese Matrizen können nicht miteinander multipliziert werden.");
    18. }
    Der *-Operator ruft dann einfach diese Funktion auf.
    Ok, ich bin's genau umgekehrt gewohnt. Ansonsten wäre das glaub' ich richtig. Das Einzige, was ich gemacht hätte, wäre, die Translation direkt auf einer Matrix auch noch zu definieren, weil eine Matrixmultiplikation für das, dass nur 2 bzw. 3 Werte aufaddiert werden schon ziemlich viele Berechnungen braucht.

    Gruß
    ~blaze~
    @Artentus: Wenn ich mich nicht ganz irre, ist eine Translation keine Matrizenmultiplikation, sondern lediglich eine Addition.
    Nur werden die Translationsvektoren gern in die 4. Reihe der Drehmatrizen geschrieben, damit alles fein beisammen steht.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Bedeutet dass, dass ich die Translationsmatrix gar nicht mit einer Drehmatrix multiplizieren kann?
    Ich dachte man stellt alle Transformationen als 4x4-Matrizen dar und multipliziert diese dann miteinander. Die dadurch entstehende Matrix multipliziert man dann mit allen Vertices.
    Doch geht immernoch mit einer Translationsmatrix und deren Multiplikation, sind halt dann ein paar unnötige Operationen dabei ;)

    Dass es genau umgekehr ist, ist nicht schlimm, denn OpenGL macht es z.B. auch andersrum als DirectX. Ist also alles ansichtssache ;)(Ebenso kehrt OpenGL Zeilen und Spalten um)
    Ich wollte auch mal ne total überflüssige Signatur:
    ---Leer---

    Artentus schrieb:

    multiplizieren
    Ich hab mal eben quer beet gekullert und bleibe bei meiner Meinung: Translation ist Addition, nicht aber Muiltiplikation.
    Allein die räumliche Vorstellung einer Translation zielt doch auf einen Offset, und das ist nun mal eine Addition.
    Sicherlich kann man die Translation vorher und nachher auch als Matrizenmultiplikation beschreiben, aber wenn ich denselben Offset auf 2 verschiedene Ortsvektoren anwende, wäre die multiplikative Translationsmatrix wohl nicht dieselbe.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    @RodFromGermany:
    Doch, die Translationsmatrix wäre dieselbe ;)

    Du musst dir das einfach so vorstellen, dass diese Matrix die ungekürzte Version ist.
    Aber da 0*x = 0 und 1*x=x löst sich das ganze nachher auf zu einer einfachen Addition ;)
    Ich wollte auch mal ne total überflüssige Signatur:
    ---Leer---

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „jvbsl“ ()