DOOM-3-BFG

DOOM 3 BFG Edition
Log | Files | Refs

Sphere.h (9238B)


      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 __BV_SPHERE_H__
     30 #define __BV_SPHERE_H__
     31 
     32 /*
     33 ===============================================================================
     34 
     35 	Sphere
     36 
     37 ===============================================================================
     38 */
     39 
     40 class idSphere {
     41 public:
     42 					idSphere();
     43 					explicit idSphere( const idVec3 &point );
     44 					explicit idSphere( const idVec3 &point, const float r );
     45 
     46 	float			operator[]( const int index ) const;
     47 	float &			operator[]( const int index );
     48 	idSphere		operator+( const idVec3 &t ) const;				// returns tranlated sphere
     49 	idSphere &		operator+=( const idVec3 &t );					// translate the sphere
     50 	idSphere		operator+( const idSphere &s ) const;
     51 	idSphere &		operator+=( const idSphere &s );
     52 
     53 	bool			Compare( const idSphere &a ) const;							// exact compare, no epsilon
     54 	bool			Compare( const idSphere &a, const float epsilon ) const;	// compare with epsilon
     55 	bool			operator==(	const idSphere &a ) const;						// exact compare, no epsilon
     56 	bool			operator!=(	const idSphere &a ) const;						// exact compare, no epsilon
     57 
     58 	void			Clear();									// inside out sphere
     59 	void			Zero();									// single point at origin
     60 	void			SetOrigin( const idVec3 &o );					// set origin of sphere
     61 	void			SetRadius( const float r );						// set square radius
     62 
     63 	const idVec3 &	GetOrigin() const;						// returns origin of sphere
     64 	float			GetRadius() const;						// returns sphere radius
     65 	bool			IsCleared() const;						// returns true if sphere is inside out
     66 
     67 	bool			AddPoint( const idVec3 &p );					// add the point, returns true if the sphere expanded
     68 	bool			AddSphere( const idSphere &s );					// add the sphere, returns true if the sphere expanded
     69 	idSphere		Expand( const float d ) const;					// return bounds expanded in all directions with the given value
     70 	idSphere &		ExpandSelf( const float d );					// expand bounds in all directions with the given value
     71 	idSphere		Translate( const idVec3 &translation ) const;
     72 	idSphere &		TranslateSelf( const idVec3 &translation );
     73 
     74 	float			PlaneDistance( const idPlane &plane ) const;
     75 	int				PlaneSide( const idPlane &plane, const float epsilon = ON_EPSILON ) const;
     76 
     77 	bool			ContainsPoint( const idVec3 &p ) const;			// includes touching
     78 	bool			IntersectsSphere( const idSphere &s ) const;	// includes touching
     79 	bool			LineIntersection( const idVec3 &start, const idVec3 &end ) const;
     80 					// intersection points are (start + dir * scale1) and (start + dir * scale2)
     81 	bool			RayIntersection( const idVec3 &start, const idVec3 &dir, float &scale1, float &scale2 ) const;
     82 
     83 					// Tight sphere for a point set.
     84 	void			FromPoints( const idVec3 *points, const int numPoints );
     85 					// Most tight sphere for a translation.
     86 	void			FromPointTranslation( const idVec3 &point, const idVec3 &translation );
     87 	void			FromSphereTranslation( const idSphere &sphere, const idVec3 &start, const idVec3 &translation );
     88 					// Most tight sphere for a rotation.
     89 	void			FromPointRotation( const idVec3 &point, const idRotation &rotation );
     90 	void			FromSphereRotation( const idSphere &sphere, const idVec3 &start, const idRotation &rotation );
     91 
     92 	void			AxisProjection( const idVec3 &dir, float &min, float &max ) const;
     93 
     94 private:
     95 	idVec3			origin;
     96 	float			radius;
     97 };
     98 
     99 extern idSphere	sphere_zero;
    100 
    101 ID_INLINE idSphere::idSphere() {
    102 }
    103 
    104 ID_INLINE idSphere::idSphere( const idVec3 &point ) {
    105 	origin = point;
    106 	radius = 0.0f;
    107 }
    108 
    109 ID_INLINE idSphere::idSphere( const idVec3 &point, const float r ) {
    110 	origin = point;
    111 	radius = r;
    112 }
    113 
    114 ID_INLINE float idSphere::operator[]( const int index ) const {
    115 	return ((float *) &origin)[index];
    116 }
    117 
    118 ID_INLINE float &idSphere::operator[]( const int index ) {
    119 	return ((float *) &origin)[index];
    120 }
    121 
    122 ID_INLINE idSphere idSphere::operator+( const idVec3 &t ) const {
    123 	return idSphere( origin + t, radius );
    124 }
    125 
    126 ID_INLINE idSphere &idSphere::operator+=( const idVec3 &t ) {
    127 	origin += t;
    128 	return *this;
    129 }
    130 
    131 ID_INLINE bool idSphere::Compare( const idSphere &a ) const {
    132 	return ( origin.Compare( a.origin ) && radius == a.radius );
    133 }
    134 
    135 ID_INLINE bool idSphere::Compare( const idSphere &a, const float epsilon ) const {
    136 	return ( origin.Compare( a.origin, epsilon ) && idMath::Fabs( radius - a.radius ) <= epsilon );
    137 }
    138 
    139 ID_INLINE bool idSphere::operator==( const idSphere &a ) const {
    140 	return Compare( a );
    141 }
    142 
    143 ID_INLINE bool idSphere::operator!=( const idSphere &a ) const {
    144 	return !Compare( a );
    145 }
    146 
    147 ID_INLINE void idSphere::Clear() {
    148 	origin.Zero();
    149 	radius = -1.0f;
    150 }
    151 
    152 ID_INLINE void idSphere::Zero() {
    153 	origin.Zero();
    154 	radius = 0.0f;
    155 }
    156 
    157 ID_INLINE void idSphere::SetOrigin( const idVec3 &o ) {
    158 	origin = o;
    159 }
    160 
    161 ID_INLINE void idSphere::SetRadius( const float r ) {
    162 	radius = r;
    163 }
    164 
    165 ID_INLINE const idVec3 &idSphere::GetOrigin() const {
    166 	return origin;
    167 }
    168 
    169 ID_INLINE float idSphere::GetRadius() const {
    170 	return radius;
    171 }
    172 
    173 ID_INLINE bool idSphere::IsCleared() const {
    174 	return ( radius < 0.0f );
    175 }
    176 
    177 ID_INLINE bool idSphere::AddPoint( const idVec3 &p ) {
    178 	if ( radius < 0.0f ) {
    179 		origin = p;
    180 		radius = 0.0f;
    181 		return true;
    182 	}
    183 	else {
    184 		float r = ( p - origin ).LengthSqr();
    185 		if ( r > radius * radius ) {
    186 			r = idMath::Sqrt( r );
    187 			origin += ( p - origin ) * 0.5f * (1.0f - radius / r );
    188 			radius += 0.5f * ( r - radius );
    189 			return true;
    190 		}
    191 		return false;
    192 	}
    193 }
    194 
    195 ID_INLINE bool idSphere::AddSphere( const idSphere &s ) {
    196 	if ( radius < 0.0f ) {
    197 		origin = s.origin;
    198 		radius = s.radius;
    199 		return true;
    200 	}
    201 	else {
    202 		float r = ( s.origin - origin ).LengthSqr();
    203 		if ( r > ( radius + s.radius ) * ( radius + s.radius ) ) {
    204 			r = idMath::Sqrt( r );
    205 			origin += ( s.origin - origin ) * 0.5f * (1.0f - radius / ( r + s.radius ) );
    206 			radius += 0.5f * ( ( r + s.radius ) - radius );
    207 			return true;
    208 		}
    209 		return false;
    210 	}
    211 }
    212 
    213 ID_INLINE idSphere idSphere::Expand( const float d ) const {
    214 	return idSphere( origin, radius + d );
    215 }
    216 
    217 ID_INLINE idSphere &idSphere::ExpandSelf( const float d ) {
    218 	radius += d;
    219 	return *this;
    220 }
    221 
    222 ID_INLINE idSphere idSphere::Translate( const idVec3 &translation ) const {
    223 	return idSphere( origin + translation, radius );
    224 }
    225 
    226 ID_INLINE idSphere &idSphere::TranslateSelf( const idVec3 &translation ) {
    227 	origin += translation;
    228 	return *this;
    229 }
    230 
    231 ID_INLINE bool idSphere::ContainsPoint( const idVec3 &p ) const {
    232 	if ( ( p - origin ).LengthSqr() > radius * radius ) {
    233 		return false;
    234 	}
    235 	return true;
    236 }
    237 
    238 ID_INLINE bool idSphere::IntersectsSphere( const idSphere &s ) const {
    239 	float r = s.radius + radius;
    240 	if ( ( s.origin - origin ).LengthSqr() > r * r ) {
    241 		return false;
    242 	}
    243 	return true;
    244 }
    245 
    246 ID_INLINE void idSphere::FromPointTranslation( const idVec3 &point, const idVec3 &translation ) {
    247 	origin = point + 0.5f * translation;
    248 	radius = idMath::Sqrt( 0.5f * translation.LengthSqr() );
    249 }
    250 
    251 ID_INLINE void idSphere::FromSphereTranslation( const idSphere &sphere, const idVec3 &start, const idVec3 &translation ) {
    252 	origin = start + sphere.origin + 0.5f * translation;
    253 	radius = idMath::Sqrt( 0.5f * translation.LengthSqr() ) + sphere.radius;
    254 }
    255 
    256 ID_INLINE void idSphere::FromPointRotation( const idVec3 &point, const idRotation &rotation ) {
    257 	idVec3 end = rotation * point;
    258 	origin = ( point + end ) * 0.5f;
    259 	radius = idMath::Sqrt( 0.5f * ( end - point ).LengthSqr() );
    260 }
    261 
    262 ID_INLINE void idSphere::FromSphereRotation( const idSphere &sphere, const idVec3 &start, const idRotation &rotation ) {
    263 	idVec3 end = rotation * sphere.origin;
    264 	origin = start + ( sphere.origin + end ) * 0.5f;
    265 	radius = idMath::Sqrt( 0.5f * ( end - sphere.origin ).LengthSqr() ) + sphere.radius;
    266 }
    267 
    268 ID_INLINE void idSphere::AxisProjection( const idVec3 &dir, float &min, float &max ) const {
    269 	float d;
    270 	d = dir * origin;
    271 	min = d - radius;
    272 	max = d + radius;
    273 }
    274 
    275 #endif /* !__BV_SPHERE_H__ */