Matrixoperationen - Verschieben des Koordinatensystems

Bislang können wir verschiedene Dinge, wie zum Beispiel mit glVertex3f selbst zusammengesetzte Dinge oder GLU-Quadriken, wie Zylinder, Kegel oder Kreisscheiben zeichnen - die Objekte werden allerdings immer im Koordinatenursprung erscheinen. Um das zu ändern kann man die Transformations-Matrix so verändern, dass Objekte quasi verschoben, gedreht oder vergrößert werden. Zum Glück hat OpenGL Helferlein, sodass wir uns nicht persönlich um die Matrix-Operationen kümmern müssen. (Stichwort: Hauptachsentransformation)

Vor-/Nachbereitung

Da es häufig vorkommt, dass lediglich bestimmte Objekte einer Szene verschoben werden sollen und die danach gezeichneten Objekte wieder am alten Platz erscheinen sollen empfiehlt es sich Codeblöcke folgendermaßen zu erstellen:

// ..
glPushMatrix();
  // Verschieben der Objekte
glPopMatrix();
// ..

Mithilfe von glPushMatrix() wird die aktuelle Transformations-Matrix auf den Stack geschoben und somit zwischengespeichert. Mit glPopMatrix() wird die aktuell in Benutzung befindliche Matrix gelöscht und mit den Werten der obersten Matrix (also derjenigen Matrix, die zuletzt auf den Stack gelegt wurde) ersetzt. Dabei wird die oberste Matrix vom Stack genommen. Die „Blöcke“ lassen sich schachteln, sodass mehrere Matrizen auf dem Stack liegen können.

Objekte verschieben (glTranslatef)

Als Anschauungsbeispiel nehme ich einen GLU-Zylinder, der folgendermaßen gezeichnet wird:

gluQuadricObj* q=gluNewQuadric();
glColor3f(1,0,0);
gluCylinder(q, 2, 2, 4);

FIXME Screenshots!

Wie zu sehen ist, erscheint der Zylinder im Koordinatenursprung. Um den Zylinder zu verschieben, verwenden wir die Funktion glTranslatef(). Sie erwartet 3 Integerwerte, die für x-, y- und z-Werte stehen um die das Koordinatensystem verschoben werden soll. Der Zylinder wird dann im neuen Koordinatensystem immernoch im Ursprung gezeichnet, erscheint aber vom Ausgangskoordinatensystem verschoben. Gleiches gilt übrigens auch für die weiter vorgestellten Funktionen.

Folgender Code verschiebt den Zylinder also auf der X-Achse um 3 Einheiten und bringt die alte Matrix zurück:

glPushMatrix();
glTranslatef(3, 0, 0);
gluQuadricObj* q=gluNewQuadric();
glColor3f(1,0,0);
gluCylinder(q, 2, 2, 4);
glPopMatrix();

Objekte drehen (glRotatef)

Oft ist es auch notwendig zum Beispiel Zylinder zu drehen um daraus Rohre werden zu lassen oder Säulen. Vielleicht wollen Sie auch ein Fahrzeug sich drehen lassen. Verwenden Sie dazu glRotatef. Die Funktion erwartet 4 Integerwerte. Der erste Wert steht für die Winkelangabe um die gedreht werden soll (in Grad) und die anderen drei Werte stehen jeweils für die Drehachse. Es ist dabei ratsam bei jeder Drehung darauf zu achten, dass Sie nur eine Eins und den Rest Nullen verwenden. So entstehen folgende Möglichkeiten:

Drehung um die x-Achse:

glRotatef(90, 1, 0, 0);

Drehung um die y-Achse:

glRotatef(90, 0, 1, 0);

Drehung um die z-Achse:

glRotatef(90, 0, 0, 1);

In allen drei Code-Schnipseln drehe ich um 90 Grad.

Objekte skalieren (glScalef)

Manchmal ist es nötig Objekte in eine Richtung zu vergrößern; dazu können Sie die Funktion glScalef() verwenden, die drei Integerwerte verlangt, welche jeweils den Anteil der Skalierung auf den einzelnen Achsen angeben. Wichtig ist dabei zu beachten, dass eine 1 die Ausgangsgröße repräsentiert. Dh. folgender Code skaliert nichts:

glScalef(1, 1, 1);

Folgendermaßen vergrößern Sie den Zylinder in x-Richtung um den Faktor 1 und verkleinern in um die Hälfte in z-Richtung:

glPushMatrix();
glScalef(2, 1, 0.5);
gluQuadricObj* q=gluNewQuadric();
glColor3f(1,0,0);
gluCylinder(q, 2, 2, 4);
glPopMatrix();

Hinweise zur Verwendung

Beachten Sie bei der Verwendung der og. Funktionen zur Transformation, dass Sie bildlich gesehen das Koordinatensystem verschieben, aber immer noch die Objekte in der Mitte zeichnen. Wenn Sie beispielsweise folgenden Code verwenden wird der Zylinder um 10 Einheiten des Ausgangskoordinatensystems verschoben:

glPushMatrix();
glScalef(5, 1, 1);
glTranslatef(2, 0, 0);
gluQuadricObj* q=gluNewQuadric();
glColor3f(1,0,0);
gluCylinder(q, 2, 2, 4);
glPopMatrix();

Gleiches gilt auch für die Rotation des Koordinatensystems. Bedenken Sie, dass die Reihenfolge der Aufrufe der Funktionen Auswirkungen auf das Ergebnis haben wird. Wenn eine Szene in einem Test nicht so aussieht, wie erwartet versuchen Sie die verwenden Transformationsfunktionen in einer anderen Reihenfolge aufzurufen.