Quat.h (11114B)
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_QUAT_H__ 30 #define __MATH_QUAT_H__ 31 32 /* 33 =============================================================================== 34 35 Quaternion 36 37 =============================================================================== 38 */ 39 40 #include "../containers/Array.h" // for idTupleSize 41 42 class idVec3; 43 class idAngles; 44 class idRotation; 45 class idMat3; 46 class idMat4; 47 class idCQuat; 48 49 class idQuat { 50 public: 51 float x; 52 float y; 53 float z; 54 float w; 55 56 idQuat(); 57 idQuat( float x, float y, float z, float w ); 58 59 void Set( float x, float y, float z, float w ); 60 61 float operator[]( int index ) const; 62 float & operator[]( int index ); 63 idQuat operator-() const; 64 idQuat & operator=( const idQuat &a ); 65 idQuat operator+( const idQuat &a ) const; 66 idQuat & operator+=( const idQuat &a ); 67 idQuat operator-( const idQuat &a ) const; 68 idQuat & operator-=( const idQuat &a ); 69 idQuat operator*( const idQuat &a ) const; 70 idVec3 operator*( const idVec3 &a ) const; 71 idQuat operator*( float a ) const; 72 idQuat & operator*=( const idQuat &a ); 73 idQuat & operator*=( float a ); 74 75 friend idQuat operator*( const float a, const idQuat &b ); 76 friend idVec3 operator*( const idVec3 &a, const idQuat &b ); 77 78 bool Compare( const idQuat &a ) const; // exact compare, no epsilon 79 bool Compare( const idQuat &a, const float epsilon ) const; // compare with epsilon 80 bool operator==( const idQuat &a ) const; // exact compare, no epsilon 81 bool operator!=( const idQuat &a ) const; // exact compare, no epsilon 82 83 idQuat Inverse() const; 84 float Length() const; 85 idQuat & Normalize(); 86 87 float CalcW() const; 88 int GetDimension() const; 89 90 idAngles ToAngles() const; 91 idRotation ToRotation() const; 92 idMat3 ToMat3() const; 93 idMat4 ToMat4() const; 94 idCQuat ToCQuat() const; 95 idVec3 ToAngularVelocity() const; 96 const float * ToFloatPtr() const; 97 float * ToFloatPtr(); 98 const char * ToString( int precision = 2 ) const; 99 100 idQuat & Slerp( const idQuat &from, const idQuat &to, float t ); 101 idQuat & Lerp( const idQuat &from, const idQuat &to, const float t ); 102 }; 103 104 // A non-member slerp function allows constructing a const idQuat object with the result of a slerp, 105 // but without having to explicity create a temporary idQuat object. 106 idQuat Slerp( const idQuat & from, const idQuat & to, const float t ); 107 108 ID_INLINE idQuat::idQuat() { 109 } 110 111 ID_INLINE idQuat::idQuat( float x, float y, float z, float w ) { 112 this->x = x; 113 this->y = y; 114 this->z = z; 115 this->w = w; 116 } 117 118 ID_INLINE float idQuat::operator[]( int index ) const { 119 assert( ( index >= 0 ) && ( index < 4 ) ); 120 return ( &x )[ index ]; 121 } 122 123 ID_INLINE float& idQuat::operator[]( int index ) { 124 assert( ( index >= 0 ) && ( index < 4 ) ); 125 return ( &x )[ index ]; 126 } 127 128 ID_INLINE idQuat idQuat::operator-() const { 129 return idQuat( -x, -y, -z, -w ); 130 } 131 132 ID_INLINE idQuat &idQuat::operator=( const idQuat &a ) { 133 x = a.x; 134 y = a.y; 135 z = a.z; 136 w = a.w; 137 138 return *this; 139 } 140 141 ID_INLINE idQuat idQuat::operator+( const idQuat &a ) const { 142 return idQuat( x + a.x, y + a.y, z + a.z, w + a.w ); 143 } 144 145 ID_INLINE idQuat& idQuat::operator+=( const idQuat &a ) { 146 x += a.x; 147 y += a.y; 148 z += a.z; 149 w += a.w; 150 151 return *this; 152 } 153 154 ID_INLINE idQuat idQuat::operator-( const idQuat &a ) const { 155 return idQuat( x - a.x, y - a.y, z - a.z, w - a.w ); 156 } 157 158 ID_INLINE idQuat& idQuat::operator-=( const idQuat &a ) { 159 x -= a.x; 160 y -= a.y; 161 z -= a.z; 162 w -= a.w; 163 164 return *this; 165 } 166 167 ID_INLINE idQuat idQuat::operator*( const idQuat &a ) const { 168 return idQuat( w*a.x + x*a.w + y*a.z - z*a.y, 169 w*a.y + y*a.w + z*a.x - x*a.z, 170 w*a.z + z*a.w + x*a.y - y*a.x, 171 w*a.w - x*a.x - y*a.y - z*a.z ); 172 } 173 174 ID_INLINE idVec3 idQuat::operator*( const idVec3 &a ) const { 175 #if 0 176 // it's faster to do the conversion to a 3x3 matrix and multiply the vector by this 3x3 matrix 177 return ( ToMat3() * a ); 178 #else 179 // result = this->Inverse() * idQuat( a.x, a.y, a.z, 0.0f ) * (*this) 180 float xxzz = x*x - z*z; 181 float wwyy = w*w - y*y; 182 183 float xw2 = x*w*2.0f; 184 float xy2 = x*y*2.0f; 185 float xz2 = x*z*2.0f; 186 float yw2 = y*w*2.0f; 187 float yz2 = y*z*2.0f; 188 float zw2 = z*w*2.0f; 189 190 return idVec3( 191 (xxzz + wwyy)*a.x + (xy2 + zw2)*a.y + (xz2 - yw2)*a.z, 192 (xy2 - zw2)*a.x + (y*y+w*w-x*x-z*z)*a.y + (yz2 + xw2)*a.z, 193 (xz2 + yw2)*a.x + (yz2 - xw2)*a.y + (wwyy - xxzz)*a.z 194 ); 195 #endif 196 } 197 198 ID_INLINE idQuat idQuat::operator*( float a ) const { 199 return idQuat( x * a, y * a, z * a, w * a ); 200 } 201 202 ID_INLINE idQuat operator*( const float a, const idQuat &b ) { 203 return b * a; 204 } 205 206 ID_INLINE idVec3 operator*( const idVec3 &a, const idQuat &b ) { 207 return b * a; 208 } 209 210 ID_INLINE idQuat& idQuat::operator*=( const idQuat &a ) { 211 *this = *this * a; 212 213 return *this; 214 } 215 216 ID_INLINE idQuat& idQuat::operator*=( float a ) { 217 x *= a; 218 y *= a; 219 z *= a; 220 w *= a; 221 222 return *this; 223 } 224 225 ID_INLINE bool idQuat::Compare( const idQuat &a ) const { 226 return ( ( x == a.x ) && ( y == a.y ) && ( z == a.z ) && ( w == a.w ) ); 227 } 228 229 ID_INLINE bool idQuat::Compare( const idQuat &a, const float epsilon ) const { 230 if ( idMath::Fabs( x - a.x ) > epsilon ) { 231 return false; 232 } 233 if ( idMath::Fabs( y - a.y ) > epsilon ) { 234 return false; 235 } 236 if ( idMath::Fabs( z - a.z ) > epsilon ) { 237 return false; 238 } 239 if ( idMath::Fabs( w - a.w ) > epsilon ) { 240 return false; 241 } 242 return true; 243 } 244 245 ID_INLINE bool idQuat::operator==( const idQuat &a ) const { 246 return Compare( a ); 247 } 248 249 ID_INLINE bool idQuat::operator!=( const idQuat &a ) const { 250 return !Compare( a ); 251 } 252 253 ID_INLINE void idQuat::Set( float x, float y, float z, float w ) { 254 this->x = x; 255 this->y = y; 256 this->z = z; 257 this->w = w; 258 } 259 260 ID_INLINE idQuat idQuat::Inverse() const { 261 return idQuat( -x, -y, -z, w ); 262 } 263 264 ID_INLINE float idQuat::Length() const { 265 float len; 266 267 len = x * x + y * y + z * z + w * w; 268 return idMath::Sqrt( len ); 269 } 270 271 ID_INLINE idQuat& idQuat::Normalize() { 272 float len; 273 float ilength; 274 275 len = this->Length(); 276 if ( len ) { 277 ilength = 1 / len; 278 x *= ilength; 279 y *= ilength; 280 z *= ilength; 281 w *= ilength; 282 } 283 return *this; 284 } 285 286 ID_INLINE float idQuat::CalcW() const { 287 // take the absolute value because floating point rounding may cause the dot of x,y,z to be larger than 1 288 return sqrt( fabs( 1.0f - ( x * x + y * y + z * z ) ) ); 289 } 290 291 ID_INLINE int idQuat::GetDimension() const { 292 return 4; 293 } 294 295 ID_INLINE const float *idQuat::ToFloatPtr() const { 296 return &x; 297 } 298 299 ID_INLINE float *idQuat::ToFloatPtr() { 300 return &x; 301 } 302 303 /* 304 =============================================================================== 305 306 Specialization to get size of an idQuat generically. 307 308 =============================================================================== 309 */ 310 template<> 311 struct idTupleSize< idQuat > { 312 enum { value = 4 }; 313 }; 314 315 /* 316 =============================================================================== 317 318 Compressed quaternion 319 320 =============================================================================== 321 */ 322 323 class idCQuat { 324 public: 325 float x; 326 float y; 327 float z; 328 329 idCQuat(); 330 idCQuat( float x, float y, float z ); 331 332 void Set( float x, float y, float z ); 333 334 float operator[]( int index ) const; 335 float & operator[]( int index ); 336 337 bool Compare( const idCQuat &a ) const; // exact compare, no epsilon 338 bool Compare( const idCQuat &a, const float epsilon ) const; // compare with epsilon 339 bool operator==( const idCQuat &a ) const; // exact compare, no epsilon 340 bool operator!=( const idCQuat &a ) const; // exact compare, no epsilon 341 342 int GetDimension() const; 343 344 idAngles ToAngles() const; 345 idRotation ToRotation() const; 346 idMat3 ToMat3() const; 347 idMat4 ToMat4() const; 348 idQuat ToQuat() const; 349 const float * ToFloatPtr() const; 350 float * ToFloatPtr(); 351 const char * ToString( int precision = 2 ) const; 352 }; 353 354 ID_INLINE idCQuat::idCQuat() { 355 } 356 357 ID_INLINE idCQuat::idCQuat( float x, float y, float z ) { 358 this->x = x; 359 this->y = y; 360 this->z = z; 361 } 362 363 ID_INLINE void idCQuat::Set( float x, float y, float z ) { 364 this->x = x; 365 this->y = y; 366 this->z = z; 367 } 368 369 ID_INLINE float idCQuat::operator[]( int index ) const { 370 assert( ( index >= 0 ) && ( index < 3 ) ); 371 return ( &x )[ index ]; 372 } 373 374 ID_INLINE float& idCQuat::operator[]( int index ) { 375 assert( ( index >= 0 ) && ( index < 3 ) ); 376 return ( &x )[ index ]; 377 } 378 379 ID_INLINE bool idCQuat::Compare( const idCQuat &a ) const { 380 return ( ( x == a.x ) && ( y == a.y ) && ( z == a.z ) ); 381 } 382 383 ID_INLINE bool idCQuat::Compare( const idCQuat &a, const float epsilon ) const { 384 if ( idMath::Fabs( x - a.x ) > epsilon ) { 385 return false; 386 } 387 if ( idMath::Fabs( y - a.y ) > epsilon ) { 388 return false; 389 } 390 if ( idMath::Fabs( z - a.z ) > epsilon ) { 391 return false; 392 } 393 return true; 394 } 395 396 ID_INLINE bool idCQuat::operator==( const idCQuat &a ) const { 397 return Compare( a ); 398 } 399 400 ID_INLINE bool idCQuat::operator!=( const idCQuat &a ) const { 401 return !Compare( a ); 402 } 403 404 ID_INLINE int idCQuat::GetDimension() const { 405 return 3; 406 } 407 408 ID_INLINE idQuat idCQuat::ToQuat() const { 409 // take the absolute value because floating point rounding may cause the dot of x,y,z to be larger than 1 410 return idQuat( x, y, z, sqrt( fabs( 1.0f - ( x * x + y * y + z * z ) ) ) ); 411 } 412 413 ID_INLINE const float *idCQuat::ToFloatPtr() const { 414 return &x; 415 } 416 417 ID_INLINE float *idCQuat::ToFloatPtr() { 418 return &x; 419 } 420 421 /* 422 =============================================================================== 423 424 Specialization to get size of an idCQuat generically. 425 426 =============================================================================== 427 */ 428 template<> 429 struct idTupleSize< idCQuat > { 430 enum { value = 3 }; 431 }; 432 433 #endif /* !__MATH_QUAT_H__ */