closestPointToPoint method
Implementation
Vector3 closestPointToPoint(Vector3 p, Vector3 target) {
final a = this.a, b = this.b, c = this.c;
double v, w;
// algorithm thanks to Real-Time Collision Detection by Christer Ericson,
// published by Morgan Kaufmann Publishers, (c) 2005 Elsevier Inc.,
// under the accompanying license; see chapter 5.1.5 for detailed explanation.
// basically, we're distinguishing which of the voronoi regions of the triangle
// the point lies in with the minimum amount of redundant computation.
_vab.sub2(b, a);
_vac.sub2(c, a);
_vap.sub2(p, a);
final d1 = _vab.dot(_vap);
final d2 = _vac.dot(_vap);
if (d1 <= 0 && d2 <= 0) {
// vertex region of A; barycentric coords (1, 0, 0)
return target.setFrom(a);
}
_vbp.sub2(p, b);
final d3 = _vab.dot(_vbp);
final d4 = _vac.dot(_vbp);
if (d3 >= 0 && d4 <= d3) {
// vertex region of B; barycentric coords (0, 1, 0)
return target.setFrom(b);
}
final vc = d1 * d4 - d3 * d2;
if (vc <= 0 && d1 >= 0 && d3 <= 0) {
v = d1 / (d1 - d3);
// edge region of AB; barycentric coords (1-v, v, 0)
return target.setFrom(a).addScaled(_vab, v);
}
_vcp.sub2(p, c);
final d5 = _vab.dot(_vcp);
final d6 = _vac.dot(_vcp);
if (d6 >= 0 && d5 <= d6) {
// vertex region of C; barycentric coords (0, 0, 1)
return target.setFrom(c);
}
final vb = d5 * d2 - d1 * d6;
if (vb <= 0 && d2 >= 0 && d6 <= 0) {
w = d2 / (d2 - d6);
// edge region of AC; barycentric coords (1-w, 0, w)
return target.setFrom(a).addScaled(_vac, w);
}
final va = d3 * d6 - d5 * d4;
if (va <= 0 && (d4 - d3) >= 0 && (d5 - d6) >= 0) {
_vbc.sub2(c, b);
w = (d4 - d3) / ((d4 - d3) + (d5 - d6));
// edge region of BC; barycentric coords (0, 1-w, w)
return target.setFrom(b).addScaled(_vbc, w); // edge region of BC
}
// face region
final denom = 1 / (va + vb + vc);
// u = va * denom
v = vb * denom;
w = vc * denom;
return target.setFrom(a).addScaled(_vab, v).addScaled(_vac, w);
}