Computergrafik

Szenengraphtraversal Rechenbeispiel

Szenengraphtraversal Beispiel | | Szenengraphen

In der folgenden Blender-Szene ist eine Objekt-Hierarchie dargestellt, in der Translation, Rotation, uniforme Skalierung sowie die View-Transformation verwendet werden:

Blender-Projektdatei

Wir bauen die finale Transformation aus relativen Transformationen $T^{vonKoordinatensystem}_{zuKoordinatensystem}$ und absoluten Transformationen $M_{Koordinatensystem}$ auf.

Wir starten im Weltursprung:

$ M_{Welt} = I $

Vom Weltursprung aus bewegen wir uns nun 6 Einheiten entlang der Y-Achse an die Position der Basisplatte der Lokomotive $M_{Lok}$:

$ T^{Welt}_{Lok} = \left( \begin{array}{c c c c} 1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 6 \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 1 \end{array} \right) $$ M_{Lok} = M_{Welt} T^{Welt}_{Lok} $

Von der Basisplatte bewegen wir uns nun entweder zum ersten Rad $M_{Rad1}$ indem wir eine Verschiebung um 1,244 Einheiten entlang der X-Achse und −2,5 Einheiten entlang der Y-Achse, eine Rotation von 90 Grad ($\theta = \pi/2$) um die Y-Achse eine uniforme Skalierung s=0,156 modellieren:

$ T^{Lok}_{Rad1} = \left( \begin{array}{c c c c} s \cdot cos(\pi/2) & 0 & s \cdot sin(\pi/2) & 1,244 \\ 0 & s & 0 & -2,5 \\ -s \cdot sin(\pi/2) & 0 & s \cdot cos(\pi/2) & 0 \\ 0 & 0 & 0 & 1 \end{array} \right) $$ M_{Rad1} = M_{Lok} T^{Lok}_{Rad1} $

Oder wir bewegen uns von der Basisplatte zum zweiten Rad $M_{Rad2}$ indem wir eine Verschiebung um 1,244 Einheiten entlang der X-Achse und 2 Einheiten entlang der Y-Achse, eine Rotation von 90 Grad (Pi/2) um die Y-Achse eine uniforme Skalierung s=0,156 modellieren:

$ T^{Lok}_{Rad2} = \left( \begin{array}{c c c c} s \cdot cos(\pi/2) & 0 & s \cdot sin(\pi/2) & 1,244 \\ 0 & s & 0 & 2 \\ -s \cdot sin(\pi/2) & 0 & s \cdot cos(\pi/2) & 0 \\ 0 & 0 & 0 & 1 \end{array} \right) $$ M_{Rad1} = M_{Lok} T^{Lok}_{Rad2} $

Man bezeichnet die ausmultiplizierten Matrizen für die jeweiligen Objekte, z.B. $T^{Welt}_{Lok} T^{Lok}_{Rad1}$ für Rad1, auch als Model Matrix $M_{M}$!

Probe:

T_Lok = bpy.context.scene.objects['M_Lok'].matrix_local
T_Rad1 = bpy.context.scene.objects['M_Rad1'].matrix_local
T_Rad2 = bpy.context.scene.objects['M_Rad2'].matrix_local

M_Rad1 = T_Lok @ T_Rad1
M_Rad2 = T_Lok @ T_Rad2

print(M_Rad1)
<Matrix 4x4 ( 0.0000, 0.0000, 0.1563, 1.2449)
            ( 0.0000, 0.1563, 0.0000, 3.5000)
            (-0.1563, 0.0000, 0.0000, 0.0000)
            ( 0.0000, 0.0000, 0.0000, 1.0000)>

print(bpy.context.scene.objects['M_Rad1'].matrix_world)
<Matrix 4x4 ( 0.0000, 0.0000, 0.1563, 1.2449)
            ( 0.0000, 0.1563, 0.0000, 3.5000)
            (-0.1563, 0.0000, 0.0000, 0.0000)
            ( 0.0000, 0.0000, 0.0000, 1.0000)>

Abschließend beschreiben wir die Kamera-Transformation durch eine Verschiebung um −7 Einheiten entlang der Y-Achse und 1 Einheit entlang der Z-Achse sowie eine Rotation um 90 Grad ($\theta = \pi/2$) um die X-Achse wie folgt:

$ T^{Welt}_{Kamera} = \left( \begin{array}{c c c c} 1 & 0 & 0 & 0 \\ 0 & cos(\pi/2) & -sin(\pi/2) & -7 \\ 0 & sin(\pi/2) & cos(\pi/2) & 1 \\ 0 & 0 & 0 & 1 \end{array} \right) $

Problem: Wir benötigen die umgekehrte Transformation - von Kamerakoordinaten zu Weltkoordinaten, denn wir benötigen die Vertices nicht relativ zum zum Ursprung der Weltkoordinaten sondern relativ zum Ursprung der Kamerakoordinaten, d.h. relativ zum Augpunkt. Man nennt diese Matrix $T^{Kamera}_{Welt} = (T^{Welt}_{Kamera})^{-1}$ auch die View Matrix $M_V$

$ T^{Kamera}_{Welt} = \left( \begin{array}{c c c c} 1 & 0 & 0 & 0 \\ 0 & cos(\pi/2) & sin(\pi/2) & -1 \\ 0 & -sin(\pi/2) & cos(\pi/2) & -7 \\ 0 & 0 & 0 & 1 \end{array} \right) $

Die Gesamttransformation für das Rad1-Objekt lautet wie folgt:

Gesamtmatrix $ M_{MV} = T^{Kamera}_{Welt} \cdot T^{Welt}_{Lok} \cdot T^{Lok}_{Rad1} $

Man nennt diese Matrix auch die Model-View Matrix $M_{MV}$, die unsere Szene nun aus Kamerasicht beschreibt:

Probe:

M_V = bpy.context.scene.objects['Camera'].matrix_world.inverted()

M_MV = M_V @ M_Rad1

print(M_MV)
<Matrix 4x4 ( 0.0000,  0.0000,  0.1563,   1.2449)
            (-0.1563, -0.0000,  0.0000,  -1.0000)
            ( 0.0000, -0.1563, -0.0000, -10.5000)
            ( 0.0000,  0.0000,  0.0000,   1.0000)>

Laut Rechnung ist das Rad1 also 10.5 Einheiten von der Kamera entfernt. Die Kamera ist bei Y = −7 und das Rad1 ist bei Y = 3.5 → Rechnung korrekt!


Ein jedes Objekt des Szenengraphen kann nun beliebig transformiert werden, indem die Gesamttransformation (von der GPU) auf jeden Vertex angewendet wird:

$ \vec{v}' = M_{MV} \cdot \vec{v} $

Hinweis: Auch die perspektivische Projektion kann als Transformation dargestellt werden, was aus Gründen der Einfachheit hier nicht berücksichtigt wurde. Diese Transformation kommt normalerweise als letztes. Wo muss sie also hinzugefügt werden?

Szenengraphtraversal Beispiel | | Szenengraphen

Options: