Computergrafik

Konstruktion von Szenengraphen

Hierarchie Ebenen | | Szenengraph Implementierung

Wie implementiert man konkret die Konstruktion und die Traversierung eines Szenengraphen wie z.B. des folgenden?

Konstruktionsprinzip in 10 Schritten:

1) Jeder Knoten eines Szenengraphen ist von einer Basisklasse abgeleitet. Für das glVertex Framework ist das die Basisklasse lgl_Node. Zuanfangs besteht der Szenengraph nur aus einem Zeiger auf den Wurzelknoten. Da der Szenengraph noch keinen Knoten enthält ist der Zeiger der NULL-Zeiger:

lgl_Node *root = NULL;

2) Einen neuen Knoten erzeugt man dynamisch wie folgt:

lgl_Node *node = new lgl_Node();

Der erste erzeugte Knoten ist typischerweise auch zugleich der Wurzel-Knoten:

root = node;

3) Jeder Knoten enthält die Methode add(), mit der sich ein weiterer neuer Knoten als Kind hinzufügen lässt:

lgl_Node *child = new lgl_Node();
node->add(child);

4) Transformations-Knoten wie z.B. einen Translations-Knoten (lgl_TranslationNode) oder einen Rotations-Knoten (lgl_RotationNode) fügt man damit wie folgt hinzu:

vec3 t = ...; // translation vector
lgl_Node *child = new lgl_TranslationNode(t);
node->add(child);

double w = ...; // rotation angle
vec3 a = ...; // rotation axis
lgl_Node *grandchild = new lgl_RotationNode(w, a);
child->add(grandchild);

Die add() Methode gibt als Rückgabewert einen Zeiger auf das gerade hinzugefügte Kind zurück. Dadurch lassen sich mehrere Hinzufügungen konkatenieren:

node->add(new lgl_TranslationNode(t))->add(new lgl_RotationNode(w, a));

Dies entspricht einer Starrkörper-Transformation (lgl_TransformationNode) mit der Matrix M:

mat4 M = mat4::rigid(w, a, t);
node->add(new lgl_TransformationNode(M));

5) Zeitlich animierte Transformationen wie Rotationen (lgl_RotationAnimationNode) werden analog hinzugefügt:

double w = ...; // angular velocity
vec3 a = ...; // rotation axis
... ->add(new lgl_RotationAnimationNode(w, a))-> ...

6) Unter den Transformations-Knoten, die sich jeweils auf ihre Kinder und Kindeskinder auswirken, werden Geometrie-Knoten eingefügt. Diese kapseln jeweils einen VBO (lglVBO *):

lglVBO *vbo = ...;
... ->add(new lgl_GeometryNode(vbo));

7) Farbe wird mittels eines Farb-Knotens (lgl_ColorNode) hinzugefügt. Diese Farbe wirkt sich auf alle Geometrie-Knoten, die Kinder oder Kindeskinder sind, aus:

... ->add(new lgl_ColorNode(vec3(...))-> ...

8) Kamerapose und Perspektive wird mittel eines Kamera-Knotens (lgl_Camera) der Szene hinzugefügt:

root->add(new lgl_CameraNode(...));

9) Abschließend kann der Szenengraph gerendert werden, indem man an der Wurzel die Methode renderSceneGraph(dt) aufruft mit dt = 1/FPS:

root->renderSceneGraph(dt);

Diese Methode veranlasst einen Tiefenabstieg des gesamten Szenengraphs, wobei alle VBOs der traversierten Geometrie-Knoten mit der jeweils aktuellen Transformation gerendert werden (Depth-First Render Traversal).

10) Wenn der Szenengraph (z.B. bei Programmende) nicht mehr benötigt wird, so gibt man den insgesamt belegten Speicher frei, indem man den Wurzelknoten löscht:

delete root;


Hierarchie Ebenen | | Szenengraph Implementierung

Options: