Antworten:
Ja, Sie können bei der Übersetzung einen Vektor hinzufügen. Der Grund für die Verwendung einer Matrix liegt in der einheitlichen Handhabung verschiedener kombinierter Transformationen.
Zum Beispiel wird die Rotation normalerweise mithilfe einer Matrix durchgeführt (prüfen Sie @ MickLH-Kommentar für andere Möglichkeiten, um mit Rotationen umzugehen), um mehrere Transformationen (Rotation / Translation / Skalierung / Projektion ... usw.) auf einheitliche Weise zu behandeln. Sie müssen sie in einer Matrix codieren.
Nun, technisch gesehen; Eine Transformation bildet einen Punkt / Vektor auf einen anderen Punkt / Vektor ab.
p` = T(p);
Dabei ist p 'der transformierte Punkt und T (p) die Transformationsfunktion.
Da wir keine Matrix verwenden, müssen wir dies tun, um mehrere Transformationen zu kombinieren:
p1 = T (p);
p final = M ( p 1 );
Eine Matrix kann nicht nur mehrere Transformationstypen in einer einzigen Matrix kombinieren (z. B. affin, linear, projektiv).
Die Verwendung einer Matrix gibt uns die Möglichkeit, Transformationsketten zu kombinieren und diese anschließend in einem Stapel zu multiplizieren. Dies erspart uns normalerweise eine Menge Zyklen durch die GPU (danke an @ChristianRau für den Hinweis).
T final = T * R * P; // translate Projekt drehen
p final = T final * p;
Es ist auch gut darauf hinzuweisen, dass GPUs und sogar einige CPUs für Vektoroperationen optimiert sind. CPUs mit SIMD und GPUs sind standardmäßig datengesteuerte Parallelprozessoren, sodass die Verwendung von Matrizen perfekt zur Hardwarebeschleunigung passt (tatsächlich wurden GPUs für Matrix- / Vektoroperationen entwickelt).
Wenn Sie sich nur auf einer Achse bewegen und keine andere Transformation anwenden, ist das, was Sie vorschlagen, in Ordnung.
Die eigentliche Stärke der Verwendung einer Matrix besteht darin, dass Sie auf einfache Weise eine Reihe komplexer Vorgänge miteinander verketten und dieselbe Reihe von Vorgängen auf mehrere Objekte anwenden können.
Die meisten Fälle sind nicht so einfach, und wenn Sie Ihr Objekt zuerst drehen und statt der Weltachsen entlang seiner lokalen Achsen transformieren möchten, können Sie nicht einfach 10 zu einer der Zahlen addieren und es richtig arbeiten lassen .
Um die "Warum" -Frage kurz und bündig zu beantworten, kann eine 4x4-Matrix Rotations-, Translations- und Skalierungsvorgänge gleichzeitig beschreiben. In der Lage zu sein, eines davon in einer konsistenten Weise zu beschreiben, vereinfacht viele Dinge.
Verschiedene Arten von Transformationen können einfacher mit unterschiedlichen mathematischen Operationen dargestellt werden. Wie Sie bemerken, kann die Übersetzung einfach durch Hinzufügen erfolgen. Einheitliche Skalierung durch Multiplikation mit einem Skalar. Eine entsprechend gestaltete 4x4-Matrix kann jedoch alles. Die konsequente Verwendung von 4x4 vereinfacht Code und Schnittstellen erheblich. Sie zahlen etwas Aufwand für das Verständnis dieser 4x4, aber viele Dinge werden dadurch einfacher und schneller.
Der Grund für die Verwendung einer 4x4-Matrix ist, dass die Operation eine lineare Transformation ist . Dies ist ein Beispiel für homogene Koordinaten . Dasselbe geschieht im 2d-Fall (unter Verwendung einer 3x3-Matrix). Der Grund für die Verwendung homogener Koordinaten ist, dass alle drei geometrischen Transformationen mit einer Operation durchgeführt werden können. ansonsten müsste man eine 3x3-Matrixmultiplikation und eine 3x3-Matrixaddition (für die Übersetzung) durchführen. dieser link von cegprakash ist nützlich.
Übersetzungen können nicht durch 3D-Matrizen dargestellt werden
Ein einfaches Argument ist, dass die Übersetzung den Ursprungsvektor annehmen kann:
0
0
0
weg von der Herkunft, sagen zu x = 1
:
1
0
0
Das würde aber eine Matrix erfordern, die:
| a b c | |0| |1|
| d e f | * |0| = |0|
| g h i | |0| |0|
Das ist aber unmöglich.
Ein weiteres Argument ist das Singular Value Decomposition Theorem , das besagt, dass jede Matrix mit zwei Rotations- und einer Skalierungsoperation gebildet werden kann. Keine Übersetzungen da.
Warum können Matrizen verwendet werden?
Viele modellierte Objekte (z. B. ein Auto-Chassis) oder Teile von modellierten Objekten (z. B. ein Autoreifen, ein Antriebsrad) sind Körper: Die Abstände zwischen Scheitelpunkten ändern sich nie.
Die einzigen Transformationen, die wir an ihnen vornehmen möchten, sind Rotationen und Übersetzungen.
Die Matrixmultiplikation kann sowohl Rotationen als auch Übersetzungen codieren.
Rotationsmatrizen haben explizite Formeln, zB: Eine 2D-Rotationsmatrix für Winkel hat a
folgende Form:
cos(a) -sin(a)
sin(a) cos(a)
Es gibt analoge Formeln für 3D , aber beachten Sie, dass 3D-Rotationen 3 Parameter anstelle von nur 1 annehmen .
Übersetzungen sind weniger trivial und werden später besprochen. Sie sind der Grund, warum wir 4D-Matrizen benötigen.
Warum ist es cool, Matrizen zu verwenden?
Denn die Zusammensetzung mehrerer Matrizen kann durch Matrixmultiplikation vorberechnet werden .
Wenn wir beispielsweise eintausend Vektoren v
unseres Fahrzeugchassis mit Matrix übersetzen T
und dann mit Matrix drehen wollen R
, anstatt Folgendes zu tun:
v2 = T * v
und dann:
v3 = R * v2
Für jeden Vektor können wir vorberechnen:
RT = R * T
und dann mache nur eine Multiplikation für jeden Eckpunkt:
v3 = RT * v
Noch besser: Wenn wir dann die Scheitelpunkte von Reifen und Antriebsrad relativ zum Auto platzieren möchten, multiplizieren wir einfach die vorherige Matrix RT
mit der Matrix relativ zum Auto.
Dies führt natürlich dazu, dass ein Stapel von Matrizen erhalten bleibt:
Wie das Hinzufügen einer Dimension das Problem löst
Betrachten wir den Fall von 1D bis 2D, der einfacher zu visualisieren ist.
Eine Matrix in 1D ist nur eine Zahl, und wie wir in 3D gesehen haben, kann sie keine Übersetzung, sondern nur eine Skalierung ausführen.
Aber wenn wir die zusätzliche Dimension wie folgt hinzufügen:
| 1 dx | * |x| = | x + dx |
| 0 1 | |1| | 1 |
und wenn wir dann die neue extra dimension vergessen, bekommen wir:
x + dx
wie wir wollten.
Diese 2D-Transformation ist so wichtig, dass sie einen Namen hat: Scher-Transformation .
Es ist cool, diese Transformation zu visualisieren:
Beachten Sie, wie jede horizontale Linie (fest y
) gerade übersetzt wird.
Wir haben die Linie zufällig y = 1
als unsere neue 1D-Linie genommen und mit einer 2D-Matrix übersetzt.
Die Dinge sind analog in 3D, mit 4D-Schermatrizen der Form:
| 1 0 0 dx | | x | | x + dx |
| 0 1 0 dy | * | y | = | y + dy |
| 0 0 1 dz | | z | | z + dz |
| 0 0 0 1 | | 1 | | 1 |
Und unsere alten 3D-Rotationen / Skalierungen haben jetzt die Form:
| a b c 0 |
| d e f 0 |
| g h i 0 |
| 0 0 0 1 |
Dieses Jamie King-Video-Tutorial ist ebenfalls sehenswert.
Affiner Raum
Der affine Raum ist der Raum, der durch alle unsere linearen 3D-Transformationen (Matrixmultiplikationen) zusammen mit der 4D-Scherung (3D-Übersetzungen) erzeugt wird.
Wenn wir eine Schermatrix und eine lineare 3D-Transformation multiplizieren, erhalten wir immer etwas von der Form:
| a b c dx |
| d e f dy |
| g h i dz |
| 0 0 0 1 |
Dies ist die allgemeinste affine Transformation, die 3D-Rotation / Skalierung und -Translation ausführt.
Eine wichtige Eigenschaft ist, dass wenn wir 2 affine Matrizen multiplizieren:
| a b c dx | | a2 b2 c2 dx2 |
| d e f dy | * | d2 e2 f2 dy2 |
| g h i dz | | g2 h2 i2 dz2 |
| 0 0 0 1 | | 0 0 0 1 |
Wir erhalten immer eine andere affine Formmatrix:
| a3 b3 c3 (dx + dx2) |
| d3 e3 f3 (dy + dy2) |
| g3 h3 i3 (dz + dz2) |
| 0 0 0 1 |
Mathematiker nennen diese Eigenschaft Schließung und ist erforderlich, um ein Leerzeichen zu definieren.
Für uns bedeutet dies, dass wir weiterhin Matrixmultiplikationen durchführen können, um die endgültigen Transformationen glücklich zu berechnen, weshalb wir in erster Linie gebrauchte Matrizen verwenden, ohne jemals allgemeinere lineare 4D-Transformationen zu erhalten, die nicht affin sind.
Kegelstumpfprojektion
Aber warten Sie, es gibt eine weitere wichtige Transformation, die wir ständig durchführen: glFrustum
Dadurch erscheint ein Objekt 2x weiter, 2x kleiner.
Machen Sie sich zunächst ein Bild von glOrtho
vs glFrustum
unter: https://stackoverflow.com/questions/2571402/explain-the-usage-of-glortho/36046924#36046924
glOrtho
kann man nur mit übersetzungen + skalierung machen, aber wie kann man das glFrustum
mit matrizen umsetzen ?
Nehme an, dass:
z = -1
ist ein Quadrat der Länge 2z = -2
Wenn wir nur allgemeinere 4-Vektoren vom Typ erlauben würden:
(x, y, z, w)
mit w != 0
und zusätzlich identifizieren wir uns (x, y, z, w)
mit (x/w, y/w, z/w, 1)
, dann wäre eine Kegelstumpftransformation mit der Matrix:
| 1 0 0 0 | | x | | x | | x / -z |
| 0 1 0 0 | * | y | = | y | identified to | y / -z |
| 0 0 1 0 | | z | | z | | -1 |
| 0 0 -1 0 | | w | | -z | | 0 |
Wenn wir wegwerfen z
und w
am Ende bekommen wir:
x_proj = x / -z
y_proj = y / -z
Das ist genau das, was wir wollten! Wir können das für einige Werte überprüfen, zB:
z == -1
, genau auf der Ebene wir projizieren zu, x_proj == x
und y_proj == y
.z == -2
, dann x_proj = x/2
: Objekte sind halb so groß.Beachten Sie, dass die glFrustum
Transformation keine affine Form hat: Sie kann nicht nur mit Rotationen und Übersetzungen implementiert werden.
Der mathematische "Trick" des Addierens w
und Dividierens heißt homogene Koordinaten
Siehe auch: Verwandte Fragen zum Stapelüberlauf: https://stackoverflow.com/questions/2465116/understanding-opengl-matrices
Sehen Sie sich dieses Video an, um die Konzepte von Modell, Ansicht und Projektion zu verstehen.
4x4-Matrizen werden nicht nur zum Verschieben eines 3D-Objekts verwendet. Aber auch für verschiedene andere Zwecke.
Sehen Sie sich das an, um zu verstehen, wie die Eckpunkte in der Welt als 4D Matrizen dargestellt werden und wie sie transformiert werden.