Quater.inl

Go to the documentation of this file.
00001 /******************************************************************************
00002 *       SOFA, Simulation Open-Framework Architecture, version 1.0 beta 3      *
00003 *                (c) 2006-2008 MGH, INRIA, USTL, UJF, CNRS                    *
00004 *                                                                             *
00005 * This library is free software; you can redistribute it and/or modify it     *
00006 * under the terms of the GNU Lesser General Public License as published by    *
00007 * the Free Software Foundation; either version 2.1 of the License, or (at     *
00008 * your option) any later version.                                             *
00009 *                                                                             *
00010 * This library is distributed in the hope that it will be useful, but WITHOUT *
00011 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or       *
00012 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License *
00013 * for more details.                                                           *
00014 *                                                                             *
00015 * You should have received a copy of the GNU Lesser General Public License    *
00016 * along with this library; if not, write to the Free Software Foundation,     *
00017 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.          *
00018 *******************************************************************************
00019 *                              SOFA :: Framework                              *
00020 *                                                                             *
00021 * Authors: M. Adam, J. Allard, B. Andre, P-J. Bensoussan, S. Cotin, C. Duriez,*
00022 * H. Delingette, F. Falipou, F. Faure, S. Fonteneau, L. Heigeas, C. Mendoza,  *
00023 * M. Nesme, P. Neumann, J-P. de la Plata Alcade, F. Poyer and F. Roy          *
00024 *                                                                             *
00025 * Contact information: contact@sofa-framework.org                             *
00026 ******************************************************************************/
00027 #ifndef SOFA_HELPER_QUATER_INL
00028 #define SOFA_HELPER_QUATER_INL
00029 
00030 #include "Quater.h"
00031 #include <cstdio>
00032 #include <math.h>
00033 #include <iostream>
00034 
00035 namespace sofa
00036 {
00037 
00038 namespace helper
00039 {
00040 
00041 #define RENORMCOUNT 50
00042 
00043 // Constructor 
00044 template<class Real>
00045 Quater<Real>::Quater()
00046 {
00047     _q[0] = _q[1] = _q[2] = _q[3] = 0.0;
00048 }
00049 
00050 template<class Real>
00051 Quater<Real>::Quater(Real x, Real y, Real z, Real w)
00052 {
00053     _q[0] = x;
00054     _q[1] = y;
00055     _q[2] = z;
00056     _q[3] = w;
00057 }
00058 
00059 template<class Real>
00060 Quater<Real>::Quater( const defaulttype::Vec<3,Real>& axis, Real angle )
00061 {
00062     axisToQuat(axis,angle);
00063 }
00064 
00065 // Destructor
00066 template<class Real>
00067 Quater<Real>::~Quater()
00068 {
00069 }
00070 
00077 template<class Real>
00078 //Quater<Real> operator+(Quater<Real> q1, Quater<Real> q2) const
00079 Quater<Real> Quater<Real>::operator+(const Quater<Real> &q1) const
00080 {
00081     static int  count   = 0;
00082 
00083     Real        t1[4], t2[4], t3[4];
00084     Real        tf[4];
00085     Quater<Real>    ret;
00086 
00087     t1[0] = _q[0] * q1._q[3];
00088     t1[1] = _q[1] * q1._q[3];
00089     t1[2] = _q[2] * q1._q[3];
00090 
00091     t2[0] = q1._q[0] * _q[3];
00092     t2[1] = q1._q[1] * _q[3];
00093     t2[2] = q1._q[2] * _q[3];
00094 
00095     // cross product t3 = q2 x q1
00096     t3[0] = (q1._q[1] * _q[2]) - (q1._q[2] * _q[1]);
00097     t3[1] = (q1._q[2] * _q[0]) - (q1._q[0] * _q[2]);
00098     t3[2] = (q1._q[0] * _q[1]) - (q1._q[1] * _q[0]);
00099     // end cross product
00100 
00101     tf[0] = t1[0] + t2[0] + t3[0];
00102     tf[1] = t1[1] + t2[1] + t3[1];
00103     tf[2] = t1[2] + t2[2] + t3[2];
00104     tf[3] = _q[3] * q1._q[3] -
00105             (_q[0] * q1._q[0] + _q[1] * q1._q[1] + _q[2] * q1._q[2]);
00106 
00107     ret._q[0] = tf[0];
00108     ret._q[1] = tf[1];
00109     ret._q[2] = tf[2];
00110     ret._q[3] = tf[3];
00111 
00112     if (++count > RENORMCOUNT)
00113     {
00114         count = 0;
00115         ret.normalize();
00116     }
00117 
00118     return ret;
00119 }
00120 
00121 template<class Real>
00122 //Quater<Real> operator*(const Quater<Real>& q1, const Quater<Real>& q2) const
00123 Quater<Real> Quater<Real>::operator*(const Quater<Real>& q1) const
00124 {
00125     Quater<Real>    ret;
00126 
00127     ret._q[3] = _q[3] * q1._q[3] -
00128                 (_q[0] * q1._q[0] +
00129                  _q[1] * q1._q[1] +
00130                  _q[2] * q1._q[2]);
00131     ret._q[0] = _q[3] * q1._q[0] +
00132                 _q[0] * q1._q[3] +
00133                 _q[1] * q1._q[2] -
00134                 _q[2] * q1._q[1];
00135     ret._q[1] = _q[3] * q1._q[1] +
00136                 _q[1] * q1._q[3] +
00137                 _q[2] * q1._q[0] -
00138                 _q[0] * q1._q[2];
00139     ret._q[2] = _q[3] * q1._q[2] +
00140                 _q[2] * q1._q[3] +
00141                 _q[0] * q1._q[1] -
00142                 _q[1] * q1._q[0];
00143 
00144     return ret;
00145 }
00146 
00147 template<class Real>
00148 Quater<Real> Quater<Real>::operator*(const Real& r) const
00149 {
00150   Quater<Real>  ret;
00151   ret[0] = _q[0] * r;
00152   ret[1] = _q[1] * r;
00153   ret[2] = _q[2] * r;
00154   ret[3] = _q[3] * r;
00155   return ret;
00156 }
00157 
00158 template<class Real>
00159 Quater<Real> Quater<Real>::quatVectMult(const defaulttype::Vec<3,Real>& vect)
00160 {
00161     Quater<Real>    ret;
00162 
00163     ret._q[3] = (Real) (-(_q[0] * vect[0] + _q[1] * vect[1] + _q[2] * vect[2]));
00164     ret._q[0] = (Real) (_q[3] * vect[0] + _q[1] * vect[2] - _q[2] * vect[1]);
00165     ret._q[1] = (Real) (_q[3] * vect[1] + _q[2] * vect[0] - _q[0] * vect[2]);
00166     ret._q[2] = (Real) (_q[3] * vect[2] + _q[0] * vect[1] - _q[1] * vect[0]);
00167 
00168     return ret;
00169 }
00170 
00171 template<class Real>
00172 Quater<Real> Quater<Real>::vectQuatMult(const defaulttype::Vec<3,Real>& vect)
00173 {
00174     Quater<Real>    ret;
00175 
00176     ret[3] = (Real) (-(vect[0] * _q[0] + vect[1] * _q[1] + vect[2] * _q[2])); 
00177     ret[0] = (Real) (vect[0] * _q[3] + vect[1] * _q[2] - vect[2] * _q[1]);
00178     ret[1] = (Real) (vect[1] * _q[3] + vect[2] * _q[0] - vect[0] * _q[2]);
00179     ret[2] = (Real) (vect[2] * _q[3] + vect[0] * _q[1] - vect[1] * _q[0]);
00180 
00181     return ret;
00182 }
00183 
00184 template<class Real>
00185 Quater<Real> Quater<Real>::inverse() const
00186 {
00187     Quater<Real>    ret;
00188 
00189     Real        norm    = sqrt(_q[0] * _q[0] +
00190                                _q[1] * _q[1] +
00191                                _q[2] * _q[2] +
00192                                _q[3] * _q[3]);
00193 
00194     if (norm != 0.0f)
00195     {
00196         norm = 1.0f / norm;
00197         ret._q[3] = _q[3] * norm;
00198         for (int i = 0; i < 3; i++)
00199         {
00200             ret._q[i] = -_q[i] * norm;
00201         }
00202     }
00203     else
00204     {
00205         for (int i = 0; i < 4; i++)
00206         {
00207             ret._q[i] = 0.0;
00208         }
00209     }
00210 
00211     return ret;
00212 }
00213 
00217 template<class Real>
00218 void Quater<Real>::normalize()
00219 {
00220     int     i;
00221     Real    mag;
00222 
00223     mag = (_q[0] * _q[0] + _q[1] * _q[1] + _q[2] * _q[2] + _q[3] * _q[3]);
00224   if( mag != 0)
00225   {
00226       for (i = 0; i < 4; i++)
00227       {
00228         _q[i] /= sqrt(mag);
00229       }
00230   }
00231 }
00232 
00233 template<class Real>
00234 void Quater<Real>::fromMatrix(const defaulttype::Matrix3 &m)
00235 {
00236   Real tr, s;
00237 
00238   tr = (Real)(m.x().x() + m.y().y() + m.z().z());
00239 
00240   // check the diagonal
00241   if (tr > 0)
00242   {
00243     s = (float)sqrt (tr + 1);
00244     _q[3] = s * 0.5f; // w OK
00245     s = 0.5f / s;
00246     _q[0] = (Real)((m.z().y() - m.y().z()) * s); // x OK
00247     _q[1] = (Real)((m.x().z() - m.z().x()) * s); // y OK
00248     _q[2] = (Real)((m.y().x() - m.x().y()) * s); // z OK
00249   }
00250   else
00251   {
00252     if (m.y().y() > m.x().x() && m.z().z() <= m.y().y())
00253     {
00254       s = (Real)sqrt ((m.y().y() - (m.z().z() + m.x().x())) + 1.0f);
00255 
00256       _q[1] = s * 0.5f; // y OK
00257 
00258       if (s != 0.0f)
00259         s = 0.5f / s;
00260 
00261       _q[2] = (Real)((m.y().z() + m.z().y()) * s); // z OK
00262       _q[0] = (Real)((m.x().y() + m.y().x()) * s); // x OK
00263       _q[3] = (Real)((m.x().z() - m.z().x()) * s); // w OK
00264     }
00265     else if ((m.y().y() <= m.x().x()  &&  m.z().z() > m.x().x())  ||  (m.z().z() > m.y().y()))
00266     {
00267       s = (Real)sqrt ((m.z().z() - (m.x().x() + m.y().y())) + 1.0f);
00268 
00269       _q[2] = s * 0.5f; // z OK
00270 
00271       if (s != 0.0f)
00272         s = 0.5f / s;
00273 
00274       _q[0] = (Real)((m.z().x() + m.x().z()) * s); // x OK
00275       _q[1] = (Real)((m.y().z() + m.z().y()) * s); // y OK
00276       _q[3] = (Real)((m.y().x() - m.x().y()) * s); // w OK
00277     }
00278     else
00279     {
00280       s = (Real)sqrt ((m.x().x() - (m.y().y() + m.z().z())) + 1.0f);
00281 
00282       _q[0] = s * 0.5f; // x OK
00283 
00284       if (s != 0.0f)
00285           s = 0.5f / s;
00286 
00287       _q[1] = (Real)((m.x().y() + m.y().x()) * s); // y OK
00288       _q[2] = (Real)((m.z().x() + m.x().z()) * s); // z OK
00289       _q[3] = (Real)((m.z().y() - m.y().z()) * s); // w OK
00290     }
00291   }
00292 }
00293 
00294 // template<class Real> template<class Mat33>
00295 //     void Quater<Real>::toMatrix(Mat33 &m) const
00296 // {
00297 //  m[0][0] = (1.0 - 2.0 * (_q[1] * _q[1] + _q[2] * _q[2]));
00298 //  m[0][1] = (2.0 * (_q[0] * _q[1] - _q[2] * _q[3]));
00299 //  m[0][2] = (2.0 * (_q[2] * _q[0] + _q[1] * _q[3]));
00300 // 
00301 //  m[1][0] = (2.0 * (_q[0] * _q[1] + _q[2] * _q[3]));
00302 //  m[1][1] = (1.0 - 2.0 * (_q[2] * _q[2] + _q[0] * _q[0]));
00303 //  m[1][2] = (float) (2.0 * (_q[1] * _q[2] - _q[0] * _q[3]));
00304 // 
00305 //  m[2][0] = (float) (2.0 * (_q[2] * _q[0] - _q[1] * _q[3]));
00306 //  m[2][1] = (float) (2.0 * (_q[1] * _q[2] + _q[0] * _q[3]));
00307 //  m[2][2] = (float) (1.0 - 2.0 * (_q[1] * _q[1] + _q[0] * _q[0]));
00308 // }
00309 
00311 template<class Real>
00312 void Quater<Real>::buildRotationMatrix(Real m[4][4]) const
00313 {
00314     m[0][0] = (1.0f - 2.0f * (_q[1] * _q[1] + _q[2] * _q[2]));
00315     m[0][1] = (2.0f * (_q[0] * _q[1] - _q[2] * _q[3]));
00316     m[0][2] = (2.0f * (_q[2] * _q[0] + _q[1] * _q[3]));
00317     m[0][3] = 0;
00318 
00319     m[1][0] = (2.0f * (_q[0] * _q[1] + _q[2] * _q[3]));
00320     m[1][1] = (1.0f - 2.0f * (_q[2] * _q[2] + _q[0] * _q[0]));
00321     m[1][2] = (2.0f * (_q[1] * _q[2] - _q[0] * _q[3]));
00322     m[1][3] = 0;
00323 
00324     m[2][0] = (2.0f * (_q[2] * _q[0] - _q[1] * _q[3]));
00325     m[2][1] = (2.0f * (_q[1] * _q[2] + _q[0] * _q[3]));
00326     m[2][2] = (1.0f - 2.0f * (_q[1] * _q[1] + _q[0] * _q[0]));
00327     m[2][3] = 0;
00328 
00329     m[3][0] = 0;
00330     m[3][1] = 0;
00331     m[3][2] = 0;
00332     m[3][3] = 1;
00333 }
00335 /*template<class Real>
00336 void Quater<Real>::writeOpenGlMatrix(double *m) const
00337 {
00338     m[0*4+0] = (1.0 - 2.0 * (_q[1] * _q[1] + _q[2] * _q[2]));
00339     m[0*4+1] = (2.0 * (_q[0] * _q[1] - _q[2] * _q[3]));
00340     m[0*4+2] = (2.0 * (_q[2] * _q[0] + _q[1] * _q[3]));
00341     m[0*4+3] = 0.0f;
00342 
00343     m[1*4+0] = (2.0 * (_q[0] * _q[1] + _q[2] * _q[3]));
00344     m[1*4+1] = (1.0 - 2.0 * (_q[2] * _q[2] + _q[0] * _q[0]));
00345     m[1*4+2] = (float) (2.0 * (_q[1] * _q[2] - _q[0] * _q[3]));
00346     m[1*4+3] = 0.0f;
00347 
00348     m[2*4+0] = (float) (2.0 * (_q[2] * _q[0] - _q[1] * _q[3]));
00349     m[2*4+1] = (float) (2.0 * (_q[1] * _q[2] + _q[0] * _q[3]));
00350     m[2*4+2] = (float) (1.0 - 2.0 * (_q[1] * _q[1] + _q[0] * _q[0]));
00351     m[2*4+3] = 0.0f;
00352 
00353     m[3*4+0] = 0.0f;
00354     m[3*4+1] = 0.0f;
00355     m[3*4+2] = 0.0f;
00356     m[3*4+3] = 1.0f;
00357 }
00358 */
00360 template<class Real>
00361 void Quater<Real>::writeOpenGlMatrix(double *m) const
00362 {
00363     m[0*4+0] = (1.0f - 2.0f * (_q[1] * _q[1] + _q[2] * _q[2]));
00364     m[1*4+0] = (2.0f * (_q[0] * _q[1] - _q[2] * _q[3]));
00365     m[2*4+0] = (2.0f * (_q[2] * _q[0] + _q[1] * _q[3]));
00366     m[3*4+0] = 0.0f;
00367 
00368     m[0*4+1] = (2.0f * (_q[0] * _q[1] + _q[2] * _q[3]));
00369     m[1*4+1] = (1.0f - 2.0f * (_q[2] * _q[2] + _q[0] * _q[0]));
00370     m[2*4+1] = (float) (2.0f * (_q[1] * _q[2] - _q[0] * _q[3]));
00371     m[3*4+1] = 0.0f;
00372 
00373     m[0*4+2] = (float) (2.0f * (_q[2] * _q[0] - _q[1] * _q[3]));
00374     m[1*4+2] = (float) (2.0f * (_q[1] * _q[2] + _q[0] * _q[3]));
00375     m[2*4+2] = (float) (1.0f - 2.0f * (_q[1] * _q[1] + _q[0] * _q[0]));
00376     m[3*4+2] = 0.0f;
00377 
00378     m[0*4+3] = 0.0f;
00379     m[1*4+3] = 0.0f;
00380     m[2*4+3] = 0.0f;
00381     m[3*4+3] = 1.0f;
00382 }
00383 
00385 template<class Real>
00386 void Quater<Real>::writeOpenGlMatrix(float *m) const
00387 {
00388     m[0*4+0] = (float) (1.0f - 2.0f * (_q[1] * _q[1] + _q[2] * _q[2]));
00389     m[1*4+0] = (float) (2.0f * (_q[0] * _q[1] - _q[2] * _q[3]));
00390     m[2*4+0] = (float) (2.0f * (_q[2] * _q[0] + _q[1] * _q[3]));
00391     m[3*4+0] = 0.0f;
00392 
00393     m[0*4+1] = (float) (2.0f * (_q[0] * _q[1] + _q[2] * _q[3]));
00394     m[1*4+1] = (float) (1.0f - 2.0f * (_q[2] * _q[2] + _q[0] * _q[0]));
00395     m[2*4+1] = (float) (2.0f * (_q[1] * _q[2] - _q[0] * _q[3]));
00396     m[3*4+1] = 0.0f;
00397 
00398     m[0*4+2] = (float) (2.0f * (_q[2] * _q[0] - _q[1] * _q[3]));
00399     m[1*4+2] = (float) (2.0f * (_q[1] * _q[2] + _q[0] * _q[3]));
00400     m[2*4+2] = (float) (1.0f - 2.0f * (_q[1] * _q[1] + _q[0] * _q[0]));
00401     m[3*4+2] = 0.0f;
00402 
00403     m[0*4+3] = 0.0f;
00404     m[1*4+3] = 0.0f;
00405     m[2*4+3] = 0.0f;
00406     m[3*4+3] = 1.0f;
00407 }
00408 
00410 template<class Real>
00411 Quater<Real> Quater<Real>::axisToQuat(defaulttype::Vec<3,Real> a, Real phi)
00412 {
00413     a = a / a.norm();
00414     _q[0] = (Real)a.x();
00415     _q[1] = (Real)a.y();
00416     _q[2] = (Real)a.z();
00417 
00418     _q[0] = _q[0] * (Real)sin(phi / 2.0);
00419     _q[1] = _q[1] * (Real)sin(phi / 2.0);
00420     _q[2] = _q[2] * (Real)sin(phi / 2.0);
00421 
00422     _q[3] = (Real)cos(phi / 2.0);
00423 
00424     return *this;
00425 }
00426 
00427 template<class Real>
00428 defaulttype::Vec<3,Real> Quater<Real>::toEulerVector() const
00429 {
00430     Quater<Real> q = *this;
00431     q.normalize();
00432 
00433     double angle = acos(q._q[3]) * 2;
00434 
00435     defaulttype::Vec<3,Real> v(q._q[0], q._q[1], q._q[2]);
00436 
00437     double norm = sqrt( (double) (v.x() * v.x() + v.y() * v.y() + v.z() * v.z()) );
00438     if (norm > 0.0005){
00439         v /= norm;
00440         v *= angle;
00441     }
00442 
00443     return v;
00444 }
00445 
00447 //template<class Real>
00448 //    std::ostream& operator<<(std::ostream& out, Quater<Real> Q)
00449 //{
00450 //  return (out << "(" << Q._q[0] << "," << Q._q[1] << "," << Q._q[2] << ","
00451 //              << Q._q[3] << ")");
00452 //}
00453 
00455 template<class Real>
00456 void Quater<Real>::print()
00457 {
00458     printf("(%f, %f ,%f, %f)\n", _q[0], _q[1], _q[2], _q[3]);
00459 }
00460 
00461 template<class Real>
00462 void Quater<Real>::operator+=(const Quater<Real>& q2)
00463 {
00464     static int  count   = 0;
00465 
00466     Real t1[4], t2[4], t3[4];
00467     Quater<Real> q1 = (*this);
00468     t1[0] = q1._q[0] * q2._q[3];
00469     t1[1] = q1._q[1] * q2._q[3];
00470     t1[2] = q1._q[2] * q2._q[3];
00471 
00472     t2[0] = q2._q[0] * q1._q[3];
00473     t2[1] = q2._q[1] * q1._q[3];
00474     t2[2] = q2._q[2] * q1._q[3];
00475 
00476     // cross product t3 = q2 x q1
00477     t3[0] = (q2._q[1] * q1._q[2]) - (q2._q[2] * q1._q[1]);
00478     t3[1] = (q2._q[2] * q1._q[0]) - (q2._q[0] * q1._q[2]);
00479     t3[2] = (q2._q[0] * q1._q[1]) - (q2._q[1] * q1._q[0]);
00480     // end cross product
00481 
00482     _q[0] = t1[0] + t2[0] + t3[0];
00483     _q[1] = t1[1] + t2[1] + t3[1];
00484     _q[2] = t1[2] + t2[2] + t3[2];
00485     _q[3] = q1._q[3] * q2._q[3] -
00486            (q1._q[0] * q2._q[0] + q1._q[1] * q2._q[1] + q1._q[2] * q2._q[2]);
00487 
00488     if (++count > RENORMCOUNT)
00489     {
00490         count = 0;
00491         normalize();
00492     }
00493 }
00494 
00495 template<class Real>
00496 void Quater<Real>::operator*=(const Quater<Real>& q1)
00497 {
00498     Quater<Real> q2 = *this;
00499         _q[3] = q2._q[3] * q1._q[3] -
00500         (q2._q[0] * q1._q[0] +
00501          q2._q[1] * q1._q[1] +
00502          q2._q[2] * q1._q[2]);
00503     _q[0] = q2._q[3] * q1._q[0] +
00504         q2._q[0] * q1._q[3] +
00505         q2._q[1] * q1._q[2] -
00506         q2._q[2] * q1._q[1];
00507     _q[1] = q2._q[3] * q1._q[1] +
00508         q2._q[1] * q1._q[3] +
00509         q2._q[2] * q1._q[0] -
00510         q2._q[0] * q1._q[2];
00511     _q[2] = q2._q[3] * q1._q[2] +
00512         q2._q[2] * q1._q[3] +
00513         q2._q[0] * q1._q[1] -
00514         q2._q[1] * q1._q[0];
00515 }
00516 
00517 
00518 } // namespace helper
00519 
00520 } // namespace sofa
00521 
00522 #endif

Generated on Sun Nov 23 02:29:30 2008 for Sofa by  doxygen 1.5.7.1