DOOM-3-BFG

DOOM 3 BFG Edition
Log | Files | Refs

Plane.h (11614B)


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