Games live on perpendicular vectors: which way a wall faces, which way is
"out", which way the light should bounce. The
cross product
is the machine that builds them. Feed it two vectors and it returns a third that is
perpendicular to both, with a length equal to the area of the parallelogram they span:
\lVert \vec{a} \times \vec{b}\rVert = \lVert\vec{a}\rVert\,\lVert\vec{b}\rVert\,\sin\theta, \qquad (\vec{a}\times\vec{b}) \perp \vec{a}, \quad (\vec{a}\times\vec{b}) \perp \vec{b}.
Perpendicularity is the whole point. Its killer application in graphics is the
surface normal — the arrow sticking straight out of a triangle — which we
now build line by line.
The triangle normal, line by line
A triangle is three points A, B, C. We want the direction it
faces: an arrow perpendicular to the whole flat triangle.
Step 1 — two edges from one corner. Subtract points to get two edge
vectors lying in the triangle's plane (point − point = vector):
\vec{e}_1 = B - A, \qquad \vec{e}_2 = C - A.
Step 2 — cross them. Both edges lie in the triangle, so anything
perpendicular to both is perpendicular to the triangle. That is exactly what the cross
product hands back:
\vec{n} = \vec{e}_1 \times \vec{e}_2 = (B - A)\times(C - A).
Step 3 — normalise to a pure direction. Its raw length is the parallelogram
area (twice the triangle's), which we don't want polluting a direction. Divide by
the length to get a unit normal — see
why the length is the area:
\hat{n} = \frac{\vec{n}}{\lVert \vec{n}\rVert}.
Step 4 — the winding order picks the side. Because
\vec{a}\times\vec{b} = -(\vec{b}\times\vec{a}), swapping
B and C flips
\hat{n} to the other side. So the order you list the
vertices — the winding order, clockwise or counter-clockwise — decides which
face is "out". Every engine fixes one convention (usually counter-clockwise = front) and
sticks to it religiously.
(B-A)\times(C-A) = -\,\big[(C-A)\times(B-A)\big] \quad\Rightarrow\quad \text{vertex order } \Leftrightarrow \text{ which way is out.}
For \vec{a}, \vec{b}\in\mathbb{R}^3 at angle
\theta:
-
Perpendicular, length = area —
\vec{a}\times\vec{b} is perpendicular to both, with
\lVert\vec{a}\times\vec{b}\rVert = \lVert\vec{a}\rVert\lVert\vec{b}\rVert\sin\theta,
the parallelogram area.
-
Triangle normal — for a triangle
A, B, C,
\vec{n} = (B-A)\times(C-A) is perpendicular to the triangle.
-
Normalise — the unit normal is
\hat{n} = \vec{n}/\lVert\vec{n}\rVert, a pure direction.
-
Winding sets the direction — swapping two vertices negates
\hat{n}, so the vertex order chooses which face is "out".
Half of every closed model faces away from the camera at any instant — the far side of a
sphere, the back of a wall. Drawing it is wasted work, so the GPU culls it.
The test is a dot product against the normal. Let \hat{n} be the
triangle's outward normal and \vec{v} the direction from the
triangle toward the camera. The face points toward the camera only when
\vec{v}\cdot\hat{n} > 0 \quad (\text{visible}), \qquad \vec{v}\cdot\hat{n} \le 0 \quad (\text{facing away — skip it}).
One cross product to build the normal, one dot product to test it, and the engine throws
away roughly half the triangles before shading a single pixel. The same
\hat{n} then drives lighting
(\max(0,\hat{n}\cdot\hat{L})) and collision response ("push the
player back out along the normal"). It is the most reused vector in the pipeline — and it
all starts with (B-A)\times(C-A).