Getting the Equation Of A Plane Right When You Already Have Three Points
The most common reason people get stuck on this isn't the math itself, it's that they try to memorize the final vector form without understanding what happens when you actually compute it by hand. I spent a semester watching students plug points into dot products and then get completely wrong answers because they never verified that their normal vector was actually perpendicular to the plane. Here's how you do it without losing your mind. Start with three non-collinear points. Let's say you have A = (1, 2, -1), B = (3, 0, 2), and C = (-1, 4, 3). The first step is creating two direction vectors that lie on the plane. You get these by subtracting coordinates: AB = B - A = (2, -2, 3) and AC = C - A = (-2, 2, 4). Keep those numbers precise. Rounding early is where everything falls apart. The normal vector to the plane is the cross product of those two direction vectors. Cross product of AB and AC gives you (a, b, c) where:
a = (-2)(4) - (3)(2) = -8 - 6 = -14 b = (3)(-2) - (2)(4) = -6 - 8 = -14 c = (2)(2) - (-2)(-2) = 4 - 4 = 0
So the normal vector is n = (-14, -14, 0). You can simplify this to (-1, -1, 0) since any scalar multiple works, but don't bother simplifying if you're doing this under time pressure. Just keep the raw values and move forward. The scalar form of the Equation Of A Plane is ax + by + cz = d, where (a, b, c) is your normal vector and d = ax + by + cz for any point on the plane. Using point A (1, 2, -1): d = (-14)(1) + (-14)(2) + (0)(-1) = -14 - 28 + 0 = -42. The equation is -14x - 14y = -42, which reduces to x + y = 3. I ran into a situation last year where a client gave me three points that were nearly collinear — the cross product produced components on the order of 10^-7 due to floating-point rounding. The resulting plane equation was numerically unstable and every downstream calculation, from point-to-plane distance to intersection testing, came back garbage. The workaround was to check the magnitude of your cross product before proceeding. If it's below some threshold relative to the input scale, the points are effectively collinear and there is no unique plane. In that case, I fell back to a least-squares plane fit using all available data points rather than forcing a solution from three unreliable coordinates.
Get the Full Details

Here's something most textbooks don't emphasize enough: the vector form r · n = d is not always the most useful representation, even though it's the one everyone learns first. When you're doing computational work, the parametric form r = A + s(AB) + t(AC) is significantly more practical. It lets you generate any point on the plane directly, which is essential for ray tracing, collision detection, and mesh generation. The normal form is great for distance queries. The parametric form is great for surface sampling. Knowing when to convert between them saves you from writing completely unnecessary conversion code. Another counter-intuitive detail that trips people up: the order of subtraction in the cross product matters for the direction of the normal, but it does not change the plane. n × m gives the opposite normal from m × n, and both are equally valid. The scalar equation just flips signs on both sides. I've seen engineers waste hours debugging sign errors in their rendering pipeline only to discover the normal was pointing inward instead of outward, which only matters for lighting calculations, not for the geometry itself. If you need to find the distance from a point P = (x, y, z) to the plane ax + by + cz + d = 0, the formula is |ax + by + cz + d| / (a² + b² + c²). This comes directly from projecting the vector from any point on the plane to P onto the normal direction. It's a single-line calculation once you have the plane in standard form.
The main bottleneck with this approach is that it breaks down entirely when the three points are collinear. There's no workaround that makes the math valid — a line doesn't define a unique plane, it defines infinitely many. Your only options are to get better input data, add a fourth point, or switch to a best-fit approach. I've seen teams ship geometry code that silently produced random planes from collinear inputs because they never validated their point set, and the bugs showed up months later as visual artifacts in production. For most practical purposes, if you're implementing this yourself, I'd recommend a direct implementation rather than pulling in a library. The full algorithm is maybe twenty lines of code and a library adds an abstraction layer that obscures exactly where numerical precision is being lost. The only time I reach for a library is when working in high dimensions or when the input data is noisy and needs regularization.