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__