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 #include "xsi_vector4f.h"
    00017 #include "xsi_vector3f.h"
    00018
    00019 namespace XSI {
    00020
    00021 namespace MATH {
    00022
    00023 class CRotation3f;
    00024
    00025 //*****************************************************************************
    00036 //*****************************************************************************
    00037 class SICPPSDKDECL CQuaternionf
    00038 {
    00039 public:
    00044     SICPPSDK_INLINE CQuaternionf();
    00045
    00049     SICPPSDK_INLINE CQuaternionf( const CQuaternionf& in_quaternion );
    00050
    00052     ~CQuaternionf() {};
    00053
    00058     SICPPSDK_INLINE CQuaternionf & operator=( const CQuaternionf & in_quaternion);
    00059
    00066     SICPPSDK_INLINE CQuaternionf( const float in_W, const float in_X, const float in_Y, const float in_Z );
    00067
    00072     SICPPSDK_INLINE CQuaternionf( const CVector3f& in_vct );
    00073
    00077     SICPPSDK_INLINE CQuaternionf( const CVector4f& in_vct );
    00078
    00084     SICPPSDK_INLINE bool Equals( const CQuaternionf &in_Quat ) const;
    00085
    00091     SICPPSDK_INLINE bool EpsilonEquals( const CQuaternionf& in_quat, const float in_fEpsilon ) const;
    00092
    00098     SICPPSDK_INLINE bool operator == ( const CQuaternionf &in_Quat ) const;
    00099
    00107     SICPPSDK_INLINE bool operator < ( const CQuaternionf& in_Quat ) const;
    00108
    00114     SICPPSDK_INLINE CQuaternionf& operator *= ( const CQuaternionf &in_Quat );
    00115
    00121     SICPPSDK_INLINE CQuaternionf& Mul( const CQuaternionf &in_Quat );
    00122
    00128     SICPPSDK_INLINE CQuaternionf& Mul( const CQuaternionf &in_Quat1, const CQuaternionf &in_Quat2);
    00129
    00134     SICPPSDK_INLINE float Dot( const CQuaternionf& in_quat1 ) const;
    00135
    00142     SICPPSDK_INLINE CQuaternionf& Slerp( const CQuaternionf& in_quatStart, const CQuaternionf& in_quatEnd, const float in_fU );
    00143
    00149     SICPPSDK_INLINE CQuaternionf& operator -= ( const CQuaternionf &in_Quat );
    00150
    00156     SICPPSDK_INLINE CQuaternionf& SubInPlace( const CQuaternionf &in_Quat );
    00157
    00164     SICPPSDK_INLINE CQuaternionf& Sub( const CQuaternionf &in_Quat1,  const CQuaternionf &in_Quat2);
    00165
    00170     SICPPSDK_INLINE CQuaternionf& NegateInPlace();
    00171
    00177     SICPPSDK_INLINE CQuaternionf& Negate( const CQuaternionf &in_Quat);
    00178
    00183     SICPPSDK_INLINE float GetSquaredLength() const;
    00184
    00189     SICPPSDK_INLINE float GetLength() const;
    00190
    00195     SICPPSDK_INLINE CQuaternionf& operator += ( const CQuaternionf &in_Quat);
    00196
    00201     SICPPSDK_INLINE CQuaternionf& AddInPlace( const CQuaternionf &in_Quat );
    00202
    00209     SICPPSDK_INLINE CQuaternionf& Add( const CQuaternionf &in_Quat1,  const CQuaternionf &in_Quat2);
    00210
    00215     SICPPSDK_INLINE CQuaternionf& ConjugateInPlace();
    00216
    00222     SICPPSDK_INLINE CQuaternionf& Conjugate( const CQuaternionf &in_Quat);
    00223
    00228     SICPPSDK_INLINE CQuaternionf& InvertInPlace();
    00229
    00235     SICPPSDK_INLINE CQuaternionf& Invert( const CQuaternionf &in_Quat);
    00236
    00240     SICPPSDK_INLINE CQuaternionf& SetIdentity();
    00241
    00246     SICPPSDK_INLINE CQuaternionf& Copy( const CQuaternionf &in_Quat );
    00247
    00251     SICPPSDK_INLINE CQuaternionf& NormalizeInPlace();
    00252
    00259     SICPPSDK_INLINE void Get( float &out_W, float &out_X, float &out_Y, float &out_Z ) const;
    00260
    00264     SICPPSDK_INLINE CVector3f GetVector3() const;
    00265
    00269     SICPPSDK_INLINE CVector4f GetVector4() const;
    00270
    00274     SICPPSDK_INLINE void Get( CVector4f &io_XYZWVector ) const;
    00275
    00283     SICPPSDK_INLINE CQuaternionf& Set( float in_W,  float in_X,  float in_Y,  float in_Z);
    00284
    00290     SICPPSDK_INLINE CQuaternionf& Set( const CVector3f &in_XYZVector );
    00291
    00297     SICPPSDK_INLINE CQuaternionf& Set( const CVector4f &in_XYZWVector );
    00298
    00305     SICPPSDK_INLINE float GetValue( short in_nIndex ) const;
    00306
    00314     SICPPSDK_INLINE CQuaternionf& SetValue( short in_nIndex, float newVal);
    00315
    00319     SICPPSDK_INLINE float GetW() const;
    00320
    00325     SICPPSDK_INLINE CQuaternionf& PutW( float newVal);
    00326
    00330     SICPPSDK_INLINE float GetZ() const;
    00331
    00336     SICPPSDK_INLINE CQuaternionf& PutZ( float newVal);
    00337
    00341     SICPPSDK_INLINE float GetY() const;
    00342
    00347     SICPPSDK_INLINE CQuaternionf& PutY( float newVal);
    00348
    00352     SICPPSDK_INLINE float GetX() const;
    00353
    00358     SICPPSDK_INLINE CQuaternionf& PutX( float newVal);
    00359
    00366     SICPPSDK_INLINE bool operator !=(const CQuaternionf & in_quat ) const;
    00367
    00368 private:
    00369     float m_W, m_X, m_Y, m_Z;
    00370 };
    00371
    00372 //inline functions
    00373 SICPPSDK_INLINE CQuaternionf::CQuaternionf()
    00374 {
    00375     SetIdentity();
    00376 }
    00377
    00378 SICPPSDK_INLINE CQuaternionf::CQuaternionf( const CQuaternionf& in_quaternion)
    00379 {
    00380     *this = in_quaternion;
    00381 }
    00382
    00383 SICPPSDK_INLINE CQuaternionf& CQuaternionf::operator=( const CQuaternionf & in_Quat )
    00384 {
    00385     m_W = in_Quat.m_W;
    00386     m_X = in_Quat.m_X;
    00387     m_Y = in_Quat.m_Y;
    00388     m_Z = in_Quat.m_Z;
    00389
    00390     return *this;
    00391 }
    00392
    00393 SICPPSDK_INLINE CQuaternionf::CQuaternionf( const float in_W, const float in_X, const float in_Y, const float in_Z )
    00394 {
    00395     Set( in_W, in_X, in_Y, in_Z );
    00396 }
    00397
    00398 SICPPSDK_INLINE CQuaternionf::CQuaternionf( const XSI::MATH::CVector3f& in_vct )
    00399 {
    00400     Set( in_vct );
    00401 }
    00402
    00403 SICPPSDK_INLINE CQuaternionf::CQuaternionf( const XSI::MATH::CVector4f& in_vct )
    00404 {
    00405     Set( in_vct );
    00406 }
    00407
    00408 SICPPSDK_INLINE bool CQuaternionf::Equals( const CQuaternionf &in_Quat ) const
    00409 {
    00410     return (this == &in_Quat) ? true :
    00411         (m_W == in_Quat.m_W &&
    00412         m_X == in_Quat.m_X &&
    00413         m_Y == in_Quat.m_Y &&
    00414         m_Z == in_Quat.m_Z );
    00415 }
    00416
    00417 SICPPSDK_INLINE bool CQuaternionf::operator == ( const CQuaternionf &in_Quat ) const
    00418 {
    00419     return Equals(in_Quat);
    00420 }
    00421
    00422 SICPPSDK_INLINE bool CQuaternionf::operator < ( const CQuaternionf& in_Quat) const
    00423 {
    00424     if ( m_W != in_Quat.m_W ) return m_W < in_Quat.m_W;
    00425     if ( m_Z != in_Quat.m_Z ) return m_Z < in_Quat.m_Z;
    00426     if ( m_Y != in_Quat.m_Y ) return m_Y < in_Quat.m_Y;
    00427     if ( m_X != in_Quat.m_X ) return m_X < in_Quat.m_X;
    00428     return false;
    00429 }
    00430
    00431 SICPPSDK_INLINE bool CQuaternionf::operator != ( const CQuaternionf &in_Quat ) const
    00432 {
    00433     return ! Equals( in_Quat );
    00434 }
    00435
    00436 SICPPSDK_INLINE CQuaternionf& CQuaternionf::operator *= ( const CQuaternionf &in_Quat )
    00437 {
    00438
    00439     return Mul(*this, in_Quat);
    00440 }
    00441
    00442 SICPPSDK_INLINE CQuaternionf& CQuaternionf::Mul( const CQuaternionf &in_Quat )
    00443 {
    00444     return Mul(*this, in_Quat);
    00445 }
    00446
    00447 SICPPSDK_INLINE CQuaternionf& CQuaternionf::Mul
    00448 (
    00449     const CQuaternionf &in_Quat1,
    00450     const CQuaternionf &in_Quat2
    00451 )
    00452 {
    00453     float dW, dX, dY, dZ;
    00454
    00455     dW = in_Quat1.m_W * in_Quat2.m_W - in_Quat1.m_X * in_Quat2.m_X -
    00456         in_Quat1.m_Y * in_Quat2.m_Y - in_Quat1.m_Z * in_Quat2.m_Z ;
    00457
    00458     dX = in_Quat1.m_W * in_Quat2.m_X + in_Quat2.m_W * in_Quat1.m_X +
    00459         in_Quat1.m_Y * in_Quat2.m_Z - in_Quat2.m_Y * in_Quat1.m_Z ;
    00460
    00461     dY = in_Quat1.m_W * in_Quat2.m_Y + in_Quat2.m_W * in_Quat1.m_Y -
    00462         in_Quat1.m_X * in_Quat2.m_Z + in_Quat2.m_X * in_Quat1.m_Z ;
    00463
    00464     dZ = in_Quat1.m_W * in_Quat2.m_Z + in_Quat2.m_W * in_Quat1.m_Z +
    00465         in_Quat1.m_X * in_Quat2.m_Y - in_Quat2.m_X * in_Quat1.m_Y ;
    00466
    00467     m_W = dW; m_X = dX; m_Y = dY; m_Z = dZ;
    00468
    00469     return *this;
    00470 }
    00471
    00472 SICPPSDK_INLINE CQuaternionf& CQuaternionf::operator -= ( const CQuaternionf &in_Quat )
    00473 {
    00474     return Sub(*this, in_Quat );
    00475 }
    00476
    00477 SICPPSDK_INLINE CQuaternionf& CQuaternionf::SubInPlace( const CQuaternionf &in_Quat )
    00478 {
    00479     return Sub(*this, in_Quat );
    00480 }
    00481
    00482 SICPPSDK_INLINE CQuaternionf& CQuaternionf::Sub
    00483 (
    00484     const CQuaternionf &in_Quat1,
    00485     const CQuaternionf &in_Quat2
    00486 )
    00487 {
    00488     m_W = in_Quat1.m_W - in_Quat2.m_W;
    00489     m_X = in_Quat1.m_X - in_Quat2.m_X;
    00490     m_Y = in_Quat1.m_Y - in_Quat2.m_Y;
    00491     m_Z = in_Quat1.m_Z - in_Quat2.m_Z;
    00492
    00493     return *this;
    00494 }
    00495
    00496 SICPPSDK_INLINE CQuaternionf& CQuaternionf::NegateInPlace()
    00497 {
    00498    return Negate(*this);
    00499 }
    00500
    00501 SICPPSDK_INLINE CQuaternionf& CQuaternionf::Negate( const CQuaternionf &in_Quat)
    00502 {
    00503    m_W = -(in_Quat.m_W);
    00504    m_X = -(in_Quat.m_X);
    00505    m_Y = -(in_Quat.m_Y);
    00506    m_Z = -(in_Quat.m_Z);
    00507
    00508    return( *this );
    00509 }
    00510
    00511 SICPPSDK_INLINE float CQuaternionf::GetSquaredLength() const
    00512 {
    00513     return( m_W * m_W + m_X * m_X + m_Y * m_Y + m_Z * m_Z );
    00514 }
    00515
    00516 SICPPSDK_INLINE float CQuaternionf::GetLength() const
    00517 {
    00518     return( sqrt( GetSquaredLength() ) );
    00519 }
    00520
    00521 SICPPSDK_INLINE CQuaternionf& CQuaternionf::operator += ( const CQuaternionf &in_Quat)
    00522 {
    00523     return Add( *this,  in_Quat );
    00524 }
    00525
    00526 SICPPSDK_INLINE CQuaternionf& CQuaternionf::AddInPlace( const CQuaternionf &in_Quat )
    00527 {
    00528     return Add( *this,  in_Quat );
    00529 }
    00530
    00531 SICPPSDK_INLINE CQuaternionf& CQuaternionf::Add
    00532 (
    00533     const CQuaternionf &in_Quat1,
    00534     const CQuaternionf &in_Quat2
    00535 )
    00536 {
    00537     m_W = in_Quat1.m_W + in_Quat2.m_W;
    00538     m_X = in_Quat1.m_X + in_Quat2.m_X;
    00539     m_Y = in_Quat1.m_Y + in_Quat2.m_Y;
    00540     m_Z = in_Quat1.m_Z + in_Quat2.m_Z;
    00541     return *this;
    00542 }
    00543
    00544 SICPPSDK_INLINE CQuaternionf& CQuaternionf::ConjugateInPlace()
    00545 {
    00546     return Conjugate(*this);
    00547 }
    00548
    00549 SICPPSDK_INLINE CQuaternionf& CQuaternionf::Conjugate( const CQuaternionf &in_Quat)
    00550 {
    00551     m_W = in_Quat.m_W;
    00552     m_X = -in_Quat.m_X;
    00553     m_Y = -in_Quat.m_Y;
    00554     m_Z = -in_Quat.m_Z;
    00555
    00556     return( *this );
    00557 }
    00558
    00559 SICPPSDK_INLINE CQuaternionf& CQuaternionf::InvertInPlace()
    00560 {
    00561     return Invert(*this);
    00562 }
    00563
    00564 SICPPSDK_INLINE CQuaternionf& CQuaternionf::Invert( const CQuaternionf &in_Quat)
    00565 {
    00566     return Conjugate(in_Quat);
    00567 }
    00568
    00569 SICPPSDK_INLINE CQuaternionf& CQuaternionf::SetIdentity()
    00570 {
    00571     m_W = 1.0;
    00572     m_X = m_Y = m_Z = 0.0;
    00573
    00574     return( *this );
    00575 }
    00576
    00577 SICPPSDK_INLINE CQuaternionf&  CQuaternionf::Copy( const CQuaternionf &in_Quat )
    00578 {
    00579     return *this = in_Quat;
    00580 }
    00581
    00582 SICPPSDK_INLINE CVector3f CQuaternionf::GetVector3( ) const
    00583 {
    00584     return CVector3f( m_X, m_Y, m_Z);
    00585 }
    00586
    00587 SICPPSDK_INLINE CVector4f CQuaternionf::GetVector4( ) const
    00588 {
    00589     return CVector4f( m_X, m_Y, m_Z, m_W);
    00590 }
    00591
    00592 SICPPSDK_INLINE void CQuaternionf::Get
    00593 (
    00594     float &io_W,
    00595     float &io_X,
    00596     float &io_Y,
    00597     float &io_Z
    00598 ) const
    00599 {
    00600     io_W = m_W;
    00601     io_X = m_X;
    00602     io_Y = m_Y;
    00603     io_Z = m_Z;
    00604 }
    00605
    00606 SICPPSDK_INLINE void CQuaternionf::Get( CVector4f &io_XYZWVector ) const
    00607 {
    00608     io_XYZWVector.Set( m_X, m_Y, m_Z, m_W);
    00609 }
    00610
    00611 SICPPSDK_INLINE CQuaternionf& CQuaternionf::Set
    00612 (
    00613     float in_W,
    00614     float in_X,
    00615     float in_Y,
    00616     float in_Z
    00617 )
    00618 {
    00619     m_W = in_W;
    00620     m_X = in_X;
    00621     m_Y = in_Y;
    00622     m_Z = in_Z;
    00623
    00624     return *this;
    00625 }
    00626
    00627 SICPPSDK_INLINE CQuaternionf& CQuaternionf::Set( const CVector3f &in_XYZVector )
    00628 {
    00629     m_W = 1.0;
    00630     m_X = in_XYZVector.GetX();
    00631     m_Y = in_XYZVector.GetY();
    00632     m_Z = in_XYZVector.GetZ();
    00633
    00634     return *this;
    00635 }
    00636
    00637 SICPPSDK_INLINE CQuaternionf& CQuaternionf::Set( const CVector4f &in_XYZWVector )
    00638 {
    00639     m_W = in_XYZWVector.GetW();
    00640     m_X = in_XYZWVector.GetX();
    00641     m_Y = in_XYZWVector.GetY();
    00642     m_Z = in_XYZWVector.GetZ();
    00643
    00644     return *this;
    00645 }
    00646
    00647 SICPPSDK_INLINE float CQuaternionf::GetValue( short in_nIndex ) const
    00648 {
    00649     assert(in_nIndex >= 0 && in_nIndex < 4);
    00650
    00651     switch (in_nIndex)
    00652     {
    00653         case 0: return m_W;
    00654         case 1: return m_X;
    00655         case 2: return m_Y;
    00656         case 3: return m_Z;
    00657     }
    00658
    00659     return 0.0; // invalid index, return 0.0
    00660 }
    00661
    00662 SICPPSDK_INLINE CQuaternionf& CQuaternionf::SetValue( short in_nIndex,  float newVal)
    00663 {
    00664     assert(in_nIndex >= 0 && in_nIndex < 4);
    00665
    00666     switch (in_nIndex)
    00667     {
    00668         case 0:  m_W = newVal; break;
    00669         case 1:  m_X = newVal; break;
    00670         case 2:  m_Y = newVal; break;
    00671         case 3:  m_Z = newVal; break;
    00672         // note: do nothing when invalid index is provided
    00673     }
    00674
    00675     return *this;
    00676 }
    00677
    00678 SICPPSDK_INLINE float CQuaternionf::GetW() const
    00679 {
    00680     return m_W;
    00681 }
    00682
    00683 SICPPSDK_INLINE CQuaternionf& CQuaternionf::PutW( float newVal)
    00684 {
    00685     m_W = newVal;
    00686
    00687     return *this;
    00688 }
    00689
    00690 SICPPSDK_INLINE float CQuaternionf::GetZ() const
    00691 {
    00692     return m_Z;
    00693 }
    00694
    00695 SICPPSDK_INLINE CQuaternionf& CQuaternionf::PutZ( float newVal)
    00696 {
    00697     m_Z = newVal;
    00698     return *this;
    00699 }
    00700
    00701 SICPPSDK_INLINE float CQuaternionf::GetY() const
    00702 {
    00703     return m_Y;
    00704 }
    00705
    00706 SICPPSDK_INLINE CQuaternionf& CQuaternionf::PutY( float newVal)
    00707 {
    00708     m_Y = newVal;
    00709     return *this;
    00710 }
    00711
    00712
    00713 SICPPSDK_INLINE float CQuaternionf::GetX() const
    00714 {
    00715     return m_X;
    00716 }
    00717
    00718 SICPPSDK_INLINE CQuaternionf& CQuaternionf::PutX( float newVal)
    00719 {
    00720     m_X = newVal;
    00721     return *this;
    00722 }
    00723
    00724 SICPPSDK_INLINE CQuaternionf& CQuaternionf::NormalizeInPlace()
    00725 {
    00726    float rLen = GetSquaredLength();
    00727
    00728    if( fabs( rLen - 1.0f ) >= PicoEPS )
    00729    {
    00730       if( rLen < PicoEPS )
    00731       {
    00732          m_X = m_Y = m_Z = 0.0;
    00733          m_W = 1.0;
    00734       }
    00735       else
    00736       {
    00737          rLen = 1.0f / sqrt( rLen );
    00738          m_W *= rLen;
    00739          m_X *= rLen;
    00740          m_Y *= rLen;
    00741          m_Z *= rLen;
    00742
    00743          LimitValue( m_W, -1.0, 1.0 );
    00744       }
    00745    }
    00746    else
    00747    {
    00748         LimitValue( m_W, -1.0, 1.0 );
    00749    }
    00750
    00751    return( *this );
    00752 }
    00753
    00754 SICPPSDK_INLINE CQuaternionf& CQuaternionf::Slerp
    00755 (
    00756     const CQuaternionf& in_quatStart,
    00757     const CQuaternionf& in_quatEnd,
    00758     const float         in_fU
    00759 )
    00760 {
    00761    float fDot, fScale1, fScale2;
    00762    bool bNegate = false;
    00763
    00764    fDot = in_quatStart.Dot( in_quatEnd );
    00765    if ( fDot < 0.0 )
    00766    {
    00767       fDot = -fDot;
    00768       bNegate = true;
    00769    }
    00770
    00771    if( fDot >= ( 1.0f - MicroEPS ) )
    00772    {
    00773       fScale1 = 1.0f - in_fU;
    00774       fScale2 = in_fU;
    00775    }
    00776    else
    00777    {
    00778       float fAngle, fFactor;
    00779
    00780       LimitValue( fDot, -1.0, 1.0 );
    00781       fAngle = acos( fDot );
    00782       fFactor = 1.0f / sin( fAngle );
    00783
    00784       fScale1 = sin( (1.0f - in_fU) * fAngle ) * fFactor;
    00785       fScale2 = sin( in_fU * fAngle ) * fFactor;
    00786    }
    00787
    00788    if( bNegate == true )
    00789       fScale2 = -fScale2;
    00790
    00791    m_W = fScale1 * in_quatStart.m_W + fScale2 * in_quatEnd.m_W;
    00792    m_X = fScale1 * in_quatStart.m_X + fScale2 * in_quatEnd.m_X;
    00793    m_Y = fScale1 * in_quatStart.m_Y + fScale2 * in_quatEnd.m_Y;
    00794    m_Z = fScale1 * in_quatStart.m_Z + fScale2 * in_quatEnd.m_Z;
    00795
    00796    return( *this );
    00797 }
    00798
    00799 SICPPSDK_INLINE float CQuaternionf::Dot( const CQuaternionf& in_quat ) const
    00800 {
    00801    return( GetW() * in_quat.GetW() +
    00802            GetX() * in_quat.GetX() +
    00803            GetY() * in_quat.GetY() +
    00804            GetZ() * in_quat.GetZ() );
    00805 }
    00806
    00807 SICPPSDK_INLINE bool CQuaternionf::EpsilonEquals( const CQuaternionf& in_quat, const float in_fEpsilon ) const
    00808 {
    00809    return( fabs( GetW() - in_quat.GetW() ) < in_fEpsilon &&
    00810            fabs( GetX() - in_quat.GetX() ) < in_fEpsilon &&
    00811            fabs( GetY() - in_quat.GetY() ) < in_fEpsilon &&
    00812            fabs( GetZ() - in_quat.GetZ() ) < in_fEpsilon );
    00813 }
    00814
    00815 };
    00816 };
    00817
    00818 #endif // __XSIQUATERNIONF_H__