# xsi_quaternionf.h

Go to the documentation of this file.

    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 //inline functions
    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; // invalid index, 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         // note: do nothing when invalid index is provided
    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__