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