123 lines
3.2 KiB
C++
123 lines
3.2 KiB
C++
/* -----------------------------------------------------------------------------
|
|
GSFramework
|
|
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
|
----------------------------------------------------------------------------- */
|
|
|
|
|
|
#include <cmath>
|
|
#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
|