Transform Hierarchies

A game character is not one rigid lump. A hand is attached to a forearm, the forearm to an upper arm, the arm to a torso, the torso to the world. When the torso turns, the whole arm swings with it — and the hand, dangling at the end of the chain, swings furthest of all. You never want to move the hand by hand. You move the torso, and the engine carries everything downstream for free. That bookkeeping is the scene graph: a tree of objects, each one parented to the one above it.

The trick is that every node stores its transform relative to its parent, not relative to the world. The hand knows only "I sit a little out along the forearm"; it has no idea where it is in the level. Turning that humble local fact into a world position is the one computation a scene graph exists to do.

Local and world: deriving the chain

Give each node two transforms. Its local transform L places it in its parent's frame. Its world transform W places it in the level. We want a rule that produces W from the locals, derived one composition at a time. We use 4\times 4 matrices so a single matrix can carry both rotation and translation (a vertex rides as (x, y, z, 1)).

Step 1 — the root is its own world. The root node has no parent, so its local frame is the world frame. Nothing to compose:

W_{\text{root}} = L_{\text{root}}.

Step 2 — a child sits in its parent's frame. The torso's local transform L_{\text{torso}} says where the torso is inside the root's frame. To express a torso-local point in the world, first place it in the root's frame with L_{\text{torso}}, then carry that into the world with the root's world matrix. Composition applies right-to-left — the first transform sits nearest the vector — so:

W_{\text{torso}} = W_{\text{root}} \, L_{\text{torso}}.

Step 3 — recurse down one more link. The arm hangs off the torso, so the identical argument with the torso playing the role of parent gives:

W_{\text{arm}} = W_{\text{torso}} \, L_{\text{arm}}.

Step 4 — read off the general rule. Nothing in Steps 2–3 depended on the names; every node obeys the same one-line recurrence. For any node with parent p:

W_{\text{node}} = W_{p} \, L_{\text{node}}.

Step 5 — unroll it into a chain. Substitute each parent's world matrix back in, all the way to the root. The hand's world transform is the product of every local transform from the root down to the hand:

W_{\text{hand}} = L_{\text{root}} \, L_{\text{torso}} \, L_{\text{arm}} \, L_{\text{hand}}.

Step 6 — push a vertex through. A vertex authored in the hand's local space (the modelling frame the artist drew it in) becomes a world vertex by multiplying through that same chain — local \to world in one matrix product:

\vec{v}_{\text{world}} = W_{\text{hand}} \, \vec{v}_{\text{local}} = L_{\text{root}} \, L_{\text{torso}} \, L_{\text{arm}} \, L_{\text{hand}} \, \vec{v}_{\text{local}}.

And here is the payoff hiding in Step 4: change one parent's transform and every W below it is recomputed from the new value automatically. Rotate the torso and the arm, hand, and fingertip all swing — you edited one matrix, the recurrence did the rest.

In a scene graph (a tree of parented objects):

Three nodes, parented in a line: tank body \to turret \to barrel tip. The body drives across the map; the turret is parented to it, so it rides along without anyone touching its local transform. The gunner spins the turret — that edits only L_{\text{turret}} — and the barrel tip, parented to the turret, sweeps with it. The muzzle's world position, where you spawn the shell, is

W_{\text{tip}} = W_{\text{body}} \, L_{\text{turret}} \, L_{\text{barrel}},

recomputed every frame from whatever the body and turret are currently doing. The very same pattern is a humanoid skeleton: pelvis \to spine \to shoulder \to elbow \to wrist. Animators key joint local rotations; the recurrence turns that into where each bone lands in the world. One product per bone, root to fingertip.

Rotate the parent, watch the child follow

A two-link rig: a parent arm pinned at the origin, and a child hand pinned to the far end of the arm with its own local offset and spin. Drag the parent rotation slider — you are editing only L_{\text{parent}} — and the hand follows automatically, because its world transform is W_{\text{hand}} = W_{\text{arm}}\,L_{\text{hand}}. Then add some hand spin to edit L_{\text{hand}}: the hand turns about its own joint without disturbing the arm. Parents drag children; children move alone.