Advertisement
makiolo

Euler to Quaternion

Nov 16th, 2011
213
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 3.07 KB | None | 0 0
  1. El uso sería algo así:
  2.  
  3. Ogre::Quaternion q1 = fromEulerToQuaternion( Ogre::Vector3(45, 90, -90) ); // por defecto en grados
  4.  
  5. Tengo un enumerado muy tonto, para especificar la unidad en la que van.
  6.  
  7. typedef enum
  8. {
  9.     DEGREE,
  10.     RADIAN
  11. } MeasureEnum;
  12.  
  13. Mi función seria esta, que usa 2 funciones de Ogre:
  14.  
  15. Ogre::Quaternion fromEulerToQuaternion(const Ogre::Vector3& rotation, MeasureEnum measure = MeasureEnum::DEGREE)
  16. {
  17.     // inicialmente es la identidad
  18.     Ogre::Quaternion ret;
  19.    
  20.     switch(measure)
  21.     {
  22.     case RADIAN:
  23.         // orden ZYX
  24.         ret = ret * Ogre::Quaternion(Ogre::Radian(rotation.z), Ogre::Vector3(0, 0, 1));
  25.         ret = ret * Ogre::Quaternion(Ogre::Radian(rotation.y), Ogre::Vector3(0, 1, 0));
  26.         ret = ret * Ogre::Quaternion(Ogre::Radian(rotation.x), Ogre::Vector3(1, 0, 0));
  27.         break;
  28.     case DEGREE:
  29.     default:
  30.         // orden ZYX
  31.         ret = ret * Ogre::Quaternion(Ogre::Degree(rotation.z), Ogre::Vector3(0, 0, 1));
  32.         ret = ret * Ogre::Quaternion(Ogre::Degree(rotation.y), Ogre::Vector3(0, 1, 0));
  33.         ret = ret * Ogre::Quaternion(Ogre::Degree(rotation.x), Ogre::Vector3(1, 0, 0));
  34.         break;
  35.     }
  36.     return ret;
  37. }
  38.  
  39. Lo que hace Ogre en los constructores es crear el Quaternion a partir de un angulo y un eje con este algoritmo:
  40.  
  41. void Quaternion::FromAngleAxis (const Radian& rfAngle, const Vector3& rkAxis)
  42. {
  43.     // assert:  axis[] is unit length
  44.     //
  45.     // The quaternion representing the rotation is
  46.     //   q = cos(A/2)+sin(A/2)*(x*i+y*j+z*k)
  47.  
  48.     Radian fHalfAngle ( 0.5*rfAngle );
  49.     Real fSin = Math::Sin(fHalfAngle);
  50.     w = Math::Cos(fHalfAngle);
  51.     x = fSin*rkAxis.x;
  52.     y = fSin*rkAxis.y;
  53.     z = fSin*rkAxis.z;
  54. }
  55.  
  56. Tambien se usa la multiplicación de Quaterniones que según Ogre es así:
  57.  
  58. Quaternion Quaternion::operator* (const Quaternion& rkQ) const
  59. {
  60.     // NOTE:  Multiplication is not generally commutative, so in most
  61.     // cases p*q != q*p.
  62.  
  63.     return Quaternion
  64.     (
  65.         w * rkQ.w - x * rkQ.x - y * rkQ.y - z * rkQ.z,
  66.         w * rkQ.x + x * rkQ.w + y * rkQ.z - z * rkQ.y,
  67.         w * rkQ.y + y * rkQ.w + z * rkQ.x - x * rkQ.z,
  68.         w * rkQ.z + z * rkQ.w + x * rkQ.y - y * rkQ.x
  69.     );
  70. }
  71.  
  72. // Por último, como al final OpenGL lo que pide son matrices, (y es medio normal que algunos engines se quedan en la matriz) tendrias que convertir el Quaternion a Matriz.
  73. // En Ogre lo hacen así:
  74.  
  75. void Quaternion::ToRotationMatrix (Matrix3& kRot) const
  76. {
  77.     Real fTx  = x+x;
  78.     Real fTy  = y+y;
  79.     Real fTz  = z+z;
  80.     Real fTwx = fTx*w;
  81.     Real fTwy = fTy*w;
  82.     Real fTwz = fTz*w;
  83.     Real fTxx = fTx*x;
  84.     Real fTxy = fTy*x;
  85.     Real fTxz = fTz*x;
  86.     Real fTyy = fTy*y;
  87.     Real fTyz = fTz*y;
  88.     Real fTzz = fTz*z;
  89.  
  90.     kRot[0][0] = 1.0f-(fTyy+fTzz);
  91.     kRot[0][1] = fTxy-fTwz;
  92.     kRot[0][2] = fTxz+fTwy;
  93.     kRot[1][0] = fTxy+fTwz;
  94.     kRot[1][1] = 1.0f-(fTxx+fTzz);
  95.     kRot[1][2] = fTyz-fTwx;
  96.     kRot[2][0] = fTxz-fTwy;
  97.     kRot[2][1] = fTyz+fTwx;
  98.     kRot[2][2] = 1.0f-(fTxx+fTyy);
  99. }
  100.  
  101. Aunque esto es una matriz de 3x3, sin la translación.
  102.  
  103. Esto seria fácil implementarlo en Lua ... IMHO
  104. Un saludo. Ricardo
  105.  
  106.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement