Raytracing, Ray-Plane Testing

5 days ago 2

A Ray is defined as:

\(\enclose{circle}[mathcolor="white"]{\color{white}{1}} \;\;\) \(P = P_0 + t * D\)

A Plane is defined as:

\(\enclose{circle}[mathcolor="white"]{\color{white}{2}} \;\;\) \(P \cdot N - C = 0\)

This formula is known as Hesse Normal Form. The symbols are interpreted as follows:

SymbolInterpretation
\(P_0\)ray origin
\(D\)ray direction (unit vector)
\(N\)plane normal (unit vector)
\(C\)plane distance from axis origin

Substituting \(P\) in \(\enclose{circle}[mathcolor="white"]{\color{white}{2}}\) from \(\enclose{circle}[mathcolor="white"]{\color{white}{1}}\):

\[(P_0 + t * D) \cdot N - C = 0\] \[(P_0 \cdot N) + t * (D \cdot N) - C = 0\] \[P_0 \cdot N - C = -t * (D \cdot N)\]

Solving for \(t\):

\(\enclose{circle}[mathcolor="white"]{\color{white}{3}} \;\;\) \(t = -\frac{(P_0 \cdot N - C)}{D \cdot N}\)

The ray is parallel to the plane and no intersection point exists if:

\[(D \cdot N) = 0\]

If \(t\) is negative it means that the ray intersects the plane behind the ray’s origin point, at the opposite direction. Otherwise, there is a single intersection point at position \(P\) with:

\[P = P_0 + t * D\]

01

Note the formula to calculate \(t\) can be manipulated a bit further to optimize the implementation.

Representing the plane distance as a dot product of a point \(X\) with the plane normal:

\[C = X \cdot N\]

Therefore:

\[-(P_0 \cdot N - C) = C - P_0 \cdot N = X \cdot N - P_0 \cdot N = (X - P_0) \cdot N\]

Substituting in \(\enclose{circle}[mathcolor="white"]{\color{white}{3}}\):

\[t = \frac{(X - P_0) \cdot N}{D \cdot N}\]

bool Plane::intersection(const Ray &ray, HitRecord* i_info) const { // check if the ray is travelling parallel to the plane. // if the ray is in the plane then we ignore it. double n_dot_dir = dot(normal, ray.direction); if (fabs(n_dot_dir) < EPSILON) return false; Vector3f v = normal * distance; Vector3f vorigin = v - ray.origin; double n_dot_vo = dot(vorigin, normal); double t = n_dot_vo / n_dot_dir; if (t < EPSILON) return false; if (i_info) { i_info->t = t; i_info->point = ray.origin + ray.direction * t; i_info->normal = normal; } return true; }
Read Entire Article