2 ===========================================================================
5 Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
7 This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
9 Doom 3 Source Code is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
14 Doom 3 Source Code is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
22 In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
24 If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
26 ===========================================================================
29 #ifndef __MATH_PLANE_H__
30 #define __MATH_PLANE_H__
33 ===============================================================================
35 3D plane with equation: a * x + b * y + c * z + d = 0
37 ===============================================================================
44 #define ON_EPSILON 0.1f
45 #define DEGENERATE_DIST_EPSILON 1e-4f
53 #define PLANESIDE_FRONT 0
54 #define PLANESIDE_BACK 1
55 #define PLANESIDE_ON 2
56 #define PLANESIDE_CROSS 3
62 #define PLANETYPE_NEGX 3
63 #define PLANETYPE_NEGY 4
64 #define PLANETYPE_NEGZ 5
65 #define PLANETYPE_TRUEAXIAL 6 // all types < 6 are true axial planes
66 #define PLANETYPE_ZEROX 6
67 #define PLANETYPE_ZEROY 7
68 #define PLANETYPE_ZEROZ 8
69 #define PLANETYPE_NONAXIAL 9
74 idPlane( float a, float b, float c, float d );
75 idPlane( const idVec3 &normal, const float dist );
77 float operator[]( int index ) const;
78 float & operator[]( int index );
79 idPlane operator-() const; // flips plane
80 idPlane & operator=( const idVec3 &v ); // sets normal and sets idPlane::d to zero
81 idPlane operator+( const idPlane &p ) const; // add plane equations
82 idPlane operator-( const idPlane &p ) const; // subtract plane equations
83 idPlane & operator*=( const idMat3 &m ); // Normal() *= m
85 bool Compare( const idPlane &p ) const; // exact compare, no epsilon
86 bool Compare( const idPlane &p, const float epsilon ) const; // compare with epsilon
87 bool Compare( const idPlane &p, const float normalEps, const float distEps ) const; // compare with epsilon
88 bool operator==( const idPlane &p ) const; // exact compare, no epsilon
89 bool operator!=( const idPlane &p ) const; // exact compare, no epsilon
91 void Zero( void ); // zero plane
92 void SetNormal( const idVec3 &normal ); // sets the normal
93 const idVec3 & Normal( void ) const; // reference to const normal
94 idVec3 & Normal( void ); // reference to normal
95 float Normalize( bool fixDegenerate = true ); // only normalizes the plane normal, does not adjust d
96 bool FixDegenerateNormal( void ); // fix degenerate normal
97 bool FixDegeneracies( float distEpsilon ); // fix degenerate normal and dist
98 float Dist( void ) const; // returns: -d
99 void SetDist( const float dist ); // sets: d = -dist
100 int Type( void ) const; // returns plane type
102 bool FromPoints( const idVec3 &p1, const idVec3 &p2, const idVec3 &p3, bool fixDegenerate = true );
103 bool FromVecs( const idVec3 &dir1, const idVec3 &dir2, const idVec3 &p, bool fixDegenerate = true );
104 void FitThroughPoint( const idVec3 &p ); // assumes normal is valid
105 bool HeightFit( const idVec3 *points, const int numPoints );
106 idPlane Translate( const idVec3 &translation ) const;
107 idPlane & TranslateSelf( const idVec3 &translation );
108 idPlane Rotate( const idVec3 &origin, const idMat3 &axis ) const;
109 idPlane & RotateSelf( const idVec3 &origin, const idMat3 &axis );
111 float Distance( const idVec3 &v ) const;
112 int Side( const idVec3 &v, const float epsilon = 0.0f ) const;
114 bool LineIntersection( const idVec3 &start, const idVec3 &end ) const;
115 // intersection point is start + dir * scale
116 bool RayIntersection( const idVec3 &start, const idVec3 &dir, float &scale ) const;
117 bool PlaneIntersection( const idPlane &plane, idVec3 &start, idVec3 &dir ) const;
119 int GetDimension( void ) const;
121 const idVec4 & ToVec4( void ) const;
122 idVec4 & ToVec4( void );
123 const float * ToFloatPtr( void ) const;
124 float * ToFloatPtr( void );
125 const char * ToString( int precision = 2 ) const;
134 extern idPlane plane_origin;
135 #define plane_zero plane_origin
137 ID_INLINE idPlane::idPlane( void ) {
140 ID_INLINE idPlane::idPlane( float a, float b, float c, float d ) {
147 ID_INLINE idPlane::idPlane( const idVec3 &normal, const float dist ) {
154 ID_INLINE float idPlane::operator[]( int index ) const {
155 return ( &a )[ index ];
158 ID_INLINE float& idPlane::operator[]( int index ) {
159 return ( &a )[ index ];
162 ID_INLINE idPlane idPlane::operator-() const {
163 return idPlane( -a, -b, -c, -d );
166 ID_INLINE idPlane &idPlane::operator=( const idVec3 &v ) {
174 ID_INLINE idPlane idPlane::operator+( const idPlane &p ) const {
175 return idPlane( a + p.a, b + p.b, c + p.c, d + p.d );
178 ID_INLINE idPlane idPlane::operator-( const idPlane &p ) const {
179 return idPlane( a - p.a, b - p.b, c - p.c, d - p.d );
182 ID_INLINE idPlane &idPlane::operator*=( const idMat3 &m ) {
187 ID_INLINE bool idPlane::Compare( const idPlane &p ) const {
188 return ( a == p.a && b == p.b && c == p.c && d == p.d );
191 ID_INLINE bool idPlane::Compare( const idPlane &p, const float epsilon ) const {
192 if ( idMath::Fabs( a - p.a ) > epsilon ) {
196 if ( idMath::Fabs( b - p.b ) > epsilon ) {
200 if ( idMath::Fabs( c - p.c ) > epsilon ) {
204 if ( idMath::Fabs( d - p.d ) > epsilon ) {
211 ID_INLINE bool idPlane::Compare( const idPlane &p, const float normalEps, const float distEps ) const {
212 if ( idMath::Fabs( d - p.d ) > distEps ) {
215 if ( !Normal().Compare( p.Normal(), normalEps ) ) {
221 ID_INLINE bool idPlane::operator==( const idPlane &p ) const {
225 ID_INLINE bool idPlane::operator!=( const idPlane &p ) const {
226 return !Compare( p );
229 ID_INLINE void idPlane::Zero( void ) {
230 a = b = c = d = 0.0f;
233 ID_INLINE void idPlane::SetNormal( const idVec3 &normal ) {
239 ID_INLINE const idVec3 &idPlane::Normal( void ) const {
240 return *reinterpret_cast<const idVec3 *>(&a);
243 ID_INLINE idVec3 &idPlane::Normal( void ) {
244 return *reinterpret_cast<idVec3 *>(&a);
247 ID_INLINE float idPlane::Normalize( bool fixDegenerate ) {
248 float length = reinterpret_cast<idVec3 *>(&a)->Normalize();
250 if ( fixDegenerate ) {
251 FixDegenerateNormal();
256 ID_INLINE bool idPlane::FixDegenerateNormal( void ) {
257 return Normal().FixDegenerateNormal();
260 ID_INLINE bool idPlane::FixDegeneracies( float distEpsilon ) {
261 bool fixedNormal = FixDegenerateNormal();
262 // only fix dist if the normal was degenerate
264 if ( idMath::Fabs( d - idMath::Rint( d ) ) < distEpsilon ) {
265 d = idMath::Rint( d );
271 ID_INLINE float idPlane::Dist( void ) const {
275 ID_INLINE void idPlane::SetDist( const float dist ) {
279 ID_INLINE bool idPlane::FromPoints( const idVec3 &p1, const idVec3 &p2, const idVec3 &p3, bool fixDegenerate ) {
280 Normal() = (p1 - p2).Cross( p3 - p2 );
281 if ( Normalize( fixDegenerate ) == 0.0f ) {
284 d = -( Normal() * p2 );
288 ID_INLINE bool idPlane::FromVecs( const idVec3 &dir1, const idVec3 &dir2, const idVec3 &p, bool fixDegenerate ) {
289 Normal() = dir1.Cross( dir2 );
290 if ( Normalize( fixDegenerate ) == 0.0f ) {
293 d = -( Normal() * p );
297 ID_INLINE void idPlane::FitThroughPoint( const idVec3 &p ) {
298 d = -( Normal() * p );
301 ID_INLINE idPlane idPlane::Translate( const idVec3 &translation ) const {
302 return idPlane( a, b, c, d - translation * Normal() );
305 ID_INLINE idPlane &idPlane::TranslateSelf( const idVec3 &translation ) {
306 d -= translation * Normal();
310 ID_INLINE idPlane idPlane::Rotate( const idVec3 &origin, const idMat3 &axis ) const {
312 p.Normal() = Normal() * axis;
313 p.d = d + origin * Normal() - origin * p.Normal();
317 ID_INLINE idPlane &idPlane::RotateSelf( const idVec3 &origin, const idMat3 &axis ) {
318 d += origin * Normal();
320 d -= origin * Normal();
324 ID_INLINE float idPlane::Distance( const idVec3 &v ) const {
325 return a * v.x + b * v.y + c * v.z + d;
328 ID_INLINE int idPlane::Side( const idVec3 &v, const float epsilon ) const {
329 float dist = Distance( v );
330 if ( dist > epsilon ) {
331 return PLANESIDE_FRONT;
333 else if ( dist < -epsilon ) {
334 return PLANESIDE_BACK;
341 ID_INLINE bool idPlane::LineIntersection( const idVec3 &start, const idVec3 &end ) const {
342 float d1, d2, fraction;
344 d1 = Normal() * start + d;
345 d2 = Normal() * end + d;
349 if ( d1 > 0.0f && d2 > 0.0f ) {
352 if ( d1 < 0.0f && d2 < 0.0f ) {
355 fraction = ( d1 / ( d1 - d2 ) );
356 return ( fraction >= 0.0f && fraction <= 1.0f );
359 ID_INLINE bool idPlane::RayIntersection( const idVec3 &start, const idVec3 &dir, float &scale ) const {
362 d1 = Normal() * start + d;
367 scale = -( d1 / d2 );
371 ID_INLINE int idPlane::GetDimension( void ) const {
375 ID_INLINE const idVec4 &idPlane::ToVec4( void ) const {
376 return *reinterpret_cast<const idVec4 *>(&a);
379 ID_INLINE idVec4 &idPlane::ToVec4( void ) {
380 return *reinterpret_cast<idVec4 *>(&a);
383 ID_INLINE const float *idPlane::ToFloatPtr( void ) const {
384 return reinterpret_cast<const float *>(&a);
387 ID_INLINE float *idPlane::ToFloatPtr( void ) {
388 return reinterpret_cast<float *>(&a);
391 #endif /* !__MATH_PLANE_H__ */