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__ */