00001 #pragma once
00002 
00003 #include "common.h"
00004 #include <math.h>
00005 #include "Vector.h"
00006 
00007 
00008 class Quaternion
00009 {
00010 public:
00011         Quaternion()
00012         {
00013                 Set(Vector(0.0f,0.0f,0.0f),0.0f);
00014         };
00015 
00016         Quaternion(const Vector &vecV, const float fS)
00017         {
00018                 Set(vecV,fS);
00019         };
00020 
00021         Quaternion(const Vector &vecV)
00022         {
00023                 Set(vecV,0.0f);
00024         };
00025 
00026         Quaternion(const float fAngle, const Vector &vecAxis)
00027         {
00028                 float fD = fAngle * 0.5f;
00029                 Set(vecAxis.GetNormalized() * sinf(fD),cosf(fD));
00030         };
00031 
00032         Quaternion(const Vector &vecFrom, const Vector &vecTo)
00033         {
00034                 const float fAngle = acosf(vecFrom.GetNormalized().GetDot(vecTo.GetNormalized()));
00035                 const Vector vecAxis = vecFrom.GetNormalized().GetCross(vecTo.GetNormalized());
00036                 (*this) = Quaternion(fAngle,vecAxis);
00037         };
00038 
00039         ~Quaternion()
00040         {
00041         };
00042 
00043         void Set(const Vector &vecV, const float fS)
00044         {
00045                 m_vecVector = vecV;
00046                 m_fScalar = fS;
00047                 normalize();
00048         };
00049 
00050         void SetVector(const Vector &vecV)
00051         {
00052                 Set(vecV,GetScalar());
00053         };
00054 
00055         void SetScalar(const float fS)
00056         {
00057                 Set(GetVector(),fS);
00058         };
00059 
00060         const Vector & GetVector() const
00061         {
00062                 return m_vecVector;
00063         };
00064 
00065         const float & GetScalar() const
00066         {
00067                 return m_fScalar;
00068         };
00069 
00070         const float GetMagnitude() const
00071         {
00072                 return sqrtf( GetScalar()*GetScalar() + GetVector().GetMagnitude() * GetVector().GetMagnitude());
00073         };
00074 
00075         const Quaternion GetNormalized() const
00076         {
00077                 Quaternion quaNew = *this;
00078                 float fMagnitude = quaNew.GetMagnitude();
00079 
00080                 if (fMagnitude > 0.0f)
00081                 {
00082                         quaNew.m_vecVector /= fMagnitude;
00083                         quaNew.m_fScalar /= fMagnitude;
00084                 }
00085 
00086                 return quaNew;
00087         };
00088 
00089         const Quaternion GetInverse() const
00090         {
00091                 return Quaternion(GetVector()*-1.0f,GetScalar()).GetNormalized();
00092         };
00093 
00094         void normalize()
00095         {
00096                 (*this) = GetNormalized();
00097         };
00098 
00099         void invert()
00100         {
00101                 (*this) = GetInverse();
00102         };
00103 
00104         const bool operator==(const Quaternion & quaOther) const
00105         {
00106                 return (GetVector() == quaOther.GetVector()) && (GetScalar() == quaOther.GetScalar());
00107         };
00108 
00109         const bool operator!=(const Quaternion & quaOther) const
00110         {
00111                 return !(*this == quaOther);
00112         };
00113 
00114         const Quaternion & operator*=(const float & fOther)
00115         {
00116                 Set(GetVector() * fOther,GetScalar() * fOther);
00117                 return *this;
00118         };
00119 
00120         const Quaternion & operator/=(const float & fOther)
00121         {
00122                 Set(GetVector() / fOther,GetScalar() / fOther);
00123                 return *this;
00124         };
00125 
00126         const Quaternion & operator+=(const Quaternion & quaOther)
00127         {
00128                 Set(GetVector() + quaOther.GetVector(),GetScalar() + quaOther.GetScalar());
00129                 return *this;
00130         };
00131 
00132         const Quaternion & operator-=(const Quaternion & quaOther)
00133         {
00134                 Set(GetVector() - quaOther.GetVector(),GetScalar() - quaOther.GetScalar());
00135                 return *this;
00136         };
00137 
00138         const Quaternion & operator*=(const Quaternion& quaOther)
00139         {
00140                 Set(
00141                         GetVector().GetCross(quaOther.GetVector()) + GetVector() * quaOther.GetScalar()  + quaOther.GetVector() * GetScalar(),
00142                         GetScalar() * quaOther.GetScalar() - GetVector().GetDot(quaOther.GetVector()));
00143                 return *this;
00144         };
00145 
00146         const Quaternion operator*(const float fOther) const
00147         {
00148                 Quaternion quaNew = *this;
00149                 quaNew *= fOther;
00150                 return quaNew;
00151         };
00152 
00153         const Quaternion operator/(const float fOther) const
00154         {
00155                 Quaternion quaNew = *this;
00156                 quaNew *= fOther;
00157                 return quaNew;
00158         };
00159 
00160         const Quaternion operator+(const Quaternion & quaOther) const
00161         {
00162                 Quaternion quaNew = *this;
00163                 quaNew += quaOther;
00164                 return quaNew;
00165         };
00166 
00167         const Quaternion operator-(const Quaternion & quaOther) const
00168         {
00169                 Quaternion quaNew = *this;
00170                 quaNew += quaOther;
00171                 return quaNew;
00172         };
00173 
00174         const Quaternion operator*(const Quaternion & quaOther) const
00175         {
00176                 Quaternion quaNew = *this;
00177                 quaNew *= quaOther;
00178                 return quaNew;
00179         };
00180 
00181         const Vector operator*(const Vector &vecOther) const
00182         {
00183                 Quaternion quaRotated = (*this * Quaternion(vecOther) * GetInverse());
00184                 return quaRotated.GetVector() * vecOther.GetMagnitude();
00185         };
00186 
00187 private:
00188         Vector m_vecVector;
00189         float m_fScalar;
00190 };
00191 
00192 
00193 inline std::ostream & operator << (std::ostream & os, const Quaternion & quaQuaternion)
00194 {
00195         os << "(" << quaQuaternion.GetVector() << ";" << quaQuaternion.GetScalar() << ")";
00196         return os;
00197 }
00198 
00199 inline std::istream & operator>> (std::istream & is, Quaternion & quaQuaternion)
00200 {
00201         Vector vecV;
00202         float fS;
00203 
00204         if (is >> eat("(") >> vecV >> eat(";") >> fS >> eat(")"))
00205                 quaQuaternion.Set(vecV,fS);
00206 
00207         return is;
00208 }