Files
FC1/CryCommon/Cry_GeoDistance.h
romkazvo 34d6c5d489 123
2023-08-07 19:29:24 +08:00

137 lines
4.5 KiB
C++

//////////////////////////////////////////////////////////////////////
//
// Crytek Common Source code
//
// File:Cry_GeoDistance.h
// Description: Common distance-computations
//
// History:
// -March 15,2003: Created by Ivo Herzeg
//
//////////////////////////////////////////////////////////////////////
#ifndef CRYDISTANCE_H
#define CRYDISTANCE_H
#if _MSC_VER > 1000
# pragma once
#endif
#include <Cry_Geo.h>
namespace Distance {
/*!
* Distance: Origin_Triangle2D
* Calculate the closest distance of a triangle in XY-plane to the coordinate origin.
* it is assumed that the z-values of the triangle are all in the same plane.
* The function returns the 3d-position of the closest point on the triangle.
*
* Example:
* Vec3 result = Distance::Origin_Triangle2D( triangle );
*/
template<typename F>
ILINE Vec3_tpl<F> Origin_Triangle2D( const Triangle_tpl<F>& t ) {
Vec3_tpl<F> a=t.v0;
Vec3_tpl<F> b=t.v1;
Vec3_tpl<F> c=t.v2;
//check if (0,0,0) is inside or in fron of any triangle sides.
u32 flag = ((a.x*(a.y-b.y)-a.y*(a.x-b.x))<0) | (((b.x*(b.y-c.y)-b.y*(b.x-c.x))<0)<<1) | (((c.x*(c.y-a.y)-c.y*(c.x-a.x))<0)<<2);
switch (flag) {
case 0: return Vec3_tpl<F>(0,0,a.z); //center is inside of triangle
case 1: if ((a|(b-a))>0.0f) flag=5; else if ((b|(a-b))>0.0f) flag=3; break;
case 2: if ((b|(c-b))>0.0f) flag=3; else if ((c|(b-c))>0.0f) flag=6; break;
case 3: return b; //vertex B is closed
case 4: if ((c|(a-c))>0.0f) flag=6; else if ((a|(c-a))>0.0f) flag=5; break;
case 5: return a; //vertex A is closed
case 6: return c; //vertex C is closed
}
//check again using expanded area
switch (flag) {
case 1: { Vec3_tpl<F> n=(b-a).GetNormalized(); return n*(-a|n)+a; }
case 2: { Vec3_tpl<F> n=(c-b).GetNormalized(); return n*(-b|n)+b; }
case 3: return b;
case 4: { Vec3_tpl<F> n=(a-c).GetNormalized(); return n*(-c|n)+c; }
case 5: return a;
case 6: return c;
}
return Vec3_tpl<F>(0,0,0);
}
/*!
* Distance: Point_Triangle
* Calculate the closest distance of a point to a triangle in 3d-space.
* The function returns the squared distance.
*
* Example:
* float result = Distance::Point_Triangle( pos, triangle );
*/
template<typename F>
ILINE F Point_Triangle( const Vec3_tpl<F>& p, const Triangle_tpl<F> &t ) {
//translate triangle into origin
Vec3_tpl<F> a=t.v0-p;
Vec3_tpl<F> b=t.v1-p;
Vec3_tpl<F> c=t.v2-p;
//transform triangle into XY-plane to simplify the test
Matrix33_tpl<F,3,1> r33=Matrix33_tpl<F,3,1>::CreateRotationV0( ((b-a)%(a-c)).GetNormalized() );
Vec3_tpl<F> h = Origin_Triangle2D(Triangle_tpl<F>(r33*a,r33*b,r33*c));
return (h|h); //return squared distance
}
/*!
* Distance: Point_Triangle
* Calculate the closest distance of a point to a triangle in 3d-space.
* The function returns the squared distance and the 3d-position of the
* closest point on the triangle.
*
* Example:
* float result = Distance::Point_Triangle( pos, triangle, output );
*/
template<typename F>
ILINE F Point_Triangle( const Vec3_tpl<F>& p, const Triangle_tpl<F> &t, Vec3_tpl<F>& output ) {
//translate triangle into origin
Vec3_tpl<F> a=t.v0-p;
Vec3_tpl<F> b=t.v1-p;
Vec3_tpl<F> c=t.v2-p;
//transform triangle into XY-plane to simplify the test
Matrix33_tpl<F,3,1> r33=Matrix33_tpl<F,3,1>::CreateRotationV0( ((b-a)%(a-c)).GetNormalized() );
Vec3_tpl<F> h = Origin_Triangle2D(Triangle_tpl<F>(r33*a,r33*b,r33*c));
output=h*r33+p;
return (h|h); //return squared distance
}
//----------------------------------------------------------------------------------
// Distance: Sphere_Triangle
//----------------------------------------------------------------------------------
// Calculate the closest distance of a sphere to a triangle in 3d-space.
// The function returns the squared distance. If sphere and triangle overlaps,
// the returned distance is 0
//
// Example:
// float result = Distance::Point_Triangle( pos, triangle );
//----------------------------------------------------------------------------------
template<typename F>
ILINE F Sphere_Triangle( const Sphere &s, const Triangle_tpl<F> &t ) {
F sqdistance = Distance::Point_Triangle(s.center,t) - (s.radius*s.radius);
if (sqdistance<0) sqdistance=0;
return sqdistance;
}
template<typename F>
ILINE F Sphere_Triangle( const Sphere &s, const Triangle_tpl<F> &t, Vec3_tpl<F>& output ) {
F sqdistance = Distance::Point_Triangle(s.center,t,output) - (s.radius*s.radius);
if (sqdistance<0) sqdistance=0;
return sqdistance;
}
} //namespace Distance
#endif