////////////////////////////////////////////////////////////////////// // // 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 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 ILINE Vec3_tpl Origin_Triangle2D( const Triangle_tpl& t ) { Vec3_tpl a=t.v0; Vec3_tpl b=t.v1; Vec3_tpl 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(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 n=(b-a).GetNormalized(); return n*(-a|n)+a; } case 2: { Vec3_tpl n=(c-b).GetNormalized(); return n*(-b|n)+b; } case 3: return b; case 4: { Vec3_tpl n=(a-c).GetNormalized(); return n*(-c|n)+c; } case 5: return a; case 6: return c; } return Vec3_tpl(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 ILINE F Point_Triangle( const Vec3_tpl& p, const Triangle_tpl &t ) { //translate triangle into origin Vec3_tpl a=t.v0-p; Vec3_tpl b=t.v1-p; Vec3_tpl c=t.v2-p; //transform triangle into XY-plane to simplify the test Matrix33_tpl r33=Matrix33_tpl::CreateRotationV0( ((b-a)%(a-c)).GetNormalized() ); Vec3_tpl h = Origin_Triangle2D(Triangle_tpl(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 ILINE F Point_Triangle( const Vec3_tpl& p, const Triangle_tpl &t, Vec3_tpl& output ) { //translate triangle into origin Vec3_tpl a=t.v0-p; Vec3_tpl b=t.v1-p; Vec3_tpl c=t.v2-p; //transform triangle into XY-plane to simplify the test Matrix33_tpl r33=Matrix33_tpl::CreateRotationV0( ((b-a)%(a-c)).GetNormalized() ); Vec3_tpl h = Origin_Triangle2D(Triangle_tpl(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 ILINE F Sphere_Triangle( const Sphere &s, const Triangle_tpl &t ) { F sqdistance = Distance::Point_Triangle(s.center,t) - (s.radius*s.radius); if (sqdistance<0) sqdistance=0; return sqdistance; } template ILINE F Sphere_Triangle( const Sphere &s, const Triangle_tpl &t, Vec3_tpl& output ) { F sqdistance = Distance::Point_Triangle(s.center,t,output) - (s.radius*s.radius); if (sqdistance<0) sqdistance=0; return sqdistance; } } //namespace Distance #endif