Matrix

Aus CINEMA 4D Wiki

Wechseln zu: Navigation, Suche

Inhaltsverzeichnis

Einführung

Eine Matrix (Plural: Matrizen) ist ein Datentyp, welcher das komplette Koordinatensystem eines Objekts enthalten kann. Mit ihr können die Position, Rotation und Skalierung eines Objekts ermittelt und manipuliert werden. Im Grunde entspricht das Null-Objekt in CINEMA 4D in seiner Funktionalität einer Matrix.

Aufbau einer Matrix

Eine Matrix enthält vier Vektoren:

NameC++C.o.f.f.e.e.Erklärung
Offset offv0Position des Matrix. Bei einer lokalen Matrix ist dies die lokale Position (relativ zum übergeordneten Objekt), bei einer globalen Matrix ist es die globale Position.
Vektor 1 v1v1Repräsentiert die X-Achse der Matrix.
Vektor 2 v2v2Repräsentiert die Y-Achse der Matrix.
Vektor 3 v3v3Repräsentiert die Z-Achse der Matrix.

Die drei Vektoren v1, v2 und v3 repräsentieren somit die drei Achsen eines Koordinatensystems. Jeder Vektor zeigt die Richtung einer Achse an. Die Länge der Vektoren zeigt die Skalierung des Objekts an, und ihre Ausrichtung die Rotation. Bei einer Skalierung von 1;1;1 beträgt die Länge jedes der drei Vektoren 1.

Idealerweise stehen alle drei Achsen-Vektoren im Rechten Winkel zueinander. Ist dies nicht der Fall, ist die Matrix verzerrt, was nur in den allerseltensten Fällen erwünscht ist, wenn überhaupt. In CINEMA 4D ist es grundsätzlich zu vermeiden. Zeigen zwei oder mehr Vektoren in dieselbe Richtung, tritt eine Singularität auf (vergl. Gimbal Lock). Dies kann durch die Verwendung des Kreuzprodukts bei der Konstruktion der Vektoren verhindert werden.


Operationen

Verschieben

Eine Verschiebung (Translation) kann ganz einfach durch Veränderung des Offset-Vektors (off in C++, v0 in Coffee) realisiert werden. Möchte man eine von ihrer aktuellen Position um 100 Einheiten in X-Richtung verschieben, addiert man einfach den Vektor 100;0;0 hinzu.

Coffee Code:


Matrix_verschieben(m, Verschiebung)
{
  return (m->GetV0() + Verschiebung);
}
 

C++ Code:


void Matrix_verschieben(Matrix &m, Vector &Verschiebung)
{
  m.off += Verschiebung;
}
 


Rotieren

Um eine Matrix zu rotieren, müssen alle 3 Vektoren v1, v2 und v3 verändert werden. Dabei muss immer darauf geachtet werden, dass sich die Länge der Vektoren nicht ändert (dann würde die Matrix unerwünscht skaliert) und dass die Vektoren immer stabil rechtwinklig zueinander stehen.

In der Praxis wird eine Rotationsangabe oft als Vektor formuliert (Rotation um H, B und P in Grad ° oder Radians). Aus diesem Vektor wird eine Rotationsmatrix berechnet und diese mit der zu rotierenden Matrix multipliziert. Das nennt man Transformieren. Klingt kompliziert, aber dafür stehen in der CINEMA 4D API zum Glück ein paar Funktionen bereit.

Zu beachten ist auch, dass beim Multiplizieren für Rotationen oft (aber nicht immer) die Position der Matrix nicht berücksichtigt werden darf. In C++ gibt es daher die Operatoren * (Multiplizieren) und ^ (Multiplizieren ohne Berücksichtigung des Offsets).

Coffee Code:


Matrix_rotieren(m, Rotieren)
{
  ...
} 

C++ Code:


void RotateMatrix(Matrix &m, Vector &Rotieren)
{
  m = m ^ HPBToMatrix(Rotieren);
} 


Skalieren

Das Skalieren einer Matrix wird realisiert, indem die Länge der drei Achsenvektoren (v1, v2 und v3) verändert wird, nicht jedoch deren Richtung. Bei einer absoluten Skalierung wird dabei die Länge einfach neu gesetzt, indem die normalisierten Achsenvektoren mit einem Wert multipliziert (Skalarprodukt) werden. Bei einer relativen Skalierung (unter Berücksichtigung der vorherigen Skalierung) werden anstatt der normalisierten Vektoren die unveränderten Vektoren mit dem Skalierungswert multipliziert.

Coffee Code:


Matrix_skalieren_absolut(m, Skalierung)
{
  ...
} 

Coffee Code:


Matrix_skalieren_relativ(m, Skalierung)
{
  ...
} 

C++ Code:


void Matrix_skalieren_absolut(Matrix &m, Vector &Skalierung)
{
  m.v1 = !m.v1 * Skalierung.x;
  m.v2 = !m.v2 * Skalierung.y;
  m.v3 = !m.v3 * Skalierung.z;
} 

C++ Code:


void Matrix_skalieren_relativ(Matrix &m, Vector &Skalierung)
{
  m.v1 *= Skalierung.x;
  m.v2 *= Skalierung.y;
  m.v3 *= Skalierung.z;
} 


Skalierung zurücksetzen

Um die Skalierung einer Matrix auf 1;1;1 zurückzusetzen,

Coffee Code:



Matrix_skalierung_reset(m)
{
  ...
} 

C++ Code:



void Matrix_skalierung_reset(Matrix &m)
{
  m.v1 = !m.v1;
  m.v2 = !m.v2;
  m.v3 = !m.v3;
} 

Transformationen für Objekt-Hierarchien

Transformationen sind immer wichtig, wenn man Koordinaten vom globalen Koordinatensystem in ein lokales, oder von einem lokalen in das globale, oder zwischen verschiedenen lokalen Koordinatensystemen übersetzen muss.

Wir können von beliebigen Objekten in der Szene leicht die globale Matrix ermitteln, und somit auch die globale Position eines Objekts Coffee Code:


var m = IrgendeinObjekt->GetMg(); 

C++ Code:


Matrix m = IrgendeinObjekt->GetMg(); 

Mit einzelnen bestandteilen eines Objekts (z.B. Punkte von Geometrien oder Splines, Tangenten von Splines, etc) ist die nicht so leicht.

Beispiel: Ein Punkt einer Geometrie hat eine Position. Diese Position jedoch ist bezogen auf das Lokale Koordinatensystem des Objekts. Verschiebt man das Objekt, so werden die Punkte der Geometrie ja mit verschoben. Möchte man die globale Position dieses Punktes ermitteln, um z.B. ein Objekt an diesem Punkt zu befestigen, muss die lokale Position des Punktes mit der globalen Matrix des Objekts transformiert (multipliziert) werden.

Coffee Code:



...
 

C++ Code:


Vector *Punkte = ToPoint(IrgendeinObjekt)->GetPointR();  // Auflistung (Array) der Punkte eines Polygonobjekts ermitteln
Vector LokalePunktposition = Punkte[1];  // Position von Punkt Nr. 1 ermitteln (ergibt eine lokale Position)
Matrix m = IrgendeinObjekt->GetMg();  // Globale Matrix des Objekts ermitteln

Vector GlobalePunktposition = LokalePunktposition * m;
 


Weiterhin kann es auch mal erwünscht sein, eine Position vom globalen in einen lokalen Raum zu verschieben. Nehmen wir mal an, wir haben ein beliebiges Objekt A in der Szene, und ein Polygon-Objekt B. Wir möchten nun einen Geometrie-Punkt von Objekt B an die globale Position von Objekt A verschieben.

C++ Code:


Vector *Punkte = ToPoint(ObjektB)->GetPointW();  // Beschreibbare Auflistung (Array) der Punkte eines Polygonobjekts ermitteln
Vector GlobaleObjektposition = ObjektA->GetMg().off;  // Globale Position von Objekt A ermitteln
Matrix m = ObjektB->GetMg();  // Globale Matrix des Objekts B ermitteln

Punkte[1] = GlobaleObjektposition * !m;  // Verschiebung des Punktes an die lokale Position in Objekt B, die der globalen Position von Objekt A entspricht
 


Beispiele

Ausrichtung einer Matrix auf ein Ziel (einfach)

Ausrichtung einer Matrix auf ein Ziel (mit UpVector)

Weitere Informationen

Möchte man sich mit Matrizen in CINEMA 4D beschäftigen (egal, ob in XPresso, Coffee oder C++), so ist es angeraten den Artikel "Using matrices" zu lesen, der sich in der Coffee-Dokumentation befindet. Diese kann frei von der Maxon-Website heruntergeladen werden:
MAXON Plugincafé - SDK Downloads

Persönliche Werkzeuge