KeosQuaternion.h

Go to the documentation of this file.
00001 /*
00002  * This source file is part of KEOS (Free 3D Engine)
00003  * For the latest info, see http://www.keosengine.org/
00004  * E-mails : thierry.vouriot@keosengine.org, yeri@keosengine.org
00005  *
00006  * This program is free software; you can redistribute it and/or modify it under
00007  * the terms of the GNU Lesser General Public License as published by the Free Software
00008  * Foundation; either version 2 of the License, or (at your option) any later
00009  * version.
00010  *
00011  * This program is distributed in the hope that it will be useful, but WITHOUT
00012  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00013  * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
00014  *
00015  * You should have received a copy of the GNU Lesser General Public License along with
00016  * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
00017  * Place - Suite 330, Boston, MA 02111-1307, USA, or go to
00018  * http://www.gnu.org/copyleft/lesser.txt.
00019  *
00020  */
00021 
00022 #ifndef KEOS_QUATERNION_H
00023 #define KEOS_QUATERNION_H
00024 
00025 #include "KeosPrerequisites.h"
00026 #include "KeosMatrix4.h"
00027 
00028 namespace Keos
00029 {
00030   //-----------------------------------------------------------------------
00034   class CQuaternion
00035   {
00036   public :
00037 
00040     CQuaternion(float X = 0.0f, float Y = 0.0f, float Z = 0.0f, float W = 1.0f);
00041 
00045     CQuaternion(const CMatrix4& Matrix);
00046 
00051     CQuaternion(const TVector3F& Axis, float Angle);
00052 
00055     void Identity();
00056 
00059     inline void Normalize();
00060 
00064     CQuaternion Conjugate() const;
00065 
00069     CMatrix4 ToMatrix() const;
00070 
00074     void FromMatrix(const CMatrix4& Matrix);
00075 
00080     void FromAxisAngle(const TVector3F& Axis, float Angle);
00081 
00086     void ToAxisAngle(TVector3F& Axis, float& Angle) const;
00087 
00093     void FromEulerAngles(float X, float Y, float Z);
00094 
00095     // Operators
00096     CQuaternion operator *(const CQuaternion& Quaternion) const;
00097     const CQuaternion& operator *=(const CQuaternion& Quaternion);
00098 
00099     float x;
00100     float y;
00101     float z;
00102     float w;
00103   };
00104 
00105   // Globals functions
00106   std::istream& operator >>(std::istream& Stream, CQuaternion& Quaternion);
00107   std::ostream& operator <<(std::ostream& Stream, const CQuaternion& Quaternion);
00108 
00109   //=======================================================================
00110   // CQuaternion inline functions
00111   //=======================================================================
00112 
00113   //-----------------------------------------------------------------------
00114   inline CQuaternion::CQuaternion(float X, float Y, float Z, float W) :
00115       x(X),
00116       y(Y),
00117       z(Z),
00118       w(W)
00119   {}
00120 
00121   //-----------------------------------------------------------------------
00122   inline CQuaternion::CQuaternion(const CMatrix4& Matrix)
00123   {
00124     FromMatrix(Matrix);
00125   }
00126 
00127   //-----------------------------------------------------------------------
00128   inline CQuaternion::CQuaternion(const TVector3F& Axis, float Angle)
00129   {
00130     FromAxisAngle(Axis, Angle);
00131   }
00132 
00133   //-----------------------------------------------------------------------
00134   inline void CQuaternion::Identity()
00135   {
00136     x = y = z = 0.0f;
00137     w = 1.0f;
00138   }
00139 
00140   //-----------------------------------------------------------------------
00141   inline void CQuaternion::Normalize()
00142   {
00143     float Norm = x * x + y * y + z * z + w * w;
00144 
00145     if (std::fabs(Norm) > std::numeric_limits<float>::epsilon())
00146     {
00147       x /= Norm;
00148       y /= Norm;
00149       z /= Norm;
00150       w /= Norm;
00151     }
00152   }
00153 
00154   //-----------------------------------------------------------------------
00155   inline CQuaternion CQuaternion::Conjugate() const
00156   {
00157     return CQuaternion(-x, -y, -z, w);
00158   }
00159 
00160   //-----------------------------------------------------------------------
00161   inline CMatrix4 CQuaternion::ToMatrix() const
00162   {
00163     float xx = x * x;
00164     float xy = x * y;
00165     float xz = x * z;
00166     float xw = x * w;
00167     float yy = y * y;
00168     float yz = y * z;
00169     float yw = y * w;
00170     float zz = z * z;
00171     float zw = z * w;
00172 
00173     return CMatrix4(1 - 2 * (yy + zz),     2 * (xy - zw),     2 * (xy + yw), 0,
00174                     2 * (xy + zw), 1 - 2 * (xx + zz),     2 * (yz - xw), 0,
00175                     2 * (xz - yw),     2 * (yz + xw), 1 - 2 * (xx + yy), 0,
00176                     0,                 0,                 0, 1);
00177   }
00178 
00179   //-----------------------------------------------------------------------
00180   inline void CQuaternion::FromMatrix(const CMatrix4& Matrix)
00181   {
00182     float Trace = Matrix(0, 0) + Matrix(1, 1) + Matrix(2, 2) + 1;
00183 
00184     if (Trace > 0)
00185     {
00186       float s = 0.5f / std::sqrtf(Trace);
00187       x = (Matrix(2, 1) - Matrix(1, 2)) * s;
00188       y = (Matrix(0, 2) - Matrix(2, 0)) * s;
00189       z = (Matrix(1, 0) - Matrix(0, 1)) * s;
00190       w = 0.25f / s;
00191     }
00192     else
00193     {
00194       if ((Matrix(0, 0) > Matrix(1, 1) && (Matrix(0, 0) > Matrix(2, 2)))
00195         {
00196           float s = std::sqrt(1 + Matrix(0, 0) - Matrix(1, 1) - Matrix(2, 2)) * 2;
00197             x = 0.5f / s;
00198             y = (Matrix(0, 1) + Matrix(1, 0)) / s;
00199             z = (Matrix(0, 2) + Matrix(2, 0)) / s;
00200             w = (Matrix(1, 2) + Matrix(2, 1)) / s;
00201           }
00202           else if (Matrix(1, 1) > Matrix(2, 2))
00203         {
00204           float s = std::sqrt(1 - Matrix(0, 0) + Matrix(1, 1) - Matrix(2, 2)) * 2;
00205             x = (Matrix(0, 1) + Matrix(1, 0)) / s;
00206             y = 0.5f / s;
00207             z = (Matrix(1, 2) + Matrix(2, 1)) / s;
00208             w = (Matrix(0, 2) + Matrix(2, 0)) / s;
00209           }
00210           else
00211           {
00212             float s = std::sqrt(1 - Matrix(0, 0) - Matrix(1, 1) + Matrix(2, 2)) * 2;
00213             x = (Matrix(0, 2) + Matrix(2, 0)) / s;
00214             y = (Matrix(1, 2) + Matrix(2, 1)) / s;
00215             z = 0.5f / s;
00216             w = (Matrix(0, 1) + Matrix(1, 0)) / s;
00217           }
00218         }
00219       }
00220 
00221       //-----------------------------------------------------------------------
00222       inline void CQuaternion::FromAxisAngle(const TVector3F& Axis, float Angle)
00223       {
00224         float Cos = std::cos(Angle / 2);
00225         float Sin = std::sin(Angle / 2);
00226 
00227         x = Axis.x * Sin;
00228         y = Axis.y * Sin;
00229         z = Axis.z * Sin;
00230         w = Cos;
00231 
00232         Normalize();
00233       }
00234 
00235       //-----------------------------------------------------------------------
00236       inline void CQuaternion::ToAxisAngle(TVector3F& Axis, float& Angle) const
00237       {
00238         // Calcul de l'angle
00239         Angle = std::acosf(w) * 2;
00240 
00241         // Calcul de l'axe
00242         float Norm = std::sqrtf(x * x + y * y + z * z);
00243         if (std::fabs(Norm) > std::numeric_limits<float>::epsilon())
00244         {
00245           Axis.x = x / Norm;
00246           Axis.y = y / Norm;
00247           Axis.z = z / Norm;
00248         }
00249         else
00250         {
00251           Axis.x = 0.0f;
00252           Axis.y = 1.0f;
00253           Axis.z = 0.0f;
00254         }
00255       }
00256 
00257       //-----------------------------------------------------------------------
00258       inline void CQuaternion::FromEulerAngles(float X, float Y, float Z)
00259       {
00260         CQuaternion Qx(TVector3F(1, 0, 0), X);
00261         CQuaternion Qy(TVector3F(0, 1, 0), Y);
00262         CQuaternion Qz(TVector3F(0, 0, 1), Z);
00263 
00264         *this = Qx * Qy * Qz;
00265       }
00266 
00267       //-----------------------------------------------------------------------
00268       inline CQuaternion CQuaternion::operator *(const CQuaternion& Quaternion) const
00269       {
00270         return CQuaternion(w * Quaternion.x + x * Quaternion.w + y * Quaternion.z - z * Quaternion.y,
00271                            w * Quaternion.y + y * Quaternion.w + z * Quaternion.x - x * Quaternion.z,
00272                            w * Quaternion.z + z * Quaternion.w + x * Quaternion.y - y * Quaternion.x,
00273                            w * Quaternion.w - x * Quaternion.x - y * Quaternion.y - z * Quaternion.z);
00274       }
00275 
00276       //-----------------------------------------------------------------------
00277       inline const CQuaternion& CQuaternion::operator *=(const CQuaternion& Quaternion)
00278       {
00279         *this = *this * Quaternion;
00280 
00281         return *this;
00282       }
00283 
00284       //-----------------------------------------------------------------------
00285       std::istream& operator >>(std::istream& Stream, CQuaternion& Quaternion)
00286       {
00287         return Stream >> Quaternion.x >> Quaternion.y >> Quaternion.z >> Quaternion.w;
00288       }
00289 
00290       //-----------------------------------------------------------------------
00291       std::ostream& operator <<(std::ostream& Stream, const CQuaternion& Quaternion)
00292       {
00293         return Stream << Quaternion.x << " " << Quaternion.y << " " << Quaternion.z << " " << Quaternion.w;
00294       }
00295 
00296     } // namespace Keos
00297 
00298 
00299 #endif // KEOS_QUATERNION_H

Generated on Fri Mar 9 14:29:02 2007 for Keos by  doxygen 1.5.1-p1