Angenommen, Sie schreiben Matrix-Code, der Rotation, Übersetzung usw. für den 3D-Raum übernimmt.
Nun müssen die Transformationsmatrizen 4x4 sein, damit sie in die Übersetzungskomponente passen.
Sie müssen jedoch tatsächlich keinew
Komponente im Vektor speichern , oder?
Auch bei der perspektivischen Unterteilung können Sie einfach w
außerhalb des Vektors berechnen und speichern und die perspektivische Unterteilung durchführen, bevor Sie von der Methode zurückkehren.
Beispielsweise:
// post multiply vec2=matrix*vector
Vector operator*( const Matrix & a, const Vector& v )
{
Vector r ;
// do matrix mult
r.x = a._11*v.x + a._12*v.y ...
real w = a._41*v.x + a._42*v.y ...
// perspective divide
r /= w ;
return r ;
}
Gibt es einen Punkt beim Speichern w
in der Vector-Klasse?
mathematics
vector
projection
Bobobobo
quelle
quelle
r.x = ... + a._14*v.w;
r.y = ... + a._24*v.w;
r.z = ... + a._34*v.w;
r.w = ... + a._44*v.w;
Sehen Sie sich meine Antwort für Details anAntworten:
EDIT Disclaimer : In dieser Antwort werden Vektoren mit w == 0 als Vektoren und mit w == 1 als Punkte bezeichnet. Obwohl FxIII darauf hinwies, ist dies keine mathematisch korrekte Terminologie. Da der Punkt der Antwort jedoch nicht die Terminologie ist, sondern die Notwendigkeit, beide Vektortypen zu unterscheiden, werde ich mich daran halten. Aus praktischen Gründen ist diese Konvention in der Spieleentwicklung weit verbreitet.
Es ist nicht möglich, zwischen Vektoren und Punkten ohne 'w'-Komponente zu unterscheiden. Es ist 1 für Punkte und 0 für Vektoren.
Wenn Vektoren mit einer affinen 4x4-Transformationsmatrix multipliziert werden, deren letzte Zeile / Spalte eine Translation enthält, wird der Vektor ebenfalls translatiert, was falsch ist. Es müssen nur Punkte translatiert werden. Dafür sorgt die Null in der 'w'-Komponente eines Vektors.
Das Hervorheben dieses Teils der Matrix-Vektor-Multiplikation macht es klarer:
Das heißt, es wäre falsch, einen Vektor, beispielsweise eine Rotationsachse, zu verschieben. Das Ergebnis ist einfach falsch. Wenn Sie die vierte Komponente Null haben, können Sie immer noch dieselbe Matrix verwenden, die die Punkte transformiert, um die Rotationsachse zu transformieren. Das Ergebnis ist dann gültig und seine Länge bleibt erhalten, solange es keine Skala in der Matrix gibt. Das ist das Verhalten, das Sie für Vektoren wünschen. Ohne die 4. Komponente müssten Sie 2 Matrizen (oder 2 verschiedene Multiplikationsfunktionen mit einem impliziten 4. Parameter) erstellen und 2 verschiedene Funktionsaufrufe für Punkte und Vektoren durchführen.
Um die Vektorregister moderner CPUs (SSE, Altivec, SPUs) zu verwenden, müssen Sie ohnehin 4x 32-Bit-Floats (ein 128-Bit-Register) übergeben und sich um die Ausrichtung kümmern, normalerweise 16 Byte. Sie haben also ohnehin keine Chance, den Platz für die 4. Komponente zu sichern.
EDIT: Die Antwort auf die Frage ist im Grunde
Man muss eine davon auswählen, es ist nicht möglich, nur {x, y, z} zu speichern und trotzdem nur eine Matrix-Vektor-Multiplikationsfunktion zu verwenden. XNA verwendet zum Beispiel den letzteren Ansatz, indem es 2 Transformationsfunktionen in seiner Vector3- Klasse namens
Transform
und hatTransformNormal
Hier ist ein Codebeispiel, das beide Ansätze zeigt und die Notwendigkeit demonstriert, beide Arten von Vektoren auf eine der beiden möglichen Arten zu unterscheiden. Wir werden eine Spieleinheit mit einer Position und einer Blickrichtung in der Welt bewegen, indem wir sie mit einer Matrix transformieren. Wenn wir die 'w'-Komponente nicht verwenden, können wir nicht mehr dieselbe Matrix-Vektor-Multiplikation verwenden, wie dieses Beispiel zeigt. Wenn wir es trotzdem tun, erhalten wir eine falsche Antwort für den transformierten
look_dir
Vektor:Ursprünglicher Entitätsstatus:
Nun wird eine Transformation mit einer Verschiebung von x + 5 und einer Drehung von 90 Grad um die y-Achse auf dieses Objekt angewendet. Die richtige Antwort nach der Transformation lautet:
Die richtige Antwort erhalten wir nur, wenn wir Vektoren mit w == 0 und Positionen mit w == 1 auf eine der oben dargestellten Arten unterscheiden.
quelle
Wenn Sie eine Vektorklasse erstellen, wird in der Klasse vermutlich die Beschreibung eines 3D-Vektors gespeichert. 3D-Vektoren haben die Größen x, y und z. Wenn Ihr Vektor also keine willkürliche Größe benötigt, nein, Sie werden ihn nicht in der Klasse speichern.
Es gibt einen großen Unterschied zwischen einem Vektor und einer Transformationsmatrix. Da sowohl DirectX als auch OpenGL für Sie Matrizen verarbeiten, speichere ich normalerweise keine 4x4-Matrix in meinem Code. Vielmehr speichere ich Euler-Rotationen (oder Quaternionen, wenn Sie möchten - die zufällig eine aw-Komponente haben) und die x, y, z-Übersetzung. Die Translation ist ein Vektor, wenn Sie möchten, und die Rotation würde technisch auch in einen Vektor passen, in dem jede Komponente den Rotationsbetrag um ihre Achse speichert.
Wenn Sie etwas tiefer in die Mathematik eines Vektors eintauchen möchten, ist ein euklidischer Vektor nur eine Richtung und eine Größe. Typischerweise wird dies durch ein Triplett von Zahlen dargestellt, wobei jede Zahl die Größe entlang einer Achse ist; Ihre Richtung ergibt sich aus der Kombination dieser drei Größen, und die Größe kann mit der euklidischen Abstandsformel ermittelt werden. Oder manchmal wird es wirklich als eine Richtung (ein Vektor mit Länge = 1) und eine Größe (ein Gleitkomma) gespeichert. Wenn dies zweckmäßig ist (z. B. wenn sich die Größe häufiger ändert als die Richtung, kann es zweckmäßiger sein, einfach zu sein Ändern Sie diese Betragszahl, um einen Vektor zu nehmen, ihn zu normalisieren und die Komponenten mit der neuen Betragszahl zu multiplizieren.
quelle
Die vierte Dimension im 3D-Vektor wird verwendet, um die affinen Transformationen zu berechnen, die mit Matrizen allein nicht berechnet werden können. Der Raum bleibt dreidimensional, was bedeutet, dass der vierte auf irgendeine Weise im 3D-Raum abgebildet wird.
Bemaßungen zuordnen bedeutet, dass unterschiedliche 4D Vektoren denselben 3D Punkt anzeigen. Die Abbildung ist, dass wenn A = [x ', y', z '. W'] und B = [x ", y", z ", w"], sie den gleichen Punkt darstellen, wenn x '/ x "= y' / y "= z '/ z" = w' / w "= α, dh die Komponenten sind proportional für den gleichen Koeffizienten α.
Sagte, dass man einen Punkt - sagen wir (1,3,7) - auf unendliche Weise wie (1,3,7,1) oder (2,6,14,2) oder (131,393,917,131) oder allgemein (α · 1, α · 3, α · 7, α).
Dies bedeutet, dass Sie einen 4D-Vektor auf einen anderen skalieren können, der denselben 3D-Punkt darstellt, sodass w = 1: Die Form (x, y, z, 1) ist die kanonische Form.
Wenn Sie eine Matrix auf diesen Vektor anwenden, erhalten Sie möglicherweise einen Vektor mit nicht w = 1, aber Sie können die Ergebnisse immer skalieren, um sie in kanonischer Form zu speichern. Die Antwort scheint also zu sein: "Sie sollten 4D-Vektoren verwenden, wenn Sie rechnen, aber die vierte Komponente nicht speichern" .
Dies ist ganz richtig, aber es gibt einige Punkte, die Sie nicht in kanonischer Form formulieren können: Punkte wie (4,2,5,0). Diese Punkte sind spezielle, sie repräsentieren gerichtete unendliche Punkte und können konsistent auf Einheitsvektoren normiert werden: Sie können sicher ins Unendliche gehen und zurückkehren (sogar zweimal), ohne Chuck Norris zu sein. Sie erhalten eine miserable Division durch Null, wenn Sie versuchen, diese Vektoren in kanonischer Form zu erzwingen.
Jetzt wissen Sie, die Wahl liegt also bei Ihnen!
quelle
Ja, das tust du. Ihre Transformation ist für einige Arten von Vektoren falsch. Sie können dies in der mathematischen D3DX-Bibliothek sehen - sie haben zwei verschiedene Matrix-Vektor-Multiplikationsfunktionen, eine für w = 0 und eine für w = 1.
quelle
Kommt darauf an, was Sie wollen und brauchen. :)
Ich würde es speichern, b / c es ist notwendig für Transformationen und solche (Sie können einen 3-Vektor nicht mit einer 4x4-Matrix multiplizieren), obwohl, wenn Sie immer nur aw von 1 haben, ich denke, Sie könnten es einfach vortäuschen.
quelle