[Math] fast way of computing barycentric coordinates explained

algorithmsbarycentric-coordinates

On this game dev stack exchange question someone puts forth a faster method of computing barycentric coordinates, but I don't understand it. I understand how barycentric interpolating works but how is he finding areas of triangles from dot products and stuff. Its the first answer

https://gamedev.stackexchange.com/questions/23743/whats-the-most-efficient-way-to-find-barycentric-coordinates

// Compute barycentric coordinates (u, v, w) for
// point p with respect to triangle (a, b, c)
void Barycentric(Point p, Point a, Point b, Point c, float &u, float &v, float &w)
{
    Vector v0 = b - a, v1 = c - a, v2 = p - a;
    float d00 = Dot(v0, v0);
    float d01 = Dot(v0, v1);
    float d11 = Dot(v1, v1);
    float d20 = Dot(v2, v0);
    float d21 = Dot(v2, v1);
    float denom = d00 * d11 - d01 * d01;
    v = (d11 * d20 - d01 * d21) / denom;
    w = (d00 * d21 - d01 * d20) / denom;
    u = 1.0f - v - w;
}

Best Answer

The barycentric coordinates $(u,v,w)$ for point $\vec{p}$ with respect to the triangle $(\vec{a},\vec{b},\vec{c})$ satisfies $$ u\vec{a}+v\vec{b}+w\vec{c} = \vec{p}, \hspace{1cm} u+v+w = 1.$$ Since $u = 1-v-w$, the first equation becomes $$ (1-v-w)\vec{a} + v\vec{b} + w\vec{c} = \vec{p}\implies v(\vec{b}-\vec{a}) + w(\vec{c}-\vec{a}) = \vec{p} - \vec{a}\implies v\vec{v_0} + w\vec{v_1} = \vec{v_2} $$ where $\vec{v_0} = \vec{b}-\vec{a}$, $\vec{v_1} = \vec{c}-\vec{a}$, and $\vec{v_2} = \vec{p}-\vec{a}$. For $0\le i,j\le 2$, define $d_{ij} = \vec{v_i}\cdot\vec{v_j}$. If we take the equation $v\vec{v_0} + w\vec{v_1} = \vec{v_2}$ and dot both sides by $\vec{v_0}$, we get $$ v\vec{v_0}\cdot\vec{v_0} + w\vec{v_0}\cdot\vec{v_1} = \vec{v_0}\cdot\vec{v_2}\implies d_{00}v+d_{01}w = d_{02}. $$ Similarly, dotting both sides by $\vec{v_1}$, we obtain $$ v\vec{v_1}\cdot\vec{v_0} + w\vec{v_1}\cdot\vec{v_1} = \vec{v_1}\cdot\vec{v_2} \implies d_{01}v+d_{11}w = d_{12}. $$ Thus we have a system of equations \begin{align} d_{00}v + d_{01}w &= d_{02} \\ d_{01}v + d_{11}w &= d_{12} \end{align} whose solution is $$ v = \frac{d_{11}d_{02}-d_{01}d_{12}}{d_{00}d_{11}-d_{01}^2} \hspace{1cm} w = \frac{d_{00}d_{12}-d_{01}d_{02}}{d_{00}d_{11}-d_{01}^2}. $$ This is the formula given in the code.

As a side note, the denominator $d_{00}d_{11}-d_{01}^2$ is always nonnegative by Cauchy-Schwarz, and it is always positive as long as the triangle is nondegenerate.