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:

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.