Floors, walls, ceilings, the still surface of water — the flat world of a game is made of
planes.
Firing a
ray
at one is the cheapest intersection in the whole tracer: where the
sphere
gave us a quadratic, the plane gives us a single linear equation, solved with one
division. No discriminant, no \pm — just one
t.
From plane equation to one division, line by line
A plane is fixed by a normal n and a constant
d: a point P lies on it exactly when its
projection onto the normal equals d.
n\cdot P = d.
Step 1 — substitute the ray. A point is on the plane when it satisfies this,
and on the ray when it equals O + tD. Demanding both, put the ray in
for P:
n\cdot(O + tD) = d.
Step 2 — distribute the dot product. The dot product is linear, so it splits
the sum and pulls the scalar t out:
n\cdot O + t\,(n\cdot D) = d.
Step 3 — isolate the only unknown. Everything except
t is a known number. Move n\cdot O across
and divide by n\cdot D:
t = \frac{d - n\cdot O}{n\cdot D}.
That is the entire intersection — one dot product on top, one on the bottom, one division.
Step 4 — watch for n\cdot D = 0: the parallel case.
If the ray's direction is perpendicular to the normal, the ray runs flat along the
plane and the denominator vanishes. There is no single crossing point: either the ray never
meets the plane (it floats above or below it forever) or it lies entirely within it. Geometrically
n\cdot D = 0 means the ray is parallel to the surface —
the one case the formula refuses to answer, so we test for it first and report "no hit".
n\cdot D = 0 \quad\Longrightarrow\quad \text{ray parallel to the plane — no intersection.}
Step 5 — reject hits behind the origin. A solved
t < 0 sits behind the camera — the plane is in the rear-view
mirror, not in front of the ray. Keep it only when t \ge 0.
Step 6 — recover the hit point. As always, feed the surviving
t back into the ray:
P_{\text{hit}} = O + t\,D.
For a ray P(t) = O + tD and a plane
n\cdot P = d:
-
One linear solve — the hit parameter is
t = \dfrac{d - n\cdot O}{n\cdot D}.
-
Parallel ⇒ no hit — when n\cdot D = 0 the ray is
parallel to the plane; there is no single crossing (test this first).
-
Forward only — keep the hit when t \ge 0;
t < 0 is behind the origin.
-
Hit point — the surface point is
P_{\text{hit}} = O + t\,D.
The formula intersects an infinite plane: a sheet of glass stretching forever in
every direction. Solving for t always finds the crossing (unless
the ray is parallel), even if that crossing is a mile off the edge of the actual floor tile.
Real geometry is bounded — a floor, a quad, a window. So a ray–plane hit is usually only
step one: compute P_{\text{hit}} = O + tD on the infinite plane,
then test whether that point lies inside the bounded patch. For an
axis-aligned rectangle that is a pair of range checks on two coordinates; for an arbitrary
quad or
triangle
it's a containment test in the plane. The plane gives you the where on the infinite
sheet cheaply; the boundary test decides whether you actually landed on the surface or
shot past its edge into the void.