// djm pooled from above /// <summary> /// Solve a line segment using barycentric coordinates. /// </summary> public void Solve2() { // 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 Vec2 w1 = m_v1.W; Vec2 w2 = m_v2.W; e12.Set(w2).SubLocal(w1); // w1 region float d12_2 = -Vec2.Dot(w1, e12); if (d12_2 <= 0.0f) { // a2 <= 0, so we clamp it to 0 m_v1.A = 1.0f; Count = 1; return; } // w2 region float d12_1 = Vec2.Dot(w2, e12); if (d12_1 <= 0.0f) { // a1 <= 0, so we clamp it to 0 m_v2.A = 1.0f; Count = 1; m_v1.Set(m_v2); return; } // Must be in e12 region. float inv_d12 = 1.0f / (d12_1 + d12_2); m_v1.A = d12_1 * inv_d12; m_v2.A = d12_2 * inv_d12; Count = 2; }
/// <summary> /// Solve a line segment using barycentric coordinates.<br/> /// Possible regions:<br/> /// - points[2]<br/> /// - edge points[0]-points[2]<br/> /// - edge points[1]-points[2]<br/> /// - inside the triangle /// </summary> public void Solve3() { w1.Set(m_v1.W); w2.Set(m_v2.W); w3.Set(m_v3.W); // Edge12 // [1 1 ][a1] = [1] // [w1.e12 w2.e12][a2] = [0] // a3 = 0 e12.Set(w2).SubLocal(w1); float w1e12 = Vec2.Dot(w1, e12); float w2e12 = Vec2.Dot(w2, e12); float d12_1 = w2e12; float d12_2 = -w1e12; // Edge13 // [1 1 ][a1] = [1] // [w1.e13 w3.e13][a3] = [0] // a2 = 0 e13.Set(w3).SubLocal(w1); float w1e13 = Vec2.Dot(w1, e13); float w3e13 = Vec2.Dot(w3, e13); float d13_1 = w3e13; float d13_2 = -w1e13; // Edge23 // [1 1 ][a2] = [1] // [w2.e23 w3.e23][a3] = [0] // a1 = 0 e23.Set(w3).SubLocal(w2); float w2e23 = Vec2.Dot(w2, e23); float w3e23 = Vec2.Dot(w3, e23); float d23_1 = w3e23; float d23_2 = -w2e23; // Triangle123 float n123 = Vec2.Cross(e12, e13); float d123_1 = n123 * Vec2.Cross(w2, w3); float d123_2 = n123 * Vec2.Cross(w3, w1); float d123_3 = n123 * Vec2.Cross(w1, w2); // w1 region if (d12_2 <= 0.0f && d13_2 <= 0.0f) { m_v1.A = 1.0f; Count = 1; return; } // e12 if (d12_1 > 0.0f && d12_2 > 0.0f && d123_3 <= 0.0f) { float inv_d12 = 1.0f / (d12_1 + d12_2); m_v1.A = d12_1 * inv_d12; m_v2.A = d12_2 * inv_d12; Count = 2; return; } // e13 if (d13_1 > 0.0f && d13_2 > 0.0f && d123_2 <= 0.0f) { float inv_d13 = 1.0f / (d13_1 + d13_2); m_v1.A = d13_1 * inv_d13; m_v3.A = d13_2 * inv_d13; Count = 2; m_v2.Set(m_v3); return; } // w2 region if (d12_1 <= 0.0f && d23_2 <= 0.0f) { m_v2.A = 1.0f; Count = 1; m_v1.Set(m_v2); return; } // w3 region if (d13_1 <= 0.0f && d23_1 <= 0.0f) { m_v3.A = 1.0f; Count = 1; m_v1.Set(m_v3); return; } // e23 if (d23_1 > 0.0f && d23_2 > 0.0f && d123_1 <= 0.0f) { float inv_d23 = 1.0f / (d23_1 + d23_2); m_v2.A = d23_1 * inv_d23; m_v3.A = d23_2 * inv_d23; Count = 2; m_v1.Set(m_v3); return; } // Must be in triangle123 float inv_d123 = 1.0f / (d123_1 + d123_2 + d123_3); m_v1.A = d123_1 * inv_d123; m_v2.A = d123_2 * inv_d123; m_v3.A = d123_3 * inv_d123; Count = 3; }