home *** CD-ROM | disk | FTP | other *** search
/ GameStar 2006 March / Gamestar_82_2006-03_dvd.iso / DVDStar / Editace / quake4_sdkv10.exe / source / idlib / math / Plane.h < prev    next >
C/C++ Source or Header  |  2005-11-14  |  10KB  |  365 lines

  1.  
  2. #ifndef __MATH_PLANE_H__
  3. #define __MATH_PLANE_H__
  4.  
  5. /*
  6. ===============================================================================
  7.  
  8.     3D plane with equation: a * x + b * y + c * z + d = 0
  9.  
  10. ===============================================================================
  11. */
  12.  
  13.  
  14. class idVec3;
  15. class idMat3;
  16.  
  17. #define    ON_EPSILON                    0.1f
  18. #define DEGENERATE_DIST_EPSILON        1e-4f
  19.  
  20. #define    SIDE_FRONT                    0
  21. #define    SIDE_BACK                    1
  22. #define    SIDE_ON                        2
  23. #define    SIDE_CROSS                    3
  24.  
  25. // plane sides
  26. #define PLANESIDE_FRONT                0
  27. #define PLANESIDE_BACK                1
  28. #define PLANESIDE_ON                2
  29. #define PLANESIDE_CROSS                3
  30.  
  31. // plane types
  32. #define PLANETYPE_X                    0
  33. #define PLANETYPE_Y                    1
  34. #define PLANETYPE_Z                    2
  35. #define PLANETYPE_NEGX                3
  36. #define PLANETYPE_NEGY                4
  37. #define PLANETYPE_NEGZ                5
  38. #define PLANETYPE_TRUEAXIAL            6    // all types < 6 are true axial planes
  39. #define PLANETYPE_ZEROX                6
  40. #define PLANETYPE_ZEROY                7
  41. #define PLANETYPE_ZEROZ                8
  42. #define PLANETYPE_NONAXIAL            9
  43.  
  44. class idPlane {
  45. public:
  46.                     idPlane( void );
  47.                     idPlane( float a, float b, float c, float d );
  48.                     idPlane( const idVec3 &normal, const float dist );
  49.  
  50.     float            operator[]( int index ) const;
  51.     float &            operator[]( int index );
  52.     idPlane            operator-() const;                        // flips plane
  53.     idPlane &        operator=( const idVec3 &v );            // sets normal and sets idPlane::d to zero
  54.     idPlane            operator+( const idPlane &p ) const;    // add plane equations
  55.     idPlane            operator-( const idPlane &p ) const;    // subtract plane equations
  56.     idPlane &        operator*=( const idMat3 &m );            // Normal() *= m
  57.  
  58.     bool            Compare( const idPlane &p ) const;                        // exact compare, no epsilon
  59.     bool            Compare( const idPlane &p, const float epsilon ) const;    // compare with epsilon
  60.     bool            Compare( const idPlane &p, const float normalEps, const float distEps ) const;    // compare with epsilon
  61.     bool            operator==(    const idPlane &p ) const;                    // exact compare, no epsilon
  62.     bool            operator!=(    const idPlane &p ) const;                    // exact compare, no epsilon
  63.  
  64.     void            Zero( void );                            // zero plane
  65.     void            SetNormal( const idVec3 &normal );        // sets the normal
  66.     const idVec3 &    Normal( void ) const;                    // reference to const normal
  67.     idVec3 &        Normal( void );                            // reference to normal
  68.     float            Normalize( bool fixDegenerate = true );    // only normalizes the plane normal, does not adjust d
  69.     bool            FixDegenerateNormal( void );            // fix degenerate normal
  70.     bool            FixDegeneracies( float distEpsilon );    // fix degenerate normal and dist
  71.     float            Dist( void ) const;                        // returns: -d
  72.     void            SetDist( const float dist );            // sets: d = -dist
  73.     int                Type( void ) const;                        // returns plane type
  74.  
  75.     bool            FromPoints( const idVec3 &p1, const idVec3 &p2, const idVec3 &p3, bool fixDegenerate = true );
  76.     bool            FromVecs( const idVec3 &dir1, const idVec3 &dir2, const idVec3 &p, bool fixDegenerate = true );
  77.     void            FitThroughPoint( const idVec3 &p );    // assumes normal is valid
  78.     bool            HeightFit( const idVec3 *points, const int numPoints );
  79.     idPlane            Translate( const idVec3 &translation ) const;
  80.     idPlane &        TranslateSelf( const idVec3 &translation );
  81.     idPlane            Rotate( const idVec3 &origin, const idMat3 &axis ) const;
  82.     idPlane &        RotateSelf( const idVec3 &origin, const idMat3 &axis );
  83.  
  84.     float            Distance( const idVec3 &v ) const;
  85.     int                Side( const idVec3 &v, const float epsilon = 0.0f ) const;
  86.  
  87.     bool            LineIntersection( const idVec3 &start, const idVec3 &end ) const;
  88.                     // intersection point is start + dir * scale
  89.     bool            RayIntersection( const idVec3 &start, const idVec3 &dir, float &scale ) const;
  90.     bool            PlaneIntersection( const idPlane &plane, idVec3 &start, idVec3 &dir ) const;
  91.  
  92.     int                GetDimension( void ) const;
  93.  
  94.     const idVec4 &    ToVec4( void ) const;
  95.     idVec4 &        ToVec4( void );
  96.     const float *    ToFloatPtr( void ) const;
  97.     float *            ToFloatPtr( void );
  98.     const char *    ToString( int precision = 2 ) const;
  99.  
  100. private:
  101.     float            a;
  102.     float            b;
  103.     float            c;
  104.     float            d;
  105. };
  106.  
  107. extern idPlane plane_origin;
  108. #define plane_zero plane_origin
  109.  
  110. ID_INLINE idPlane::idPlane( void ) {
  111. }
  112.  
  113. ID_INLINE idPlane::idPlane( float a, float b, float c, float d ) {
  114.     this->a = a;
  115.     this->b = b;
  116.     this->c = c;
  117.     this->d = d;
  118. }
  119.  
  120. ID_INLINE idPlane::idPlane( const idVec3 &normal, const float dist ) {
  121.     this->a = normal.x;
  122.     this->b = normal.y;
  123.     this->c = normal.z;
  124.     this->d = -dist;
  125. }
  126.  
  127. ID_INLINE float idPlane::operator[]( int index ) const {
  128.     return ( &a )[ index ];
  129. }
  130.  
  131. ID_INLINE float& idPlane::operator[]( int index ) {
  132.     return ( &a )[ index ];
  133. }
  134.  
  135. ID_INLINE idPlane idPlane::operator-() const {
  136.     return idPlane( -a, -b, -c, -d );
  137. }
  138.  
  139. ID_INLINE idPlane &idPlane::operator=( const idVec3 &v ) { 
  140.     a = v.x;
  141.     b = v.y;
  142.     c = v.z;
  143.     d = 0;
  144.     return *this;
  145. }
  146.  
  147. ID_INLINE idPlane idPlane::operator+( const idPlane &p ) const {
  148.     return idPlane( a + p.a, b + p.b, c + p.c, d + p.d );
  149. }
  150.  
  151. ID_INLINE idPlane idPlane::operator-( const idPlane &p ) const {
  152.     return idPlane( a - p.a, b - p.b, c - p.c, d - p.d );
  153. }
  154.  
  155. ID_INLINE idPlane &idPlane::operator*=( const idMat3 &m ) {
  156.     Normal() *= m;
  157.     return *this;
  158. }
  159.  
  160. ID_INLINE bool idPlane::Compare( const idPlane &p ) const {
  161.     return ( a == p.a && b == p.b && c == p.c && d == p.d );
  162. }
  163.  
  164. ID_INLINE bool idPlane::Compare( const idPlane &p, const float epsilon ) const {
  165.     if ( idMath::Fabs( a - p.a ) > epsilon ) {
  166.         return false;
  167.     }
  168.             
  169.     if ( idMath::Fabs( b - p.b ) > epsilon ) {
  170.         return false;
  171.     }
  172.  
  173.     if ( idMath::Fabs( c - p.c ) > epsilon ) {
  174.         return false;
  175.     }
  176.  
  177.     if ( idMath::Fabs( d - p.d ) > epsilon ) {
  178.         return false;
  179.     }
  180.  
  181.     return true;
  182. }
  183.  
  184. ID_INLINE bool idPlane::Compare( const idPlane &p, const float normalEps, const float distEps ) const {
  185.     if ( idMath::Fabs( d - p.d ) > distEps ) {
  186.         return false;
  187.     }
  188.     if ( !Normal().Compare( p.Normal(), normalEps ) ) {
  189.         return false;
  190.     }
  191.     return true;
  192. }
  193.  
  194. ID_INLINE bool idPlane::operator==( const idPlane &p ) const {
  195.     return Compare( p );
  196. }
  197.  
  198. ID_INLINE bool idPlane::operator!=( const idPlane &p ) const {
  199.     return !Compare( p );
  200. }
  201.  
  202. ID_INLINE void idPlane::Zero( void ) {
  203.     a = b = c = d = 0.0f;
  204. }
  205.  
  206. ID_INLINE void idPlane::SetNormal( const idVec3 &normal ) {
  207.     a = normal.x;
  208.     b = normal.y;
  209.     c = normal.z;
  210. }
  211.  
  212. ID_INLINE const idVec3 &idPlane::Normal( void ) const {
  213.     return *reinterpret_cast<const idVec3 *>(&a);
  214. }
  215.  
  216. ID_INLINE idVec3 &idPlane::Normal( void ) {
  217.     return *reinterpret_cast<idVec3 *>(&a);
  218. }
  219.  
  220. ID_INLINE float idPlane::Normalize( bool fixDegenerate ) {
  221.     float length = reinterpret_cast<idVec3 *>(&a)->Normalize();
  222.  
  223.     if ( fixDegenerate ) {
  224.         FixDegenerateNormal();
  225.     }
  226.     return length;
  227. }
  228.  
  229. ID_INLINE bool idPlane::FixDegenerateNormal( void ) {
  230.     return Normal().FixDegenerateNormal();
  231. }
  232.  
  233. ID_INLINE bool idPlane::FixDegeneracies( float distEpsilon ) {
  234.     bool fixedNormal = FixDegenerateNormal();
  235.     // only fix dist if the normal was degenerate
  236.     if ( fixedNormal ) {
  237.         if ( idMath::Fabs( d - idMath::Rint( d ) ) < distEpsilon ) {
  238.             d = idMath::Rint( d );
  239.         }
  240.     }
  241.     return fixedNormal;
  242. }
  243.  
  244. ID_INLINE float idPlane::Dist( void ) const {
  245.     return -d;
  246. }
  247.  
  248. ID_INLINE void idPlane::SetDist( const float dist ) {
  249.     d = -dist;
  250. }
  251.  
  252. ID_INLINE bool idPlane::FromPoints( const idVec3 &p1, const idVec3 &p2, const idVec3 &p3, bool fixDegenerate ) {
  253.     Normal() = (p1 - p2).Cross( p3 - p2 );
  254.     if ( Normalize( fixDegenerate ) == 0.0f ) {
  255.         return false;
  256.     }
  257.     d = -( Normal() * p2 );
  258.     return true;
  259. }
  260.  
  261. ID_INLINE bool idPlane::FromVecs( const idVec3 &dir1, const idVec3 &dir2, const idVec3 &p, bool fixDegenerate ) {
  262.     Normal() = dir1.Cross( dir2 );
  263.     if ( Normalize( fixDegenerate ) == 0.0f ) {
  264.         return false;
  265.     }
  266.     d = -( Normal() * p );
  267.     return true;
  268. }
  269.  
  270. ID_INLINE void idPlane::FitThroughPoint( const idVec3 &p ) {
  271.     d = -( Normal() * p );
  272. }
  273.  
  274. ID_INLINE idPlane idPlane::Translate( const idVec3 &translation ) const {
  275.     return idPlane( a, b, c, d - translation * Normal() );
  276. }
  277.  
  278. ID_INLINE idPlane &idPlane::TranslateSelf( const idVec3 &translation ) {
  279.     d -= translation * Normal();
  280.     return *this;
  281. }
  282.  
  283. ID_INLINE idPlane idPlane::Rotate( const idVec3 &origin, const idMat3 &axis ) const {
  284.     idPlane p;
  285.     p.Normal() = Normal() * axis;
  286.     p.d = d + origin * Normal() - origin * p.Normal();
  287.     return p;
  288. }
  289.  
  290. ID_INLINE idPlane &idPlane::RotateSelf( const idVec3 &origin, const idMat3 &axis ) {
  291.     d += origin * Normal();
  292.     Normal() *= axis;
  293.     d -= origin * Normal();
  294.     return *this;
  295. }
  296.  
  297. ID_INLINE float idPlane::Distance( const idVec3 &v ) const {
  298.     return a * v.x + b * v.y + c * v.z + d;
  299. }
  300.  
  301. ID_INLINE int idPlane::Side( const idVec3 &v, const float epsilon ) const {
  302.     float dist = Distance( v );
  303.     if ( dist > epsilon ) {
  304.         return PLANESIDE_FRONT;
  305.     }
  306.     else if ( dist < -epsilon ) {
  307.         return PLANESIDE_BACK;
  308.     }
  309.     else {
  310.         return PLANESIDE_ON;
  311.     }
  312. }
  313.  
  314. ID_INLINE bool idPlane::LineIntersection( const idVec3 &start, const idVec3 &end ) const {
  315.     float d1, d2, fraction;
  316.  
  317.     d1 = Normal() * start + d;
  318.     d2 = Normal() * end + d;
  319.     if ( d1 == d2 ) {
  320.         return false;
  321.     }
  322.     if ( d1 > 0.0f && d2 > 0.0f ) {
  323.         return false;
  324.     }
  325.     if ( d1 < 0.0f && d2 < 0.0f ) {
  326.         return false;
  327.     }
  328.     fraction = ( d1 / ( d1 - d2 ) );
  329.     return ( fraction >= 0.0f && fraction <= 1.0f );
  330. }
  331.  
  332. ID_INLINE bool idPlane::RayIntersection( const idVec3 &start, const idVec3 &dir, float &scale ) const {
  333.     float d1, d2;
  334.  
  335.     d1 = Normal() * start + d;
  336.     d2 = Normal() * dir;
  337.     if ( d2 == 0.0f ) {
  338.         return false;
  339.     }
  340.     scale = -( d1 / d2 );
  341.     return true;
  342. }
  343.  
  344. ID_INLINE int idPlane::GetDimension( void ) const {
  345.     return 4;
  346. }
  347.  
  348. ID_INLINE const idVec4 &idPlane::ToVec4( void ) const {
  349.     return *reinterpret_cast<const idVec4 *>(&a);
  350. }
  351.  
  352. ID_INLINE idVec4 &idPlane::ToVec4( void ) {
  353.     return *reinterpret_cast<idVec4 *>(&a);
  354. }
  355.  
  356. ID_INLINE const float *idPlane::ToFloatPtr( void ) const {
  357.     return reinterpret_cast<const float *>(&a);
  358. }
  359.  
  360. ID_INLINE float *idPlane::ToFloatPtr( void ) {
  361.     return reinterpret_cast<float *>(&a);
  362. }
  363.  
  364. #endif /* !__MATH_PLANE_H__ */
  365.