"L. Spiro Engine"
|
00001 00016 #ifndef __LSM_QUATERNION_H__ 00017 #define __LSM_QUATERNION_H__ 00018 00019 #include "../LSMMathLib.h" 00020 #include "../Matrix/LSMMatrix4x4.h" 00021 #include "../Vector/LSMVector3.h" 00022 00023 #pragma warning( push ) 00024 00025 // warning C4201: nonstandard extension used : nameless struct/union 00026 #pragma warning( disable : 4201 ) 00027 00028 00029 namespace lsm { 00030 00037 class CQuaternion { 00038 public : 00039 // == Various constructors. 00040 LSE_INLINE LSE_CALLCTOR CQuaternion(); 00041 LSE_INLINE LSE_CALLCTOR CQuaternion( LSREAL _fX, LSREAL _fY, LSREAL _fZ, LSREAL _fW ); 00042 LSE_INLINE LSE_CALLCTOR CQuaternion( const CQuaternion &_qQuat ); 00043 00044 00045 // == Operators. 00052 LSE_INLINE CQuaternion & LSE_FCALL operator += ( const CQuaternion &_qQuat ); 00053 00060 LSE_INLINE CQuaternion & LSE_FCALL operator -= ( const CQuaternion &_qQuat ); 00061 00068 LSE_INLINE CQuaternion & LSE_FCALL operator *= ( const CQuaternion &_qQuat ); 00069 00076 LSE_INLINE CQuaternion & LSE_FCALL operator *= ( LSREAL _fVal ); 00077 00084 LSE_INLINE CQuaternion & LSE_FCALL operator /= ( LSREAL _fVal ); 00085 00091 LSE_INLINE CQuaternion LSE_FCALL operator + () const; 00092 00098 LSE_INLINE CQuaternion LSE_FCALL operator - () const; 00099 00106 LSE_INLINE CQuaternion LSE_FCALL operator + ( const CQuaternion &_qQuat ) const; 00107 00114 LSE_INLINE CQuaternion LSE_FCALL operator - ( const CQuaternion &_qQuat ) const; 00115 00122 LSE_INLINE CQuaternion LSE_FCALL operator * ( const CQuaternion &_qQuat ) const; 00123 00130 LSE_INLINE CQuaternion LSE_FCALL operator * ( LSREAL _fVal ) const; 00131 00138 LSE_INLINE CQuaternion LSE_FCALL operator / ( LSREAL _fVal ) const; 00139 00146 LSE_INLINE bool LSE_FCALL operator == ( const CQuaternion &_qQuat ) const; 00147 00154 LSE_INLINE bool LSE_FCALL operator != ( const CQuaternion &_qQuat ) const; 00155 00162 LSE_INLINE LSREAL & LSE_FCALL operator [] ( LSUINT32 _ui32Index ); 00163 00170 LSE_INLINE LSREAL LSE_FCALL operator [] ( LSUINT32 _ui32Index ) const; 00171 00172 00173 // == Functions. 00180 LSE_INLINE CQuaternion & LSE_FCALL Identity(); 00181 00187 LSE_INLINE CQuaternion LSE_FCALL Conjugate() const; 00188 00195 LSE_INLINE LSREAL LSE_FCALL Dot( const CQuaternion &_qQuat ) const; 00196 00202 CQuaternion LSE_FCALL Exp() const; 00203 00209 CQuaternion LSE_FCALL Log() const; 00210 00216 LSE_INLINE LSREAL LSE_FCALL LenSq() const; 00217 00223 LSE_INLINE LSREAL LSE_FCALL Len() const; 00224 00228 LSE_INLINE LSVOID LSE_FCALL Normalize(); 00229 00235 LSE_INLINE CQuaternion LSE_FCALL Inverse(); 00236 00245 LSE_INLINE CQuaternion & LSE_FCALL Lerp( const CQuaternion &_qLeft, const CQuaternion &_qRight, LSREAL _fT ); 00246 00255 CQuaternion & LSE_FCALL Slerp( const CQuaternion &_qLeft, const CQuaternion &_qRight, LSREAL _fT ); 00256 00267 CQuaternion & LSE_FCALL Squad( const CQuaternion &_qQ, const CQuaternion &_qA, const CQuaternion &_qB, const CQuaternion &_qC, LSREAL _fT ); 00268 00275 CQuaternion & LSE_FCALL FromRotationMatrix( const CMatrix4x4 &_mMat ); 00276 00283 LSVOID LSE_FCALL ToRotationMatrix( CMatrix4x4 &_mMat ) const; 00284 00291 CQuaternion & LSE_FCALL FromRotationVectors( const CVector3 _vVectors[3] ); 00292 00300 CQuaternion & LSE_FCALL AddScaledVector( const CVector3 &_vVec, LSREAL _fTime ); 00301 00307 LSE_INLINE LSREAL & LSE_FCALL X(); 00308 00314 LSE_INLINE LSREAL & LSE_FCALL Y(); 00315 00321 LSE_INLINE LSREAL & LSE_FCALL Z(); 00322 00328 LSE_INLINE LSREAL & LSE_FCALL W(); 00329 00330 // == Members. 00331 #pragma pack( push, 1 ) 00332 struct { 00336 LSREAL x, 00337 y, 00338 z, 00339 w; 00340 } u; 00341 #pragma pack( pop ) 00342 00343 protected : 00344 static LSUINT32 m_ui32Next[3]; 00345 }; 00346 00347 00348 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 00349 // DEFINITIONS 00350 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 00351 // == Various constructors. 00352 LSE_INLINE LSE_CALLCTOR CQuaternion::CQuaternion() {} 00353 LSE_INLINE LSE_CALLCTOR CQuaternion::CQuaternion( LSREAL _fX, LSREAL _fY, LSREAL _fZ, LSREAL _fW ) { 00354 u.x = _fX; 00355 u.y = _fY; 00356 u.z = _fZ; 00357 u.w = _fW; 00358 } 00359 LSE_INLINE LSE_CALLCTOR CQuaternion::CQuaternion( const CQuaternion &_qQuat ) { 00360 u.x = _qQuat[0]; 00361 u.y = _qQuat[1]; 00362 u.z = _qQuat[2]; 00363 u.w = _qQuat[3]; 00364 } 00365 00366 00367 // == Operators. 00374 LSE_INLINE CQuaternion & LSE_FCALL CQuaternion::operator += ( const CQuaternion &_qQuat ) { 00375 u.x += _qQuat[0]; 00376 u.y += _qQuat[1]; 00377 u.z += _qQuat[2]; 00378 u.w += _qQuat[3]; 00379 return (*this); 00380 } 00381 00388 LSE_INLINE CQuaternion & LSE_FCALL CQuaternion::operator -= ( const CQuaternion &_qQuat ) { 00389 u.x -= _qQuat[0]; 00390 u.y -= _qQuat[1]; 00391 u.z -= _qQuat[2]; 00392 u.w -= _qQuat[3]; 00393 return (*this); 00394 } 00395 00402 LSE_INLINE CQuaternion & LSE_FCALL CQuaternion::operator *= ( const CQuaternion &_qQuat ) { 00403 CQuaternion qProd; 00404 00405 qProd[3] = 00406 u.w * _qQuat[3] - 00407 u.x * _qQuat[0] - 00408 u.y * _qQuat[1] - 00409 u.z * _qQuat[2]; 00410 00411 qProd[0] = 00412 u.w * _qQuat[0] + 00413 u.x * _qQuat[3] + 00414 u.y * _qQuat[2] - 00415 u.z * _qQuat[1]; 00416 00417 qProd[1] = 00418 u.w * _qQuat[1] + 00419 u.y * _qQuat[3] + 00420 u.z * _qQuat[0] - 00421 u.x * _qQuat[2]; 00422 00423 qProd[2] = 00424 u.w * _qQuat[2] + 00425 u.z * _qQuat[3] + 00426 u.x * _qQuat[1] - 00427 u.y * _qQuat[0]; 00428 00429 (*this) = qProd; 00430 return (*this); 00431 } 00432 00439 LSE_INLINE CQuaternion & LSE_FCALL CQuaternion::operator *= ( LSREAL _fVal ) { 00440 u.x *= _fVal; 00441 u.y *= _fVal; 00442 u.z *= _fVal; 00443 u.w *= _fVal; 00444 return (*this); 00445 } 00446 00453 LSE_INLINE CQuaternion & LSE_FCALL CQuaternion::operator /= ( LSREAL _fVal ) { 00454 _fVal = LSM_ONE / _fVal; 00455 u.x *= _fVal; 00456 u.y *= _fVal; 00457 u.z *= _fVal; 00458 u.w *= _fVal; 00459 return (*this); 00460 } 00461 00462 00468 LSE_INLINE CQuaternion LSE_FCALL CQuaternion::operator + () const { 00469 return CQuaternion( +u.x, +u.y, +u.z, +u.w ); 00470 } 00471 00477 LSE_INLINE CQuaternion LSE_FCALL CQuaternion::operator - () const { 00478 return CQuaternion( -u.x, -u.y, -u.z, -u.w ); 00479 } 00480 00481 00488 LSE_INLINE CQuaternion LSE_FCALL CQuaternion::operator + ( const CQuaternion &_qQuat ) const { 00489 return CQuaternion( u.x + _qQuat.u.x, u.y + _qQuat.u.y, u.z + _qQuat.u.z, u.w + _qQuat.u.w ); 00490 } 00491 00498 LSE_INLINE CQuaternion LSE_FCALL CQuaternion::operator - ( const CQuaternion &_qQuat ) const { 00499 return CQuaternion( u.x - _qQuat.u.x, u.y - _qQuat.u.y, u.z - _qQuat.u.z, u.w - _qQuat.u.w ); 00500 } 00501 00508 LSE_INLINE CQuaternion LSE_FCALL CQuaternion::operator * ( const CQuaternion &_qQuat ) const { 00509 /*return CQuaternion( u.w * _qQuat.u.x + 00510 u.x * _qQuat.u.w + 00511 u.y * _qQuat.u.z - 00512 u.z * _qQuat.u.y, 00513 u.w * _qQuat.u.y + 00514 u.y * _qQuat.u.w + 00515 u.z * _qQuat.u.x - 00516 u.x * _qQuat.u.z, 00517 u.w * _qQuat.u.z + 00518 u.z * _qQuat.u.w + 00519 u.x * _qQuat.u.y - 00520 u.y * _qQuat.u.x, 00521 u.w * _qQuat.u.w - 00522 u.x * _qQuat.u.x - 00523 u.y * _qQuat.u.y - 00524 u.z * _qQuat.u.z );*/ 00525 return CQuaternion( u.w * _qQuat.u.x + 00526 u.x * _qQuat.u.w - 00527 u.y * _qQuat.u.z - 00528 u.z * _qQuat.u.y, 00529 u.w * _qQuat.u.y - 00530 u.x * _qQuat.u.z + 00531 u.y * _qQuat.u.w - 00532 u.z * _qQuat.u.x, 00533 u.w * _qQuat.u.z + 00534 u.x * _qQuat.u.y - 00535 u.y * _qQuat.u.x + 00536 u.z * _qQuat.u.w, 00537 u.w * _qQuat.u.w - 00538 u.x * _qQuat.u.x - 00539 u.y * _qQuat.u.y - 00540 u.z * _qQuat.u.z ); 00541 } 00542 00549 LSE_INLINE CQuaternion LSE_FCALL CQuaternion::operator * ( LSREAL _fVal ) const { 00550 return CQuaternion( u.x * _fVal, u.y * _fVal, u.z * _fVal, u.w * _fVal ); 00551 } 00552 00559 LSE_INLINE CQuaternion LSE_FCALL CQuaternion::operator / ( LSREAL _fVal ) const { 00560 register LSREAL fVal = LSM_ONE / _fVal; 00561 return CQuaternion( u.x * fVal, u.y * fVal, u.z * fVal, u.w * fVal ); 00562 } 00563 00570 LSE_INLINE bool LSE_FCALL CQuaternion::operator == ( const CQuaternion &_qQuat ) const { 00571 return u.x == _qQuat[0] && u.y == _qQuat[1] && u.z == _qQuat[2] && u.w == _qQuat[3]; 00572 } 00573 00580 LSE_INLINE bool LSE_FCALL CQuaternion::operator != ( const CQuaternion &_qQuat ) const { 00581 return u.x != _qQuat[0] || u.y != _qQuat[1] || u.z != _qQuat[2] || u.w != _qQuat[3]; 00582 } 00583 00590 LSE_INLINE LSREAL & LSE_FCALL CQuaternion::operator [] ( LSUINT32 _ui32Index ) { 00591 return reinterpret_cast<LSREAL *>(this)[_ui32Index]; 00592 } 00593 00600 LSE_INLINE LSREAL LSE_FCALL CQuaternion::operator [] ( LSUINT32 _ui32Index ) const { 00601 return reinterpret_cast<const LSREAL *>(this)[_ui32Index]; 00602 } 00603 00604 00611 LSE_INLINE CQuaternion & LSE_FCALL CQuaternion::Identity() { 00612 u.x = u.y = u.z = LSM_ZERO; 00613 u.w = LSM_ONE; 00614 return (*this); 00615 } 00616 00622 LSE_INLINE CQuaternion LSE_FCALL CQuaternion::Conjugate() const { 00623 return CQuaternion( -u.x, -u.y, -u.z, u.w ); 00624 } 00625 00632 LSE_INLINE LSREAL LSE_FCALL CQuaternion::Dot( const CQuaternion &_qQuat ) const { 00633 return (u.x * _qQuat[0]) + 00634 (u.y * _qQuat[1]) + 00635 (u.z * _qQuat[2]) + 00636 (u.w * _qQuat[3]); 00637 } 00638 00644 LSE_INLINE LSREAL LSE_FCALL CQuaternion::LenSq() const { 00645 return u.x * u.x + 00646 u.y * u.y + 00647 u.z * u.z + 00648 u.w * u.w; 00649 } 00650 00656 LSE_INLINE LSREAL LSE_FCALL CQuaternion::Len() const { 00657 return CMathLib::Sqrt( u.x * u.x + 00658 u.y * u.y + 00659 u.z * u.z + 00660 u.w * u.w ); 00661 } 00662 00666 LSE_INLINE LSVOID LSE_FCALL CQuaternion::Normalize() { 00667 LSREAL fInvLen = CMathLib::InvSqrt( u.x * u.x + 00668 u.y * u.y + 00669 u.z * u.z + 00670 u.w * u.w ); 00671 u.x *= fInvLen; 00672 u.y *= fInvLen; 00673 u.z *= fInvLen; 00674 u.w *= fInvLen; 00675 } 00676 00682 LSE_INLINE CQuaternion LSE_FCALL CQuaternion::Inverse() { 00683 CQuaternion qRet; 00684 00685 LSREAL fInvLen = -CMathLib::InvSqrt( u.x * u.x + 00686 u.y * u.y + 00687 u.z * u.z + 00688 u.w * u.w ); 00689 00690 qRet[3] = u.w * -fInvLen; 00691 qRet[0] = u.x * fInvLen; 00692 qRet[1] = u.y * fInvLen; 00693 qRet[2] = u.z * fInvLen; 00694 00695 return qRet; 00696 } 00697 00706 LSE_INLINE CQuaternion & LSE_FCALL CQuaternion::Lerp( const CQuaternion &_qLeft, const CQuaternion &_qRight, LSREAL _fT ) { 00707 (*this) = _qLeft + (_qRight - _qLeft) * _fT; 00708 Normalize(); 00709 return (*this); 00710 } 00711 00718 LSE_INLINE LSVOID LSE_FCALL CQuaternion::ToRotationMatrix( CMatrix4x4 &_mMat ) const { 00719 LSREAL fTx = LSM_TWO * u.x; 00720 LSREAL fTy = LSM_TWO * u.y; 00721 LSREAL fTz = LSM_TWO * u.z; 00722 LSREAL fTwx = fTx * u.w; 00723 LSREAL fTwy = fTy * u.w; 00724 LSREAL fTwz = fTz * u.w; 00725 LSREAL fTxx = fTx * u.x; 00726 LSREAL fTxy = fTy * u.x; 00727 LSREAL fTxz = fTz * u.x; 00728 LSREAL fTyy = fTy * u.y; 00729 LSREAL fTyz = fTz * u.y; 00730 LSREAL fTzz = fTz * u.z; 00731 00732 _mMat( 0, 0 ) = LSM_ONE - (fTyy + fTzz); 00733 _mMat( 1, 0 ) = fTxy - fTwz; 00734 _mMat( 2, 0 ) = fTxz + fTwy; 00735 _mMat( 0, 1 ) = fTxy + fTwz; 00736 _mMat( 1, 1 ) = LSM_ONE - (fTxx + fTzz); 00737 _mMat( 2, 1 ) = fTyz - fTwx; 00738 _mMat( 0, 2 ) = fTxz - fTwy; 00739 _mMat( 1, 2 ) = fTyz + fTwx; 00740 _mMat( 2, 2 ) = LSM_ONE - (fTxx + fTyy); 00741 } 00742 00748 LSE_INLINE LSREAL & LSE_FCALL CQuaternion::X() { 00749 return u.x; 00750 } 00751 00757 LSE_INLINE LSREAL & LSE_FCALL CQuaternion::Y() { 00758 return u.y; 00759 } 00760 00766 LSE_INLINE LSREAL & LSE_FCALL CQuaternion::Z() { 00767 return u.z; 00768 } 00769 00775 LSE_INLINE LSREAL & LSE_FCALL CQuaternion::W() { 00776 return u.w; 00777 } 00778 00779 } // namespace lsm 00780 00781 #pragma warning( pop ) 00782 00783 #endif // __LSM_QUATERNION_H__