Three.js Triangle Barycentric Coordinates Explained
This article explains how the Triangle class in Three.js
calculates barycentric coordinates using the getBarycoord
method. It details the underlying mathematical formulas, specifically
the algebraic projection method based on Cramer’s Rule, and explains how
to interpret the resulting vector coordinates in your 3D
applications.
In Three.js, the Triangle.getBarycoord(point, target)
method is used to determine the barycentric coordinates of a specific 3D
point relative to the triangle’s three vertices: \(A\), \(B\), and \(C\). Barycentric coordinates represent any
point \(P\) inside or near a triangle
as a weighted average of the triangle’s vertices, defined as:
\[P = w_A \cdot A + w_B \cdot B + w_C \cdot C\]
where the weights \(w_A\), \(w_B\), and \(w_C\) sum to \(1\).
The Mathematical Algorithm
To compute these weights, Three.js uses an efficient vector-based formulation of Cramer’s Rule. This method projects the point \(P\) onto the plane of the triangle and solves a system of linear equations using dot products.
First, Three.js defines three helper vectors relative to vertex \(A\): * \(\vec{v_0} = C - A\) * \(\vec{v_1} = B - A\) * \(\vec{v_2} = P - A\)
Next, it calculates five dot products from these vectors: * \(dot_{00} = \vec{v_0} \cdot \vec{v_0}\) * \(dot_{01} = \vec{v_0} \cdot \vec{v_1}\) * \(dot_{02} = \vec{v_0} \cdot \vec{v_2}\) * \(dot_{11} = \vec{v_1} \cdot \vec{v_1}\) * \(dot_{12} = \vec{v_1} \cdot \vec{v_2}\)
Using these dot products, the algorithm computes a common denominator (\(denom\)), which represents the scaled area of the triangle: \[denom = dot_{00} \cdot dot_{11} - dot_{01} \cdot dot_{01}\]
If the denominator is \(0\), it
indicates that the triangle is degenerate (collinear vertices or a
single point). In this case, Three.js returns a fallback vector
(-2, -1, -1) to signal an invalid input.
If the denominator is valid, the algorithm computes two intermediate variables, \(u\) and \(v\): \[u = \frac{dot_{11} \cdot dot_{02} - dot_{01} \cdot dot_{12}}{denom}\] \[v = \frac{dot_{00} \cdot dot_{12} - dot_{01} \cdot dot_{02}}{denom}\]
Output Mapping
The final barycentric coordinates must sum to \(1\). Three.js maps the calculated variables
\(u\) and \(v\) to the target Vector3
\((x, y, z)\) representing the weights
for vertices \(A\), \(B\), and \(C\) respectively:
- \(w_A\) (stored in
target.x) \(= 1 - u - v\) - \(w_B\) (stored in
target.y) \(= v\) - \(w_C\) (stored in
target.z) \(= u\)
If the point \(P\) lies strictly inside the triangle, all three returned values will be between \(0\) and \(1\). If the point is outside the triangle, at least one of the values will be negative.