////////////////////////////////////////////////////////////////////// // // Crytek Common Source code // // File: Cry_Geo.h // Description: Common structures for geometry computations // // History: // -March 15,2003: Created by Ivo Herzeg // ////////////////////////////////////////////////////////////////////// #ifndef CRYGEOSTRUCTS_H #define CRYGEOSTRUCTS_H #include "Cry_Math.h" #if _MSC_VER > 1000 # pragma once #endif /////////////////////////////////////////////////////////////////////////////// // Forward declarations // /////////////////////////////////////////////////////////////////////////////// struct Line; struct Ray; struct Lineseg; template struct Triangle_tpl; struct AABB; template struct OBB_tpl; struct Sphere; struct AAEllipsoid; struct Ellipsoid; //----------------------------------------------------- /////////////////////////////////////////////////////////////////////////////// // Definitions // /////////////////////////////////////////////////////////////////////////////// #define FINDMINMAX(x0,x1,x2,min,max) \ min = max = x0; \ if(x1max) max=x1;\ if(x2max) max=x2; /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// // struct Line /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// struct Line { Vec3 pointonline; Vec3 direction; //caution: the direction is important for any intersection test //default Line constructor (without initialisation) inline Line( void ) {} inline Line( const Vec3 &o, const Vec3 &d ) { pointonline=o; direction=d; } inline void operator () ( const Vec3 &o, const Vec3 &d ) { pointonline=o; direction=d; } ~Line( void ) {}; }; /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// // struct Ray /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// struct Ray { Vec3 origin; Vec3 direction; //default Ray constructor (without initialisation) inline Ray( void ) {} inline Ray( const Vec3 &o, const Vec3 &d ) { origin=o; direction=d; } inline void operator () ( const Vec3 &o, const Vec3 &d ) { origin=o; direction=d; } ~Ray( void ) {}; }; /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// // struct Lineseg /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// struct Lineseg { Vec3 start; Vec3 end; //default Lineseg constructor (without initialisation) inline Lineseg( void ) {} inline Lineseg( const Vec3 &s, const Vec3 &e ) { start=s; end=e; } inline void operator () ( const Vec3 &s, const Vec3 &e ) { start=s; end=e; } ~Lineseg( void ) {}; }; /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// // struct Triangle /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// template struct Triangle_tpl { Vec3_tpl v0,v1,v2; //default Lineseg constructor (without initialisation) inline Triangle_tpl( void ) {} inline Triangle_tpl( const Vec3_tpl& a, const Vec3_tpl& b, const Vec3_tpl& c ) { v0=a; v1=b; v2=c; } inline void operator () ( const Vec3_tpl& a, const Vec3_tpl& b, const Vec3_tpl& c ) { v0=a; v1=b; v2=c; } ~Triangle_tpl( void ) {}; }; /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// // struct AABB /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// struct AABB { Vec3 min; Vec3 max; //default AABB constructor (without initialisation) inline AABB( void ) {} inline AABB( const Vec3 &vmin, const Vec3 &vmax ) { min=vmin; max=vmax; } inline void operator () ( const Vec3 &vmin, const Vec3 &vmax ) { min=vmin; max=vmax; } ~AABB( void ) {}; //! Reset Bounding box before calculating bounds. void Reset() { min = Vec3(MAX); max = Vec3(MIN); } //! Check if bounding box is empty (Zero volume). bool IsEmpty() const { return min == max; } void Add( const Vec3 &v ) { min.x=__min( min.x,v.x ); min.y=__min( min.y,v.y ); min.z=__min( min.z,v.z ); max.x=__max( max.x,v.x ); max.y=__max( max.y,v.y ); max.z=__max( max.z,v.z ); } //! Check if this bounding box overlap with bounding box of sphere. bool IsOverlapSphereBounds( const Vec3 &pos,float radius ) const { if (pos.x > min.x && pos.x < max.x && pos.y > min.y && pos.y < max.y && pos.z > min.z && pos.z < max.z) return true; if (pos.x+radius < min.x) return false; if (pos.y+radius < min.y) return false; if (pos.z+radius < min.z) return false; if (pos.x-radius > max.x) return false; if (pos.y-radius > max.y) return false; if (pos.z-radius > max.z) return false; return true; } //! Check if this bounding box contain sphere within itself. bool IsContainSphere( const Vec3 &pos,float radius ) const { if (pos.x-radius < min.x) return false; if (pos.y-radius < min.y) return false; if (pos.z-radius < min.z) return false; if (pos.x+radius > max.x) return false; if (pos.y+radius > max.y) return false; if (pos.z+radius > max.z) return false; return true; } // Check two bounding boxes for intersection. inline bool IsIntersectBox( const AABB &b ) const { // Check for intersection on X axis. if ((min.x > b.max.x)||(b.min.x > max.x)) return false; // Check for intersection on Y axis. if ((min.y > b.max.y)||(b.min.y > max.y)) return false; // Check for intersection on Z axis. if ((min.z > b.max.z)||(b.min.z > max.z)) return false; // Boxes overlap in all 3 axises. return true; } //! Transforms AABB with specified matrix. void Transform( const Matrix44 &tm ) { Vec3 m = tm.TransformPointOLD( min ); Vec3 vx = Vec3(tm(0,0),tm(0,1),tm(0,2))*(max.x-min.x); Vec3 vy = Vec3(tm(1,0),tm(1,1),tm(1,2))*(max.y-min.y); Vec3 vz = Vec3(tm(2,0),tm(2,1),tm(2,2))*(max.z-min.z); min = m; max = m; if (vx.x < 0) min.x += vx.x; else max.x += vx.x; if (vx.y < 0) min.y += vx.y; else max.y += vx.y; if (vx.z < 0) min.z += vx.z; else max.z += vx.z; if (vy.x < 0) min.x += vy.x; else max.x += vy.x; if (vy.y < 0) min.y += vy.y; else max.y += vy.y; if (vy.z < 0) min.z += vy.z; else max.z += vy.z; if (vz.x < 0) min.x += vz.x; else max.x += vz.x; if (vz.y < 0) min.y += vz.y; else max.y += vz.y; if (vz.z < 0) min.z += vz.z; else max.z += vz.z; } /*! * calculate the new bounds of a transformed AABB * * Example: * AABB aabb = AABB::CreateAABBfromOBB(m34,aabb); * * return values: * expanded AABB in world-space */ ILINE void SetTransformedAABB( const Matrix34& m34, const AABB& aabb ) { Vec3 sz = Matrix33(m34).GetFabs()*((aabb.max-aabb.min)*0.5f); Vec3 pos = m34*((aabb.max+aabb.min)*0.5f); min=pos-sz; max=pos+sz; } ILINE static AABB CreateTransformedAABB( const Matrix34& m34, const AABB& aabb ) { AABB taabb; taabb.SetTransformedAABB(m34,aabb); return taabb; } //create an AABB using just the extensions of the OBB and ignore the orientation. template ILINE void SetAABBfromOBB( const OBB_tpl& obb ) { min=obb.c-obb.h; max=obb.c+obb.h; } template ILINE static AABB CreateAABBfromOBB( const OBB_tpl& obb ) { return AABB(obb.c-obb.h,obb.c+obb.h); } /*! * converts an OBB into an tight fitting AABB * * Example: * AABB aabb = AABB::CreateAABBfromOBB(wposition,obb,1.0f); * * return values: * expanded AABB in world-space */ template ILINE void SetAABBfromOBB( const Vec3& wpos, const OBB_tpl& obb, f32 scaling=1.0f ) { Vec3 pos = obb.m33*obb.c*scaling + wpos; Vec3 sz = obb.m33.GetFabs()*obb.h*scaling; min=pos-sz; max=pos+sz; } template ILINE static AABB CreateAABBfromOBB( const Vec3& wpos, const OBB_tpl& obb, f32 scaling=1.0f) { AABB taabb; taabb.SetAABBfromOBB(wpos,obb,scaling); return taabb; } }; /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// // struct OBB /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// template struct OBB_tpl { Matrix33 m33; //orientation vectors Vec3 h; //half-length-vector Vec3 c; //center of obb //default OBB constructor (without initialisation) inline OBB_tpl() {} ILINE void SetOBB( const Matrix33& m33, const Vec3& hlv, const Vec3& center ) { m33=m33; h=hlv; c=center; } ILINE static OBB_tpl CreateOBB( const Matrix33& m33, const Vec3& hlv, const Vec3& center ) { OBB_tpl obb; obb.m33=m33; obb.h=hlv; obb.c=center; return obb; } ILINE void SetOBBfromAABB( const Matrix33& mat33, const AABB& aabb ) { m33 = mat33; h = (aabb.max-aabb.min)*0.5f; //calculate the half-length-vectors c = (aabb.max+aabb.min)*0.5f; //the center is relative to the PIVOT } ILINE static OBB_tpl CreateOBBfromAABB( const Matrix33& m33, const AABB& aabb ) { OBB_tpl obb; obb.SetOBBfromAABB(m33,aabb); return obb; } ~OBB_tpl( void ) {}; }; /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// // struct Sphere /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// struct Sphere { Vec3 center; float radius; //default Sphere constructor (without initialisation) inline Sphere( void ) {} inline Sphere( const Vec3 &c, const float &r ) { center=c; radius=r; } inline void operator () ( const Vec3 &c, const float &r ) { center=c; radius=r; } ~Sphere( void ) {}; }; /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// // struct AAEllipsoid /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// struct AAEllipsoid { Vec3 center; Vec3 radius_vec; //default AAEllipsoid constructor (without initialisation) inline AAEllipsoid( void ) {} inline AAEllipsoid( const Vec3 &c, const Vec3 &rv ) { radius_vec=rv; center=c; } inline void operator () ( const Vec3 &c, const Vec3 &rv ) { radius_vec=rv; center=c; } ~AAEllipsoid( void ) {}; }; /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// // struct Ellipsoid /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// struct Ellipsoid { Matrix34 ExtensionPos; //default Ellipsoid constructor (without initialisation) inline Ellipsoid( void ) {} inline Ellipsoid( const Matrix34 &ep ) { ExtensionPos=ep; } inline void operator () ( const Matrix34 &ep ) { ExtensionPos=ep; } ~Ellipsoid( void ) {}; }; typedef Triangle_tpl Triangle; typedef Triangle_tpl Triangle_f64; typedef OBB_tpl OBB; #include "Cry_GeoDistance.h" #include "Cry_GeoOverlap.h" #include "Cry_GeoIntersect.h" ///////////////////////////////////////////////////////////////////////// //this is some special engine stuff, should be moved to a better location ///////////////////////////////////////////////////////////////////////// // for bbox's checks and calculations #define MAX_BB +99999.0f #define MIN_BB -99999.0f //! checks if this has been set to minBB inline bool IsMinBB( const Vec3& v ) { if (v.x<=MIN_BB) return (true); if (v.y<=MIN_BB) return (true); if (v.z<=MIN_BB) return (true); return (false); } //! checks if this has been set to maxBB inline bool IsMaxBB( const Vec3& v ) { if (v.x>=MAX_BB) return (true); if (v.y>=MAX_BB) return (true); if (v.z>=MAX_BB) return (true); return (false); } inline Vec3 SetMaxBB( void ) { return Vec3(MAX_BB,MAX_BB,MAX_BB); } inline Vec3 SetMinBB( void ) { return Vec3(MIN_BB,MIN_BB,MIN_BB); } inline void AddToBounds (const Vec3& v, Vec3& mins, Vec3& maxs) { if (v.x < mins.x) mins.x = v.x; if (v.x > maxs.x) maxs.x = v.x; if (v.y < mins.y) mins.y = v.y; if (v.y > maxs.y) maxs.y = v.y; if (v.z < mins.z) mins.z = v.z; if (v.z > maxs.z) maxs.z = v.z; } //////////////////////////////////////////////////////////////// //! calc the area of a polygon giving a list of vertices and normal inline float CalcArea(const Vec3 *vertices,int numvertices,const Vec3 &normal) { Vec3 csum(0,0,0); int n=numvertices; for (int i = 0, j = 1; i <= n-2; i++, j++) { csum.x += vertices[i].y*vertices[j].z-vertices[i].z*vertices[j].y; csum.y += vertices[i].z*vertices[j].x-vertices[i].x*vertices[j].z; csum.z += vertices[i].x*vertices[j].y-vertices[i].y*vertices[j].x; } csum.x += vertices[n-1].y*vertices[0].z-vertices[n-1].z*vertices[0].y; csum.y += vertices[n-1].z*vertices[0].x-vertices[n-1].x*vertices[0].z; csum.z += vertices[n-1].x*vertices[0].y-vertices[n-1].y*vertices[0].x; float area=0.5f*(float)fabs(normal*csum); return (area); } #endif //geostructs