makiolo

Euler to Quaternion

Nov 16th, 2011
169
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  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.  
RAW Paste Data