00001
00011
00012 #ifndef __XSIQUATERNIONF_H__
00013 #define __XSIQUATERNIONF_H__
00014
00015 #include "sicppsdk.h"
00016
00017 namespace XSI {
00018
00019 namespace MATH {
00020
00021 class CRotation3f;
00022
00023
00034
00035 class SICPPSDKDECL CQuaternionf
00036 {
00037 public:
00042 SICPPSDK_INLINE CQuaternionf();
00043
00047 SICPPSDK_INLINE CQuaternionf( const CQuaternionf& in_quaternion );
00048
00050 ~CQuaternionf() {};
00051
00056 SICPPSDK_INLINE CQuaternionf & operator=( const CQuaternionf & in_quaternion);
00057
00064 SICPPSDK_INLINE CQuaternionf( const float in_W, const float in_X, const float in_Y, const float in_Z );
00065
00070 SICPPSDK_INLINE CQuaternionf( const CVector3f& in_vct );
00071
00075 SICPPSDK_INLINE CQuaternionf( const CVector4f& in_vct );
00076
00082 SICPPSDK_INLINE bool Equals( const CQuaternionf &in_Quat ) const;
00083
00089 SICPPSDK_INLINE bool EpsilonEquals( const CQuaternionf& in_quat, const float in_fEpsilon ) const;
00090
00096 SICPPSDK_INLINE bool operator == ( const CQuaternionf &in_Quat ) const;
00097
00105 SICPPSDK_INLINE bool operator < ( const CQuaternionf& in_Quat ) const;
00106
00112 SICPPSDK_INLINE CQuaternionf& operator *= ( const CQuaternionf &in_Quat );
00113
00119 SICPPSDK_INLINE CQuaternionf& Mul( const CQuaternionf &in_Quat );
00120
00126 SICPPSDK_INLINE CQuaternionf& Mul( const CQuaternionf &in_Quat1, const CQuaternionf &in_Quat2);
00127
00132 SICPPSDK_INLINE float Dot( const CQuaternionf& in_quat1 ) const;
00133
00140 SICPPSDK_INLINE CQuaternionf& Slerp( const CQuaternionf& in_quatStart, const CQuaternionf& in_quatEnd, const float in_fU );
00141
00147 SICPPSDK_INLINE CQuaternionf& operator -= ( const CQuaternionf &in_Quat );
00148
00154 SICPPSDK_INLINE CQuaternionf& SubInPlace( const CQuaternionf &in_Quat );
00155
00162 SICPPSDK_INLINE CQuaternionf& Sub( const CQuaternionf &in_Quat1, const CQuaternionf &in_Quat2);
00163
00168 SICPPSDK_INLINE CQuaternionf& NegateInPlace();
00169
00175 SICPPSDK_INLINE CQuaternionf& Negate( const CQuaternionf &in_Quat);
00176
00181 SICPPSDK_INLINE float GetSquaredLength() const;
00182
00187 SICPPSDK_INLINE float GetLength() const;
00188
00193 SICPPSDK_INLINE CQuaternionf& operator += ( const CQuaternionf &in_Quat);
00194
00199 SICPPSDK_INLINE CQuaternionf& AddInPlace( const CQuaternionf &in_Quat );
00200
00207 SICPPSDK_INLINE CQuaternionf& Add( const CQuaternionf &in_Quat1, const CQuaternionf &in_Quat2);
00208
00213 SICPPSDK_INLINE CQuaternionf& ConjugateInPlace();
00214
00220 SICPPSDK_INLINE CQuaternionf& Conjugate( const CQuaternionf &in_Quat);
00221
00226 SICPPSDK_INLINE CQuaternionf& InvertInPlace();
00227
00233 SICPPSDK_INLINE CQuaternionf& Invert( const CQuaternionf &in_Quat);
00234
00238 SICPPSDK_INLINE CQuaternionf& SetIdentity();
00239
00244 SICPPSDK_INLINE CQuaternionf& Copy( const CQuaternionf &in_Quat );
00245
00249 SICPPSDK_INLINE CQuaternionf& NormalizeInPlace();
00250
00257 SICPPSDK_INLINE void Get( float &out_W, float &out_X, float &out_Y, float &out_Z ) const;
00258
00262 SICPPSDK_INLINE CVector3f Get() const;
00263
00267 SICPPSDK_INLINE void Get( CVector4f &io_XYZWVector ) const;
00268
00276 SICPPSDK_INLINE CQuaternionf& Set( float in_W, float in_X, float in_Y, float in_Z);
00277
00283 SICPPSDK_INLINE CQuaternionf& Set( const CVector3f &in_XYZVector );
00284
00290 SICPPSDK_INLINE CQuaternionf& Set( const CVector4f &in_XYZWVector );
00291
00298 SICPPSDK_INLINE float GetValue( short in_nIndex ) const;
00299
00307 SICPPSDK_INLINE CQuaternionf& SetValue( short in_nIndex, float newVal);
00308
00312 SICPPSDK_INLINE float GetW() const;
00313
00318 SICPPSDK_INLINE CQuaternionf& PutW( float newVal);
00319
00323 SICPPSDK_INLINE float GetZ() const;
00324
00329 SICPPSDK_INLINE CQuaternionf& PutZ( float newVal);
00330
00334 SICPPSDK_INLINE float GetY() const;
00335
00340 SICPPSDK_INLINE CQuaternionf& PutY( float newVal);
00341
00345 SICPPSDK_INLINE float GetX() const;
00346
00351 SICPPSDK_INLINE CQuaternionf& PutX( float newVal);
00352
00359 SICPPSDK_INLINE bool operator !=(const CQuaternionf & in_quat ) const;
00360
00361 private:
00362 float m_X, m_Y, m_Z, m_W;
00363 };
00364
00365
00366 SICPPSDK_INLINE CQuaternionf::CQuaternionf()
00367 {
00368 SetIdentity();
00369 }
00370
00371 SICPPSDK_INLINE CQuaternionf::CQuaternionf( const CQuaternionf& in_quaternion)
00372 {
00373 *this = in_quaternion;
00374 }
00375
00376 SICPPSDK_INLINE CQuaternionf& CQuaternionf::operator=( const CQuaternionf & in_Quat )
00377 {
00378 m_W = in_Quat.m_W;
00379 m_X = in_Quat.m_X;
00380 m_Y = in_Quat.m_Y;
00381 m_Z = in_Quat.m_Z;
00382
00383 return *this;
00384 }
00385
00386 SICPPSDK_INLINE CQuaternionf::CQuaternionf( const float in_W, const float in_X, const float in_Y, const float in_Z )
00387 {
00388 Set( in_W, in_X, in_Y, in_Z );
00389 }
00390
00391 SICPPSDK_INLINE CQuaternionf::CQuaternionf( const XSI::MATH::CVector3f& in_vct )
00392 {
00393 Set( in_vct );
00394 }
00395
00396 SICPPSDK_INLINE CQuaternionf::CQuaternionf( const XSI::MATH::CVector4f& in_vct )
00397 {
00398 Set( in_vct );
00399 }
00400
00401 SICPPSDK_INLINE bool CQuaternionf::Equals( const CQuaternionf &in_Quat ) const
00402 {
00403 return (this == &in_Quat) ? true :
00404 (m_W == in_Quat.m_W &&
00405 m_X == in_Quat.m_X &&
00406 m_Y == in_Quat.m_Y &&
00407 m_Z == in_Quat.m_Z );
00408 }
00409
00410 SICPPSDK_INLINE bool CQuaternionf::operator == ( const CQuaternionf &in_Quat ) const
00411 {
00412 return Equals(in_Quat);
00413 }
00414
00415 SICPPSDK_INLINE bool CQuaternionf::operator < ( const CQuaternionf& in_Quat) const
00416 {
00417 if ( m_W != in_Quat.m_W ) return m_W < in_Quat.m_W;
00418 if ( m_Z != in_Quat.m_Z ) return m_Z < in_Quat.m_Z;
00419 if ( m_Y != in_Quat.m_Y ) return m_Y < in_Quat.m_Y;
00420 if ( m_X != in_Quat.m_X ) return m_X < in_Quat.m_X;
00421 return false;
00422 }
00423
00424 SICPPSDK_INLINE bool CQuaternionf::operator != ( const CQuaternionf &in_Quat ) const
00425 {
00426 return ! Equals( in_Quat );
00427 }
00428
00429 SICPPSDK_INLINE CQuaternionf& CQuaternionf::operator *= ( const CQuaternionf &in_Quat )
00430 {
00431
00432 return Mul(*this, in_Quat);
00433 }
00434
00435 SICPPSDK_INLINE CQuaternionf& CQuaternionf::Mul( const CQuaternionf &in_Quat )
00436 {
00437 return Mul(*this, in_Quat);
00438 }
00439
00440 SICPPSDK_INLINE CQuaternionf& CQuaternionf::Mul
00441 (
00442 const CQuaternionf &in_Quat1,
00443 const CQuaternionf &in_Quat2
00444 )
00445 {
00446 float dW, dX, dY, dZ;
00447
00448 dW = in_Quat1.m_W * in_Quat2.m_W - in_Quat1.m_X * in_Quat2.m_X -
00449 in_Quat1.m_Y * in_Quat2.m_Y - in_Quat1.m_Z * in_Quat2.m_Z ;
00450
00451 dX = in_Quat1.m_W * in_Quat2.m_X + in_Quat2.m_W * in_Quat1.m_X +
00452 in_Quat1.m_Y * in_Quat2.m_Z - in_Quat2.m_Y * in_Quat1.m_Z ;
00453
00454 dY = in_Quat1.m_W * in_Quat2.m_Y + in_Quat2.m_W * in_Quat1.m_Y -
00455 in_Quat1.m_X * in_Quat2.m_Z + in_Quat2.m_X * in_Quat1.m_Z ;
00456
00457 dZ = in_Quat1.m_W * in_Quat2.m_Z + in_Quat2.m_W * in_Quat1.m_Z +
00458 in_Quat1.m_X * in_Quat2.m_Y - in_Quat2.m_X * in_Quat1.m_Y ;
00459
00460 m_W = dW; m_X = dX; m_Y = dY; m_Z = dZ;
00461
00462 return *this;
00463 }
00464
00465 SICPPSDK_INLINE CQuaternionf& CQuaternionf::operator -= ( const CQuaternionf &in_Quat )
00466 {
00467 return Sub(*this, in_Quat );
00468 }
00469
00470 SICPPSDK_INLINE CQuaternionf& CQuaternionf::SubInPlace( const CQuaternionf &in_Quat )
00471 {
00472 return Sub(*this, in_Quat );
00473 }
00474
00475 SICPPSDK_INLINE CQuaternionf& CQuaternionf::Sub
00476 (
00477 const CQuaternionf &in_Quat1,
00478 const CQuaternionf &in_Quat2
00479 )
00480 {
00481 m_W = in_Quat1.m_W - in_Quat2.m_W;
00482 m_X = in_Quat1.m_X - in_Quat2.m_X;
00483 m_Y = in_Quat1.m_Y - in_Quat2.m_Y;
00484 m_Z = in_Quat1.m_Z - in_Quat2.m_Z;
00485
00486 return *this;
00487 }
00488
00489 SICPPSDK_INLINE CQuaternionf& CQuaternionf::NegateInPlace()
00490 {
00491 return Negate(*this);
00492 }
00493
00494 SICPPSDK_INLINE CQuaternionf& CQuaternionf::Negate( const CQuaternionf &in_Quat)
00495 {
00496 m_W = -(in_Quat.m_W);
00497 m_X = -(in_Quat.m_X);
00498 m_Y = -(in_Quat.m_Y);
00499 m_Z = -(in_Quat.m_Z);
00500
00501 return( *this );
00502 }
00503
00504 SICPPSDK_INLINE float CQuaternionf::GetSquaredLength() const
00505 {
00506 return( m_W * m_W + m_X * m_X + m_Y * m_Y + m_Z * m_Z );
00507 }
00508
00509 SICPPSDK_INLINE float CQuaternionf::GetLength() const
00510 {
00511 return( sqrt( GetSquaredLength() ) );
00512 }
00513
00514 SICPPSDK_INLINE CQuaternionf& CQuaternionf::operator += ( const CQuaternionf &in_Quat)
00515 {
00516 return Add( *this, in_Quat );
00517 }
00518
00519 SICPPSDK_INLINE CQuaternionf& CQuaternionf::AddInPlace( const CQuaternionf &in_Quat )
00520 {
00521 return Add( *this, in_Quat );
00522 }
00523
00524 SICPPSDK_INLINE CQuaternionf& CQuaternionf::Add
00525 (
00526 const CQuaternionf &in_Quat1,
00527 const CQuaternionf &in_Quat2
00528 )
00529 {
00530 m_W = in_Quat1.m_W + in_Quat2.m_W;
00531 m_X = in_Quat1.m_X + in_Quat2.m_X;
00532 m_Y = in_Quat1.m_Y + in_Quat2.m_Y;
00533 m_Z = in_Quat1.m_Z + in_Quat2.m_Z;
00534 return *this;
00535 }
00536
00537 SICPPSDK_INLINE CQuaternionf& CQuaternionf::ConjugateInPlace()
00538 {
00539 return Conjugate(*this);
00540 }
00541
00542 SICPPSDK_INLINE CQuaternionf& CQuaternionf::Conjugate( const CQuaternionf &in_Quat)
00543 {
00544 m_W = in_Quat.m_W;
00545 m_X = -in_Quat.m_X;
00546 m_Y = -in_Quat.m_Y;
00547 m_Z = -in_Quat.m_Z;
00548
00549 return( *this );
00550 }
00551
00552 SICPPSDK_INLINE CQuaternionf& CQuaternionf::InvertInPlace()
00553 {
00554 return Invert(*this);
00555 }
00556
00557 SICPPSDK_INLINE CQuaternionf& CQuaternionf::Invert( const CQuaternionf &in_Quat)
00558 {
00559 return Conjugate(in_Quat);
00560 }
00561
00562 SICPPSDK_INLINE CQuaternionf& CQuaternionf::SetIdentity()
00563 {
00564 m_W = 1.0;
00565 m_X = m_Y = m_Z = 0.0;
00566
00567 return( *this );
00568 }
00569
00570 SICPPSDK_INLINE CQuaternionf& CQuaternionf::Copy( const CQuaternionf &in_Quat )
00571 {
00572 return *this = in_Quat;
00573 }
00574
00575 SICPPSDK_INLINE void CQuaternionf::Get
00576 (
00577 float &io_W,
00578 float &io_X,
00579 float &io_Y,
00580 float &io_Z
00581 ) const
00582 {
00583 io_W = m_W;
00584 io_X = m_X;
00585 io_Y = m_Y;
00586 io_Z = m_Z;
00587 }
00588
00589 SICPPSDK_INLINE void CQuaternionf::Get( CVector4f &io_XYZWVector ) const
00590 {
00591 io_XYZWVector.Set( m_X, m_Y, m_Z, m_W);
00592 }
00593
00594 SICPPSDK_INLINE CQuaternionf& CQuaternionf::Set
00595 (
00596 float in_W,
00597 float in_X,
00598 float in_Y,
00599 float in_Z
00600 )
00601 {
00602 m_W = in_W;
00603 m_X = in_X;
00604 m_Y = in_Y;
00605 m_Z = in_Z;
00606
00607 return *this;
00608 }
00609
00610 SICPPSDK_INLINE CQuaternionf& CQuaternionf::Set( const CVector3f &in_XYZVector )
00611 {
00612 m_W = 1.0;
00613 m_X = in_XYZVector.GetX();
00614 m_Y = in_XYZVector.GetY();
00615 m_Z = in_XYZVector.GetZ();
00616
00617 return *this;
00618 }
00619
00620 SICPPSDK_INLINE CQuaternionf& CQuaternionf::Set( const CVector4f &in_XYZWVector )
00621 {
00622 m_W = in_XYZWVector.GetW();
00623 m_X = in_XYZWVector.GetX();
00624 m_Y = in_XYZWVector.GetY();
00625 m_Z = in_XYZWVector.GetZ();
00626
00627 return *this;
00628 }
00629
00630 SICPPSDK_INLINE float CQuaternionf::GetValue( short in_nIndex ) const
00631 {
00632 assert(in_nIndex >= 0 && in_nIndex < 4);
00633
00634 switch (in_nIndex)
00635 {
00636 case 0: return m_W;
00637 case 1: return m_X;
00638 case 2: return m_Y;
00639 case 3: return m_Z;
00640 }
00641
00642 return 0.0;
00643 }
00644
00645 SICPPSDK_INLINE CQuaternionf& CQuaternionf::SetValue( short in_nIndex, float newVal)
00646 {
00647 assert(in_nIndex >= 0 && in_nIndex < 4);
00648
00649 switch (in_nIndex)
00650 {
00651 case 0: m_W = newVal; break;
00652 case 1: m_X = newVal; break;
00653 case 2: m_Y = newVal; break;
00654 case 3: m_Z = newVal; break;
00655
00656 }
00657
00658 return *this;
00659 }
00660
00661 SICPPSDK_INLINE float CQuaternionf::GetW() const
00662 {
00663 return m_W;
00664 }
00665
00666 SICPPSDK_INLINE CQuaternionf& CQuaternionf::PutW( float newVal)
00667 {
00668 m_W = newVal;
00669
00670 return *this;
00671 }
00672
00673 SICPPSDK_INLINE float CQuaternionf::GetZ() const
00674 {
00675 return m_Z;
00676 }
00677
00678 SICPPSDK_INLINE CQuaternionf& CQuaternionf::PutZ( float newVal)
00679 {
00680 m_Z = newVal;
00681 return *this;
00682 }
00683
00684 SICPPSDK_INLINE float CQuaternionf::GetY() const
00685 {
00686 return m_Y;
00687 }
00688
00689 SICPPSDK_INLINE CQuaternionf& CQuaternionf::PutY( float newVal)
00690 {
00691 m_Y = newVal;
00692 return *this;
00693 }
00694
00695
00696 SICPPSDK_INLINE float CQuaternionf::GetX() const
00697 {
00698 return m_X;
00699 }
00700
00701 SICPPSDK_INLINE CQuaternionf& CQuaternionf::PutX( float newVal)
00702 {
00703 m_X = newVal;
00704 return *this;
00705 }
00706
00707 SICPPSDK_INLINE CQuaternionf& CQuaternionf::NormalizeInPlace()
00708 {
00709 float rLen = GetSquaredLength();
00710
00711 if( fabs( rLen - 1.0f ) >= PicoEPS )
00712 {
00713 if( rLen < PicoEPS )
00714 {
00715 m_X = m_Y = m_Z = 0.0;
00716 m_W = 1.0;
00717 }
00718 else
00719 {
00720 rLen = 1.0f / sqrt( rLen );
00721 m_W *= rLen;
00722 m_X *= rLen;
00723 m_Y *= rLen;
00724 m_Z *= rLen;
00725
00726 LimitValue( m_W, -1.0, 1.0 );
00727 }
00728 }
00729 else
00730 {
00731 LimitValue( m_W, -1.0, 1.0 );
00732 }
00733
00734 return( *this );
00735 }
00736
00737 SICPPSDK_INLINE CQuaternionf& CQuaternionf::Slerp
00738 (
00739 const CQuaternionf& in_quatStart,
00740 const CQuaternionf& in_quatEnd,
00741 const float in_fU
00742 )
00743 {
00744 float fDot, fScale1, fScale2;
00745 bool bNegate = false;
00746
00747 fDot = in_quatStart.Dot( in_quatEnd );
00748 if ( fDot < 0.0 )
00749 {
00750 fDot = -fDot;
00751 bNegate = true;
00752 }
00753
00754 if( fDot >= ( 1.0f - MicroEPS ) )
00755 {
00756 fScale1 = 1.0f - in_fU;
00757 fScale2 = in_fU;
00758 }
00759 else
00760 {
00761 float fAngle, fFactor;
00762
00763 LimitValue( fDot, -1.0, 1.0 );
00764 fAngle = acos( fDot );
00765 fFactor = 1.0f / sin( fAngle );
00766
00767 fScale1 = sin( (1.0f - in_fU) * fAngle ) * fFactor;
00768 fScale2 = sin( in_fU * fAngle ) * fFactor;
00769 }
00770
00771 if( bNegate == true )
00772 fScale2 = -fScale2;
00773
00774 m_W = fScale1 * in_quatStart.m_W + fScale2 * in_quatEnd.m_W;
00775 m_X = fScale1 * in_quatStart.m_X + fScale2 * in_quatEnd.m_X;
00776 m_Y = fScale1 * in_quatStart.m_Y + fScale2 * in_quatEnd.m_Y;
00777 m_Z = fScale1 * in_quatStart.m_Z + fScale2 * in_quatEnd.m_Z;
00778
00779 return( *this );
00780 }
00781
00782 SICPPSDK_INLINE float CQuaternionf::Dot( const CQuaternionf& in_quat ) const
00783 {
00784 return( GetW() * in_quat.GetW() +
00785 GetX() * in_quat.GetX() +
00786 GetY() * in_quat.GetY() +
00787 GetZ() * in_quat.GetZ() );
00788 }
00789
00790 SICPPSDK_INLINE bool CQuaternionf::EpsilonEquals( const CQuaternionf& in_quat, const float in_fEpsilon ) const
00791 {
00792 return( fabs( GetW() - in_quat.GetW() ) < in_fEpsilon &&
00793 fabs( GetX() - in_quat.GetX() ) < in_fEpsilon &&
00794 fabs( GetY() - in_quat.GetY() ) < in_fEpsilon &&
00795 fabs( GetZ() - in_quat.GetZ() ) < in_fEpsilon );
00796 }
00797
00798 };
00799 };
00800
00801 #endif // __XSIQUATERNIONF_H__