xsi_rotationf.h
Go to the documentation of this file.
00001 //*****************************************************************************
00011 //*****************************************************************************
00012 #ifndef __XSIROTATIONF_H__
00013 #define __XSIROTATIONF_H__
00014 
00015 #include "sicppsdk.h"
00016 #include "xsi_math.h"
00017 #include "xsi_vector3f.h"
00018 #include "xsi_vector4f.h"
00019 #include "xsi_matrix3f.h"
00020 #include "xsi_quaternionf.h"
00021 
00022 namespace XSI {
00023 
00024 namespace MATH {
00025 
00026 //*****************************************************************************
00036 //*****************************************************************************
00037 class SICPPSDKDECL CRotationf
00038 {
00039 public:
00042     enum RotationOrder
00043     {
00044         siXYZ = 0,  
00045         siXZY = 1,  
00046         siYXZ = 2,  
00047         siYZX = 3,  
00048         siZXY = 4,  
00049         siZYX = 5   
00050     };
00051 
00054     enum RotationRep
00055     {
00056         siQuaternionRot = 0,    
00057         siEulerRot,             
00058         siAxisAngleRot          
00059     };
00060 
00062     SICPPSDK_INLINE CRotationf();
00063 
00067     SICPPSDK_INLINE CRotationf( const CRotationf& in_rotation);
00068 
00074     SICPPSDK_INLINE CRotationf( const CVector3f &in_EulerAngles, const RotationOrder in_RotOrder = siXYZ);
00075 
00083     SICPPSDK_INLINE CRotationf( const float in_X, const float in_Y, const float in_Z, const RotationOrder in_RotOrder = siXYZ);
00084 
00089     SICPPSDK_INLINE CRotationf( const CQuaternionf &in_Quat );
00090 
00096     SICPPSDK_INLINE CRotationf( const CVector3f &in_Axis, const float in_Angle );
00097 
00099     SICPPSDK_INLINE ~CRotationf();
00100 
00105     SICPPSDK_INLINE CRotationf & operator=( const CRotationf & in_rotation);
00106 
00112     SICPPSDK_INLINE CVector3f GetXYZAngles(const RotationOrder in_Order) const;
00113 
00120     SICPPSDK_INLINE void GetXYZAngles( float &io_X, float &io_Y, float &io_Z ) const;
00121 
00126     SICPPSDK_INLINE CVector3f GetXYZAngles( ) const;
00127 
00131     SICPPSDK_INLINE RotationOrder GetOrder() const;
00132 
00137     SICPPSDK_INLINE void SetOrder( const RotationOrder in_rotOrder );
00138 
00142     SICPPSDK_INLINE RotationRep GetRepresentation() const;
00143 
00149     SICPPSDK_INLINE void SetRepresentation( const RotationRep in_rotRep, const RotationOrder in_order = siXYZ );
00150 
00161     SICPPSDK_INLINE CRotationf& Set( const RotationOrder in_order, const bool in_bCompensate = false );
00162 
00169     SICPPSDK_INLINE CRotationf& Set( const CVector3f &in_EulerAngles, const RotationOrder in_Order = siXYZ);
00170 
00179     SICPPSDK_INLINE CRotationf& Set( const float in_X, const float in_Y, const float in_Z, const RotationOrder in_Order = siXYZ);
00180 
00186     SICPPSDK_INLINE CRotationf& Set( const CQuaternionf &in_Quat);
00187 
00192     SICPPSDK_INLINE CRotationf& Mul( const CRotationf &in_rot );
00193 
00199     SICPPSDK_INLINE CRotationf& Mul( const CRotationf &in_rot1, const CRotationf &in_rot2 );
00200 
00205     SICPPSDK_INLINE CRotationf& Mul( const float in_scalar );
00206 
00211     SICPPSDK_INLINE CRotationf& LeftMul( const CRotationf &in_rot );
00212 
00219     SICPPSDK_INLINE CRotationf& Interpolate( const CRotationf& in_rot1, const CRotationf& in_rot2, const float in_u );
00220 
00226     SICPPSDK_INLINE CRotationf& Div ( const CRotationf& in_rot1, const float in_scalar );
00227 
00232     SICPPSDK_INLINE CRotationf& Div ( const float in_scalar );
00233 
00238     SICPPSDK_INLINE CRotationf& Div( const CRotationf& in_rot );
00239 
00245     SICPPSDK_INLINE CRotationf& Div( const CRotationf& in_rot1, const CRotationf& in_rot2 );
00246 
00250     SICPPSDK_INLINE CRotationf& Invert();
00251 
00256     SICPPSDK_INLINE CRotationf& Invert( const CRotationf &in_rot );
00257 
00262     SICPPSDK_INLINE CQuaternionf GetQuaternion() const;
00263 
00269     SICPPSDK_INLINE CRotationf& operator = ( const CQuaternionf &in_Quat );
00270 
00276     SICPPSDK_INLINE CVector3f GetAxisAngle( float &io_Angle) const;
00277 
00284     SICPPSDK_INLINE CRotationf& Set( const CVector3f &in_Axis,  const float in_Angle );
00285 
00288     SICPPSDK_INLINE void SetIdentity();
00289 
00295     SICPPSDK_INLINE bool Equals( const CRotationf &in_rot ) const;
00296 
00302     SICPPSDK_INLINE bool EpsilonEquals( const CRotationf& in_rot, const float in_fEpsilon ) const;
00303 
00309     SICPPSDK_INLINE bool operator == ( const CRotationf &in_rot ) const;
00310 
00316     SICPPSDK_INLINE bool operator !=(const CRotationf & in_rot ) const;
00317 
00325     SICPPSDK_INLINE bool operator < ( const CRotationf& in_rot ) const;
00326 
00327 private:
00328     SICPPSDK_INLINE void QuatToEuler( const CQuaternionf& in_quat, CVector3f& out_vct, const RotationOrder in_eOrder );
00329     SICPPSDK_INLINE void QuatToMat( const CQuaternionf& in_quat, CMatrix3f& out_mat );
00330     SICPPSDK_INLINE void AxisAngleToQuat( const CVector3f& in_vctAxis, const float in_fAngle, CQuaternionf& out_quat);
00331     SICPPSDK_INLINE void QuatToAxisAngle(const CQuaternionf& in_quat, CVector3f& out_vctAxis, float& out_fAngle );
00332 
00333     SICPPSDK_INLINE RotationOrder GetRotOrder() const;
00334 
00335     float m_X, m_Y, m_Z;
00336     union
00337     {
00338         float           m_W;            // Quaternion W component
00339         float           m_Angle;        // Angle for axis/angle
00340         RotationOrder   m_rotOrder;     // Euler rotation order
00341     };
00342     unsigned char m_rotRep;             // Rotation representation
00343 };
00344 
00345 SICPPSDK_INLINE CRotationf::CRotationf()
00346 {
00347     m_X = m_Y = m_Z = 0.0;
00348     m_W = 1.0;
00349     m_rotRep = siQuaternionRot;
00350 }
00351 
00352 SICPPSDK_INLINE CRotationf::CRotationf( const CRotationf& in_rotation)
00353 {
00354     *this = in_rotation;
00355 }
00356 
00357 SICPPSDK_INLINE CRotationf::CRotationf( const CQuaternionf& in_quat )
00358 {
00359     Set( in_quat );
00360 }
00361 
00362 SICPPSDK_INLINE CRotationf::CRotationf( const CVector3f &in_Angles, const RotationOrder in_Order)
00363 {
00364     Set( in_Angles, in_Order );
00365 }
00366 
00367 SICPPSDK_INLINE CRotationf::CRotationf( const CVector3f &in_Axis, const float in_fAngle )
00368 {
00369     Set( in_Axis, in_fAngle );
00370 }
00371 
00372 SICPPSDK_INLINE CRotationf::CRotationf( float in_fX, float in_fY, float in_fZ, const RotationOrder in_Order )
00373 {
00374     Set( in_fX, in_fY, in_fZ, in_Order );
00375 }
00376 
00377 SICPPSDK_INLINE CRotationf::~CRotationf()
00378 {
00379 }
00380 
00381 SICPPSDK_INLINE CRotationf& CRotationf::operator=( const CRotationf & in_rotation)
00382 {
00383     m_X = in_rotation.m_X;
00384     m_Y = in_rotation.m_Y;
00385     m_Z = in_rotation.m_Z;
00386     m_W = in_rotation.m_W;
00387     m_rotRep = in_rotation.m_rotRep;
00388     return *this;
00389 }
00390 
00391 SICPPSDK_INLINE CRotationf& CRotationf::Set( const CVector3f &in_AngleValues, const RotationOrder in_Order )
00392 {
00393     return Set( in_AngleValues.GetX(), in_AngleValues.GetY(), in_AngleValues.GetZ(), in_Order );
00394 }
00395 
00396 SICPPSDK_INLINE CRotationf& CRotationf::Set
00397 (
00398     const float in_fX,
00399     const float in_fY,
00400     const float in_fZ,
00401     const RotationOrder in_Order
00402 )
00403 {
00404     m_rotRep = siEulerRot;
00405     m_rotOrder = in_Order;
00406     m_X = in_fX; m_Y = in_fY; m_Z = in_fZ;
00407 
00408     return *this;
00409 }
00410 
00411 SICPPSDK_INLINE CRotationf& CRotationf::Set( const RotationOrder in_order, const bool in_bCompensate )
00412 {
00413     if ( m_rotRep != siEulerRot )
00414     {
00415         SetRepresentation( siEulerRot, in_bCompensate ? in_order : siXYZ );
00416     }
00417 
00418     if ( in_order != m_rotRep )
00419     {
00420         if ( in_bCompensate )
00421         {
00422             CMatrix3f vRotTmp;
00423             CVector3f vEuler( m_X, m_Y, m_Z );
00424             XSI::MATH::EulerToMat( vEuler, vRotTmp, (int)m_rotOrder );
00425 
00426             vEuler.SetNull( );
00427             XSI::MATH::MatToEuler( vRotTmp, vEuler, in_order );
00428             vEuler.Get( m_X, m_Y, m_Z );
00429         }
00430         m_rotOrder = in_order;
00431     }
00432     return *this;
00433 }
00434 
00435 SICPPSDK_INLINE CRotationf& CRotationf::Set( const CQuaternionf &in_Quat )
00436 {
00437     m_rotRep = siQuaternionRot;
00438 
00439     m_W = in_Quat.GetW();
00440     m_X = in_Quat.GetX();
00441     m_Y = in_Quat.GetY();
00442     m_Z = in_Quat.GetZ();
00443 
00444     return *this;
00445 }
00446 
00447 SICPPSDK_INLINE CRotationf::RotationOrder CRotationf::GetRotOrder() const
00448 {
00449     return ( m_rotRep == siEulerRot ? m_rotOrder : siXYZ );
00450 }
00451 
00452 SICPPSDK_INLINE CVector3f CRotationf::GetXYZAngles(const RotationOrder in_Order) const
00453 {
00454     CVector3f outV;
00455     if ( m_rotRep == siEulerRot && m_rotOrder == in_Order )
00456     {
00457         outV.Set( m_X, m_Y, m_Z );
00458     }
00459     else
00460     {
00461         CRotationf rot( *this );
00462         rot.Set( in_Order, true );
00463         outV.Set( rot.m_X, rot.m_Y, rot.m_Z );
00464     }
00465     return outV;
00466 }
00467 
00468 SICPPSDK_INLINE void CRotationf::GetXYZAngles( float &io_fX, float &io_fY, float &io_fZ ) const
00469 {
00470     CVector3f vEuler = GetXYZAngles( GetRotOrder() );
00471     vEuler.Get( io_fX, io_fY, io_fZ );
00472 }
00473 
00474 SICPPSDK_INLINE CVector3f CRotationf::GetXYZAngles() const
00475 {
00476     return GetXYZAngles( GetRotOrder() );
00477 }
00478 
00479 SICPPSDK_INLINE CRotationf& CRotationf::Mul( const CRotationf &in_rot )
00480 {
00481     return Mul( *this, in_rot );
00482 }
00483 
00484 SICPPSDK_INLINE CRotationf& CRotationf::Mul( const CRotationf &in_rot1, const CRotationf &in_rot2 )
00485 {
00486     CQuaternionf q1 = in_rot1.GetQuaternion();
00487     CQuaternionf q2 = in_rot2.GetQuaternion();
00488     q2.Mul( q1 ).NormalizeInPlace();
00489     return Set( q2 );
00490 }
00491 
00492 SICPPSDK_INLINE CRotationf& CRotationf::Mul( const float in_scalar )
00493 {
00494     switch (m_rotRep)
00495     {
00496         case siQuaternionRot:
00497         case siEulerRot:
00498         {
00499             CRotationf identity;
00500             Interpolate( identity, *this, in_scalar );
00501         }
00502         break;
00503 
00504         case siAxisAngleRot:
00505         {
00506             m_Angle *= in_scalar;
00507         }
00508         break;
00509     }
00510     return *this;
00511 }
00512 
00513 SICPPSDK_INLINE CRotationf& CRotationf::Div( const CRotationf &in_rot )
00514 {
00515     return Div( *this, in_rot );
00516 }
00517 
00518 SICPPSDK_INLINE CRotationf& CRotationf::Div( const float in_scalar )
00519 {
00520     return Mul( 1.0f/in_scalar );
00521 }
00522 
00523 SICPPSDK_INLINE CRotationf& CRotationf::Div( const CRotationf &in_rot1, const CRotationf &in_rot2 )
00524 {
00525     CRotationf rotInv;
00526     return Mul( in_rot1, rotInv.Invert(in_rot2) );
00527 }
00528 
00529 SICPPSDK_INLINE CRotationf& CRotationf::LeftMul( const CRotationf &in_rot )
00530 {
00531     return Mul( in_rot, *this );
00532 }
00533 
00534 SICPPSDK_INLINE CRotationf& CRotationf::Interpolate ( const CRotationf& in_rot1, const CRotationf& in_rot2, const float in_u )
00535 {
00536     CQuaternionf q1 = in_rot1.GetQuaternion();
00537     CQuaternionf q2 = in_rot2.GetQuaternion();
00538     CQuaternionf q;
00539     q.Slerp( q1, q2, in_u );
00540     return Set( q );
00541 }
00542 
00543 SICPPSDK_INLINE CRotationf& CRotationf::Invert( )
00544 {
00545     static RotationOrder InvRotOrder[] = { siZYX, siYZX, siZXY, siXZY, siYXZ, siXYZ };
00546 
00547     switch (m_rotRep)
00548     {
00549         case siQuaternionRot:
00550             m_X = -m_X; m_Y = -m_Y; m_Z = -m_Z;
00551             break;
00552         case siEulerRot:
00553             m_rotOrder = InvRotOrder[m_rotOrder];
00554             m_X = -m_X; m_Y = -m_Y; m_Z = -m_Z;
00555             break;
00556         case siAxisAngleRot:
00557             m_Angle = -m_Angle;
00558             break;
00559     }
00560     return *this;
00561 }
00562 
00563 SICPPSDK_INLINE CRotationf& CRotationf::Invert( const CRotationf &in_rot )
00564 {
00565     *this = in_rot;
00566     return Invert( );
00567 }
00568 
00569 SICPPSDK_INLINE CVector3f CRotationf::GetAxisAngle( float &io_fAngle ) const
00570 {
00571     CVector3f out_axis;
00572     if ( m_rotRep == siAxisAngleRot )
00573     {
00574         out_axis.Set( m_X, m_Y, m_Z );
00575         io_fAngle = m_Angle;
00576     }
00577     else
00578     {
00579         CRotationf rot( *this );
00580         rot.SetRepresentation( siAxisAngleRot );
00581         out_axis.Set( rot.m_X, rot.m_Y, rot.m_Z );
00582         io_fAngle = rot.m_Angle;
00583     }
00584     return out_axis;
00585 }
00586 
00587 SICPPSDK_INLINE CRotationf& CRotationf::Set( const CVector3f &in_axis, const float in_fAngle )
00588 {
00589     m_rotRep = siAxisAngleRot;
00590     m_Angle = in_fAngle;
00591     in_axis.Get( m_X, m_Y, m_Z );
00592 
00593     return *this;
00594 }
00595 
00596 SICPPSDK_INLINE void CRotationf::SetIdentity()
00597 {
00598     switch (m_rotRep)
00599     {
00600         case siQuaternionRot:
00601             m_W = 1.0; m_X = m_Y = m_Z = 0.0;
00602             break;
00603         case siEulerRot:
00604             m_X = m_Y = m_Z = 0.0; m_rotOrder = siXYZ;
00605             break;
00606         case siAxisAngleRot:
00607             m_Angle = 0.0; m_X = 1.0; m_Y = m_Z = 0.0;
00608             break;
00609     }
00610 }
00611 
00612 SICPPSDK_INLINE CRotationf::RotationOrder CRotationf::GetOrder() const
00613 {
00614     return m_rotOrder;
00615 }
00616 
00617 SICPPSDK_INLINE CRotationf::RotationRep CRotationf::GetRepresentation() const
00618 {
00619     return (CRotationf::RotationRep)m_rotRep;
00620 }
00621 
00622 void CRotationf::SetRepresentation( const RotationRep in_rep, const RotationOrder in_order )
00623 {
00624     if ( m_rotRep != in_rep )
00625     {
00626         switch( in_rep )
00627         {
00628             case siQuaternionRot:
00629             {
00630                 CQuaternionf l_quat;
00631                 switch ( m_rotRep )
00632                 {
00633                     case siEulerRot:
00634                     {
00635                         CVector3f l_euler( m_X, m_Y, m_Z );
00636                         XSI::MATH::EulerToQuat( l_euler, l_quat, m_rotOrder );
00637                     }
00638                     break;
00639                     case siAxisAngleRot:
00640                     {
00641                         CVector3f l_axis( m_X, m_Y, m_Z );
00642                         if ( l_axis.GetLength() > MicroEPS )
00643                         {
00644                             l_axis.NormalizeInPlace();
00645                             AxisAngleToQuat( l_axis, m_Angle, l_quat );
00646                         }
00647                     }
00648                     break;
00649                 }
00650                 *this = l_quat;
00651             }
00652             break;
00653 
00654             case siEulerRot:
00655             {
00656                 CVector3f l_euler;
00657                 switch ( m_rotRep )
00658                 {
00659                     case siQuaternionRot:
00660                     {
00661                         CQuaternionf l_quat( m_W, m_X, m_Y, m_Z );
00662                         l_quat.NormalizeInPlace();
00663                         QuatToEuler( l_quat, l_euler, in_order );
00664                     }
00665                     break;
00666                     case siAxisAngleRot:
00667                     {
00668                         CQuaternionf l_quat;
00669                         CVector3f l_axis( m_X, m_Y, m_Z );
00670                         if ( l_axis.GetLength() > MicroEPS )
00671                         {
00672                             l_axis.NormalizeInPlace();
00673                             AxisAngleToQuat( l_axis, m_Angle, l_quat );
00674                         }
00675                         QuatToEuler( l_quat, l_euler, in_order );
00676                     }
00677                     break;
00678                 }
00679                 Set( l_euler, in_order );
00680             }
00681             break;
00682             case siAxisAngleRot:
00683             {
00684                 float l_angle = 0;
00685                 CVector3f l_axis;
00686                 switch ( m_rotRep )
00687                 {
00688                     case siQuaternionRot:
00689                     {
00690                         CQuaternionf l_quat( m_W, m_X, m_Y, m_Z );
00691                         l_quat.NormalizeInPlace();
00692                         QuatToAxisAngle( l_quat, l_axis, l_angle );
00693                     }
00694                     break;
00695 
00696                     case siEulerRot:
00697                     {
00698                         CQuaternionf l_quat;
00699                         CVector3f l_euler( m_X, m_Y, m_Z );
00700                         XSI::MATH::EulerToQuat( l_euler, l_quat, m_rotOrder );
00701                         QuatToAxisAngle( l_quat, l_axis, l_angle );
00702                     }
00703                     break;
00704                 }
00705 
00706                 if ( l_axis.IsNull() )
00707                 {
00708                     l_axis.Set(1.0, 0.0, 0.0); // If axis is undefined set it to a valid axis
00709                 }
00710                 Set( l_axis, l_angle );
00711             }
00712             break;
00713         }
00714     }
00715 }
00716 
00717 SICPPSDK_INLINE CQuaternionf CRotationf::GetQuaternion() const
00718 {
00719     CQuaternionf out_quat;
00720     if ( m_rotRep == siQuaternionRot )
00721     {
00722         out_quat.Set( m_W, m_X, m_Y, m_Z );
00723     }
00724     else
00725     {
00726         CRotationf rot( *this );
00727         rot.SetRepresentation( siQuaternionRot );
00728         out_quat.Set( rot.m_W, rot.m_X, rot.m_Y, rot.m_Z );
00729     }
00730     return out_quat;
00731 }
00732 
00733 SICPPSDK_INLINE CRotationf& CRotationf::operator = ( const CQuaternionf &in_Quat )
00734 {
00735     return Set( in_Quat );
00736 }
00737 
00738 SICPPSDK_INLINE bool CRotationf::Equals( const CRotationf &in_rot ) const
00739 {
00740     if (this == &in_rot) return true;
00741 
00742     CQuaternionf q1 = GetQuaternion();
00743     CQuaternionf q2 = in_rot.GetQuaternion();
00744 
00745     return (true == ( q1 == q2) );
00746 }
00747 
00748 SICPPSDK_INLINE bool CRotationf::EpsilonEquals( const CRotationf& in_rot, const float in_fEpsilon ) const
00749 {
00750     CRotationf r1( *this );
00751     CRotationf r2( in_rot );
00752     if ( r1.GetRepresentation() != r2.GetRepresentation() )
00753     {
00754         r2.SetRepresentation( r1.GetRepresentation() );
00755     }
00756     switch (r1.GetRepresentation())
00757     {
00758         case siQuaternionRot:
00759         {
00760             return r1.GetQuaternion().EpsilonEquals( r2.GetQuaternion(), in_fEpsilon );
00761         }
00762         case siEulerRot:
00763         {
00764             return ( r1.GetOrder() == r2.GetOrder() && r1.GetXYZAngles().EpsilonEquals( r2.GetXYZAngles(), in_fEpsilon ) );
00765         }
00766         case siAxisAngleRot:
00767         {
00768             float a1, a2;
00769             CVector3f v1 = r1.GetAxisAngle( a1 );
00770             CVector3f v2 = r2.GetAxisAngle( a2 );
00771             return ( fabs( a1 - a2 ) < in_fEpsilon && v1.EpsilonEquals( v2, in_fEpsilon ) );
00772         }
00773         default:
00774             break;
00775     }
00776     return false;
00777 }
00778 
00779 SICPPSDK_INLINE bool CRotationf::operator == ( const CRotationf &in_rot ) const
00780 {
00781     return Equals( in_rot );
00782 }
00783 
00784 SICPPSDK_INLINE bool CRotationf::operator != ( const CRotationf &in_rot ) const
00785 {
00786     return ! Equals( in_rot );
00787 }
00788 
00789 SICPPSDK_INLINE bool CRotationf::operator < ( const CRotationf& in_rot) const
00790 {
00791     if ( m_W != in_rot.m_W ) return m_W < in_rot.m_W;
00792     if ( m_Z != in_rot.m_Z ) return m_Z < in_rot.m_Z;
00793     if ( m_Y != in_rot.m_Y ) return m_Y < in_rot.m_Y;
00794     if ( m_X != in_rot.m_X ) return m_X < in_rot.m_X;
00795     if ( m_rotRep != in_rot.m_rotRep ) return m_rotRep < in_rot.m_rotRep;
00796 
00797     return false;
00798 }
00799 
00800 SICPPSDK_INLINE void CRotationf::QuatToMat( const CQuaternionf& in_quat, CMatrix3f& out_mat )
00801 {
00802     float d2X, d2Y, d2Z, d2X2, d2Y2, d2Z2, d2WX, d2WY, d2WZ, d2XY, d2XZ, d2YZ;
00803 
00804     d2X = (float)2.0 * in_quat.GetX();
00805     d2Y = (float)2.0 * in_quat.GetY();
00806     d2Z = (float)2.0 * in_quat.GetZ();
00807 
00808     d2X2 = d2X * in_quat.GetX();
00809     d2Y2 = d2Y * in_quat.GetY();
00810     d2Z2 = d2Z * in_quat.GetZ();
00811 
00812     d2WX = d2X * in_quat.GetW();
00813     d2WY = d2Y * in_quat.GetW();
00814     d2WZ = d2Z * in_quat.GetW();
00815     d2XY = d2X * in_quat.GetY();
00816     d2YZ = d2Y * in_quat.GetZ();
00817     d2XZ = d2Z * in_quat.GetX();
00818 
00819     out_mat.SetValue( 0, 0, (float)1.0 - d2Y2 - d2Z2 );
00820     out_mat.SetValue( 1, 1, (float)1.0 - d2X2 - d2Z2 );
00821     out_mat.SetValue( 2, 2, (float)1.0 - d2X2 - d2Y2 );
00822     out_mat.SetValue( 0, 1, d2XY + d2WZ );
00823     out_mat.SetValue( 1, 0, d2XY - d2WZ );
00824     out_mat.SetValue( 0, 2, d2XZ - d2WY );
00825     out_mat.SetValue( 2, 0, d2XZ + d2WY );
00826     out_mat.SetValue( 1, 2, d2YZ + d2WX );
00827     out_mat.SetValue( 2, 1, d2YZ - d2WX );
00828 }
00829 
00830 SICPPSDK_INLINE void CRotationf::QuatToEuler( const CQuaternionf& in_quat, CVector3f& out_vct, const RotationOrder in_eOrder )
00831 {
00832     CMatrix3f mat;
00833     QuatToMat( in_quat, mat );
00834     XSI::MATH::MatToEuler( mat, out_vct, in_eOrder);
00835 }
00836 
00837 SICPPSDK_INLINE void CRotationf::AxisAngleToQuat( const CVector3f& in_vctAxis, const float in_fAngle, CQuaternionf& out_quat)
00838 {
00839     float fCos, fSin;
00840     CVector3f vct(in_vctAxis);
00841 
00842     fCos = cos( in_fAngle * 0.5f );
00843     fSin = sin( in_fAngle * 0.5f );
00844 
00845     vct.SetLength( fSin );
00846     out_quat.Set( fCos, vct.GetX(), vct.GetY(), vct.GetZ() );
00847 }
00848 
00849 SICPPSDK_INLINE void CRotationf::QuatToAxisAngle(const CQuaternionf& in_quat, CVector3f& out_vctAxis, float& out_fAngle )
00850 {
00851     out_fAngle = (float)(2.0 * ::acos( in_quat.GetW() ));
00852 
00853     //from C3DRotation::GetAxisAngle();
00854     float fSin = (float)sin( 0.5f * out_fAngle );
00855 
00856     if( ::fabs( fSin ) < MicroEPS )
00857     {
00858         // If angle is almost zero, then axis of rotation is undefined.
00859         out_vctAxis.SetNull();
00860     }
00861     else
00862     {
00863         //Retrieve the axis of rotation
00864         fSin = 1.0f / fSin;
00865         out_vctAxis.PutX( in_quat.GetX() * fSin );
00866         out_vctAxis.PutY( in_quat.GetY() * fSin );
00867         out_vctAxis.PutZ( in_quat.GetZ() * fSin );
00868     }
00869 }
00870 
00871 };
00872 };
00873 
00874 #endif // __XSIROTATIONF_H__