/* ----------------------------------------------------------------------------- GSFramework Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. ----------------------------------------------------------------------------- */ #include #include "geometry/geometric_tools.h" namespace GS { namespace Geometric { //------------------------------------------------------------------------------ float TriArea2D(float x0, float y0, float x1, float y1, float x2, float y2) { return (x0 - x1) * (y1 - y2) - (x1 - x2) * (y0 - y1); } //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ void Barycentric(const Vector4 &a, const Vector4 &b, const Vector4 &c, const Vector4 &p, float &u, float &v, float &w) { Vector4 m = (b - a).Cross(c - a); float nu, nv, ood; float x = fabs(m.x), y = fabs(m.y), z = fabs(m.z); if (x >= y && x >= z) { nu = TriArea2D(p.y, p.z, b.y, b.z, c.y, c.z); nv = TriArea2D(p.y, p.z, c.y, c.z, a.y, a.z); ood = 1.f / m.x; } else if (y >= x && y >= z) { nu = TriArea2D(p.x, p.z, b.x, b.z, c.x, c.z); nv = TriArea2D(p.x, p.z, c.x, c.z, a.x, a.z); ood = 1.f / -m.y; } else { nu = TriArea2D(p.x, p.y, b.x, b.y, c.x, c.y); nv = TriArea2D(p.x, p.y, c.x, c.y, a.x, a.y); ood = 1.f / m.z; } u = nu * ood; v = nv * ood; w = 1.f - u - v; } //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ bool LineIntersectPlane(const Vector4 &a, const Vector4 &v, const Vector4 &n, const Vector4 &p, float &t) { float k = v.Dot(n); if (Math::EqualZero(k)) return false; t = (p.Dot(n) - a.Dot(n)) / k; return true; } bool LineIntersectSphere(const Vector4 &a, const Vector4 &v, const Vector4 &c, float r, float t[2]) { Vector4 e = c - a; float k = e.Dot(v); float d = r * r - (e.Len2() - k * k); if (d < 0) return false; d = Math::Sqrt(d); if (t) { t[0] = k - d; t[1] = k + d; } return true; } float LineClosestPoint(const Vector4 &a, const Vector4 &b, const Vector4 &u, Vector4 *p) { Vector4 _u = u - a; Vector4 _v = b - a; float t = _u.Dot(_v) / _v.Dot(_v); if (p) p[0] = _v * t + a; return t; } bool LineClosestPointToLine(const Vector4 &a, const Vector4 &b, const Vector4 &la, const Vector4 &lb, float t[2]) { Vector4 u = b - a, v = lb - la; float ul2 = u.Len2(), vl2 = v.Len2(); float d = u.Dot(v), k = ul2 * vl2 - d * d; if (fabs(k) < 0.00000001f) return false; k = 1.f / k; float uv = d, du = (la - a).Dot(u), dv = (a - la).Dot(v); t[0] = (vl2 * du + uv * dv) * k; t[1] = (uv * du + ul2 * dv) * k; return true; } //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ float SegmentClosestPoint(const Vector4 &a, const Vector4 &b, const Vector4 &u, Vector4 *p) { Vector4 _u = u - a, _v = b - a; float t = Types::Clamp(_u.Dot(_v) / _v.Dot(_v)); if (p) p[0] = _v * t + a; return t; } //------------------------------------------------------------------------------ } // Geometric } // GS