// Solve a line segment using barycentric coordinates. // // p = a1 * w1 + a2 * w2 // a1 + a2 = 1 // // The vector from the origin to the closest point on the line is // perpendicular to the line. // e12 = w2 - w1 // dot(p, e) = 0 // a1 * dot(w1, e) + a2 * dot(w2, e) = 0 // // 2-by-2 linear system // [1 1 ][a1] = [1] // [w1.e12 w2.e12][a2] = [0] // // Define // d12_1 = dot(w2, e12) // d12_2 = -dot(w1, e12) // d12 = d12_1 + d12_2 // // Solution // a1 = d12_1 / d12 // a2 = d12_2 / d12 /// <summary> /// Solves the 2 /// </summary> internal void Solve2() { Vec2 w1 = V1.W; Vec2 w2 = V2.W; Vec2 e12 = w2 - w1; // w1 region float d122 = -Vec2.Dot(w1, e12); if (d122 <= 0.0f) { // a2 <= 0, so we clamp it to 0 V1.A = 1.0f; Count = 1; return; } // w2 region float d121 = Vec2.Dot(w2, e12); if (d121 <= 0.0f) { // a1 <= 0, so we clamp it to 0 V2.A = 1.0f; Count = 1; V1 = V2; return; } // Must be in e12 region. float invD12 = 1.0f / (d121 + d122); V1.A = d121 * invD12; V2.A = d122 * invD12; Count = 2; }
// Possible regions: // - points[2] // - edge points[0]-points[2] // - edge points[1]-points[2] // - inside the triangle /// <summary> /// Solves the 3 /// </summary> internal void Solve3() { Vec2 w1 = V1.W; Vec2 w2 = V2.W; Vec2 w3 = V3.W; // Edge12 // [1 1 ][a1] = [1] // [w1.e12 w2.e12][a2] = [0] // a3 = 0 Vec2 e12 = w2 - w1; float w1E12 = Vec2.Dot(w1, e12); float w2E12 = Vec2.Dot(w2, e12); float d121 = w2E12; float d122 = -w1E12; // Edge13 // [1 1 ][a1] = [1] // [w1.e13 w3.e13][a3] = [0] // a2 = 0 Vec2 e13 = w3 - w1; float w1E13 = Vec2.Dot(w1, e13); float w3E13 = Vec2.Dot(w3, e13); float d131 = w3E13; float d132 = -w1E13; // Edge23 // [1 1 ][a2] = [1] // [w2.e23 w3.e23][a3] = [0] // a1 = 0 Vec2 e23 = w3 - w2; float w2E23 = Vec2.Dot(w2, e23); float w3E23 = Vec2.Dot(w3, e23); float d231 = w3E23; float d232 = -w2E23; // Triangle123 float n123 = Vec2.Cross(e12, e13); float d1231 = n123 * Vec2.Cross(w2, w3); float d1232 = n123 * Vec2.Cross(w3, w1); float d1233 = n123 * Vec2.Cross(w1, w2); // w1 region if (d122 <= 0.0f && d132 <= 0.0f) { V1.A = 1.0f; Count = 1; return; } // e12 if (d121 > 0.0f && d122 > 0.0f && d1233 <= 0.0f) { float invD12 = 1.0f / (d121 + d122); V1.A = d121 * invD12; V2.A = d121 * invD12; Count = 2; return; } // e13 if (d131 > 0.0f && d132 > 0.0f && d1232 <= 0.0f) { float invD13 = 1.0f / (d131 + d132); V1.A = d131 * invD13; V3.A = d132 * invD13; Count = 2; V2 = V3; return; } // w2 region if (d121 <= 0.0f && d232 <= 0.0f) { V2.A = 1.0f; Count = 1; V1 = V2; return; } // w3 region if (d131 <= 0.0f && d231 <= 0.0f) { V3.A = 1.0f; Count = 1; V1 = V3; return; } // e23 if (d231 > 0.0f && d232 > 0.0f && d1231 <= 0.0f) { float invD23 = 1.0f / (d231 + d232); V2.A = d231 * invD23; V3.A = d232 * invD23; Count = 2; V1 = V3; return; } // Must be in triangle123 float invD123 = 1.0f / (d1231 + d1232 + d1233); V1.A = d1231 * invD123; V2.A = d1232 * invD123; V3.A = d1233 * invD123; Count = 3; }