CGExercises

CG Exercise #05

Computergraphik Übungsblatt #05


OpenGL Tutorial: Modeling & Viewing



OpenGL & MVP



glVertex Cheat Sheet

Aufgabe 5.1: Präliminarien

Wir beginnen wieder mit der OpenGL-Programmiervorlage (qt_template), d.h. Sie laden und zeichnen wie in der vorherigen Übung Ihr Blender Objekt. Sie sollten dazu aber eine Kopie des vorherigen Programms bzw. Quelltextes in einem neuen Verzeichnis anlegen (siehe Cheat-Sheet). Das ist die empfohlene Vorgehensweise für die weiteren Aufgaben.

Alternativ können wir auch einfach einen Würfel wie in der Hausaufgabe zeichnen. Oder wir starten mit dem Quelltext cube.cpp, der bereits einen vorgefertigten Würfel enthält.

Aufgabe 5.2: GLM (bzw. GLSLMath)

Definieren Sie mit der GLM (siehe Cheat Sheet → GLSLmath) den homogenen 3D Punkt bzw. Vertex $v = (0,0,-1,1)$ und geben Sie ihn auf der Konsole aus (mit dem << operator).

Den Vertex $v$ kann man auch etwas hübscher mit glslmath::print(...) ausgeben.

Berechnen Sie die sog. aspect-ratio, d.h. das Seitenverhältnis des Framebuffers (wie z.B. 16:9 bei FHD) und geben Sie dieses Verhältnis ebenfalls aus.

Tipp: Breite und Höhe des Framebuffers → width() bzw. height()

Materialien:

Aufgabe 5.3: Trackball mit dem Framework

Das Framework hat die Möglichkeit, einen Trackball zur Verfügung zu stellen, bei dem man mit der Maus das dargestellte Objekt “greifen” und rotieren kann.

Dazu stellt das Framework eine Rotations- bzw. Modellierungsmatrix zur Verfügung, die von der lglGetManip() Funktion zurück geliefert wird. Diese speichern wir uns in einer Variable ab:

mat4 M_manip = lglGetManip();

Nun multiplizieren wir den Vertex $v$ erstmal mit dieser Modellierungsmatrix und geben beides fortlaufend mit glslmath::print(...) aus.

Bauen Sie den Trackball nun in Ihr Programm ein, so dass Ihr Objekt mit dem Trackball rotiert wird. Dazu muss einfach die Matrix als aktuelle Modellierungsmatrix $M_M$ auf die Grafikkarte geladen werden. Dazu verwendet man den Befehl lglLoadMatrix(...). Dieser Befehl setzt die aktuelle Modelview-Matrix $M_MV$, wobei wir annehmen, dass die View-Matrix $M_V$ momentan noch die Einheitsmatrix ist.

Tipp: Der Trackball skaliert auch (mit dem Mausrad).

Aufgabe 5.4: MVP Berechnen mit der GLM


Strahlenverlauf einer Spiegelreflexkamera

Nun berechnen wir die restlichen Teilmatrizen der MVP-Matrix selber mit der GLM.

Berechnen Sie dazu die Matrizen $M_M$, $M_V$ und $M_P$ mit den konkreten Werten aus der Hausaufgabe. Verwenden Sie die dafür die Funktionen mat4::perspective für $M_P$, mat4::lookat für $M_V$ und eine Kombination von mat4::translate und mat4::rotate für $M_M$. Beachten Sie außerdem, dass das korrekte Seitenverhältnis für $M_P$ verwendet wird!

Berechnen Sie die Gesamtmatrizen $M_{MV}$ und $M_{MVP}$ durch Multiplikation der entsprechenden Teilmatrizen und geben Sie das Resultat für beide Matrizen aus. Vergleichen Sie mit der Hausaufgabe!

Verwenden Sie außerdem wieder die Rotationsmatrix des Trackballs als zusätzliche Modellierungsmatrix. An welcher Stelle muss diese Matrix eingefügt werden, damit sie sich auf die Objektkoordinaten auswirkt, also das Objekt rotiert wird?

Aufgabe 5.5: MVP anwenden

Verwenden Sie nun die obige MVP-Matrix zur perspektivischen Darstellung des Ihres Objeckts bzw. Würfels. Dabei teilen wir die Gesamtmatrix so auf, so dass $M_P$ mit lglProjection(...) geladen wird und $M_{MV}$ mit lglModelView(...) geladen wird. Der Grund dafür ist, dass sich erstens die Projektionsmatrix für einen Frame nicht ändert und zweitens $M_{MV}$ später noch für Beleuchtungsberechnungen benötigt wird.

Wahrscheinlich sehen Sie nun zuerst einmal gar nichts, weil der Würfel außerhalb des sichtbaren Bereichs liegt. Wo war dieser nochmal?

Welche Parameter kann man anpassen, damit der Würfel sichtbar wird? Es gibt prinzipiell drei verschiedene Möglichkeiten.

Aufgabe 5.6: Meshes und Koordinatensysteme


OpenGL Koordinatensysteme

Das Framework bietet wie Blender vorgefertigte Meshes bzw. VBOs für die Darstellung von Kugeln, Pyramiden, Tori etc. (siehe Cheat Sheet → VBOs). Diese sind alle auf eine Einheitsgröße normiert, so dass sie sich mit einer Skalierungsmatrix S einfach auf eine bestimmte Größe skalieren lassen.

Insbesondere bietet das Framework das Mesh lglCoordSys als Koordinatensystemkreuz mit drei verschiedenfarbigen Achsen. Stellen Sie damit das lokale Koordinatensystem Ihres Objektes dar, d.h. das Koordinatensystem, welches mit dem Trackball rotiert wird.

Verwenden Sie dieses Mesh ebenfalls, um das System der Weltkoordinaten darzustellen. Berechnen Sie dazu zuerst eine weitere entsprechende MVP-Matrix für dieses zusätzliche Koordinatensystem. Da die Projektions-Matrix gleich bleibt, reicht es aus, nur eine weitere entsprechende Model-View-Matrix zu berechnen und auf die Graphikkarte zu laden.

Gehen Sie also nach folgendem Muster vor:

// projection matrix for all objects
lglProjection(P);

// modelview matrix for the first object
mat4 MV1 = ...
lglModelView(MV1 * S1);
lglRender(obj1);

// modelview matrix for the second object
mat4 MV2 = ...
lglModelView(MV2 * S2);
lglRender(obj2);

// and so on
...

Welche Parameteranpassungen am Frustum müssen vorgenommen werden, damit das Weltkoordinatenkreuz sichtbar wird?

Aufgabe 5.7: Weitere Meshes (Empfohlen)

Bauen Sie jetzt weitere Objekte bzw. Meshes in Ihr Programm ein. Zeichnen Sie z.B. ein paar Kugeln, Tori, Teapots etc. und färben Sie diese Objekte unterschiedlich ein (via lglColor()).

Aufgabe 5.8: Experimentieren (Optional)

Experimentieren Sie mit der Reihenfolge der Rotationen und Translationen und der Skalierung verschiedener Meshes.

Lassen Sie ein Objekt um sich selber rotieren und lassen Sie ein Objekt um den Weltursprung rotieren.

Experimentieren Sie z.B. auch mit der nicht-uniformen Skalierung eines Würfels zu einem Quader.

Aufgabe 5.9: MVP im Shader

Ergänzen Sie den Code um einen Shader bzw. bauen Sie in Ihren Code einen Shader-Editor ein. Dazu benötigen Sie die folgenden zusätzliche Zeilen:

Im Globalen Namensraum:

GLuint prog_id;
const char shader[] = "";

In der Methode initializeOpenGL():

prog_id = lglCompileGLSLProgram(shader);
create_lgl_Qt_ShaderEditor("shader", &prog_id);

In der Methode renderOpenGL():

lglUseProgram(prog_id, false);

Der Shader Editor startet mit dem denkbar einfachsten Programm, dem sog. Plain-Shader.

Überlegen Sie Sich: Aus welchen zwei Bestandteilen besteht dieser Plain-Shader? Welche Stufe der Graphik-Pipeline repräsentieren diese und welche Stufe befindet sich dazwischen? In welcher Stufe wird mit der MVP multipliziert und wie häufig? Wie häufig wird der andere Bestandteil verwendet? Dies ist zum Verständnis der weiteren Übungen relevant!

Aufgabe 5.10: Sonnensystem (Optional)


Ein nettes Spielzeug

Versuchen Sie, mit geigneten Rotationen und Translationen die Objekte wie ein Planetensystem (Sonne/Erde/Mond/Satellit/Hai) umeinander rotieren zu lassen. Fangen Sie mit der Sonne an, d.h. platzieren Sie eine gelbe Kugel im Ursprung der Weltkoordinaten.

Tipp: Bei vielen Objekten bzw. bei vielen lokalen Koordinatensystemen kommt man schnell durcheinander. Speichern Sie Sich daher die jeweils letzte funktionierende Programmversion als Sicherheitskopie ab.


Hausaufgaben bis zum sechsten Praktikum



Ein netter Ausziehtisch

1. Hierarchische Modellierung / Theorie:
Ein Tisch besteht aus einer Arbeitsplatte und vier Beinen. Die Beine sind getrennt von der Tischplatte modelliert. Dabei sei $M_P$ die Projektion, $M_V$ die View-Transformation, $M_T$ die Modellierungstranformation, welche die Position (und Orientierung) des Tisches in der Welt beschreibt, und $M_{B_x}$ die vier Modellierungstransformationen, die beschreiben, wie man von der Tischposition zur Position des x-ten Beines kommt.

  1. Zeichnen Sie den dazugehörigen Szenengraphen!
  2. Und beschreiben Sie nun, wie die ModellViewProjection-Matrizen aufgebaut sind, um die einzelnen 5 Elemente zu rendern!

2. Hierarchische Modellierung / Coding:
Wie würde diese Aufgabe in der renderOpenGL() Methode des Frameworks aussehen? Nehmen Sie an, Sie haben die Funktionen zeichneTischplatte() und zeichneTischbein() zur Verfügung und die benötigten Matrizen stehen schon in den Variablen $M_P$, $M_V$, $M_T$, $M_{B_1}$, $M_{B_2}$, $M_{B_3}$ und $M_{B_4}$.

  • Tipp: Sie müssen nur jeweils für jeden Zeichenvorgang die ensprechende MV- und P-Matrix setzen (via lglProjection() und lglModelView()) und dann die jeweilige Zeichenroutine aufrufen. Da sich die Projektionsmatrix nicht ändert, muss diese nicht mehrfach gesetzt werden.

Options: