2012-04-16 3 views
1

Мне нужно получить некоторые данные из матрицы вращения openGL. Мне нужно получить эквивалентные углы Эйлера (уже сделал это), эквивалентный кватернион (сделал это, но просто скопировал его из Интернета) и эквивалентный ось-угол.Как получить ось-угол от матрицы вращения?

Я не знаю, может ли матрица вращения быть выражена как одно вращение определенного угла вокруг определенного вектора. Эти эквиваленты? Если да, то как я могу получить один от другого?

Также я хотел бы лучше понять значение кватерниона и внутренности матрицы вращения. Куда мне идти, чтобы узнать об этом?

ответ

1

Да любая матрица/единица измерения вращения эквивалентна вращению вокруг одной оси. Если мы называем эту ось n и угол theta затем кватернион для этого вращения:

[n * sin(theta/2) cos(theta/2)] 

Чтобы восстановить это использование acos на w элемента кватерниона, чтобы получить theta/2. После того, как у вас есть theta, вы можете разделить x, y и z с sin(theta/2), чтобы восстановить ось.

+0

Thanx, я думаю, что это то, что мне нужно. :) – Alex

+0

Мне также нужно получить ось/угол от матрицы вращения, можете ли вы объяснить немного больше, используя матрицу в качестве отправной точки? Я не знаю, что такое кватернион, и я не уверен, что действительно хочу знать ... –

0

Вот функция, которая преобразует матрицу 3x3 в ось, угол (используя quatention, поэтому, возможно, это более эффективный способ, который обходит этот шаг).

void axis_angle_from_mat3(float r_axis[3], float *r_angle, float mat[3][3]) 
{ 
    float q[4]; 

    /* -------------------------------------------------------------------- */ 
    /* matrix to quaternion */ 
    double tr, s; 
    float tmat[3][3]; 

    /* work on a copy */ 
    memcpy(tmat, mat, sizeof(tmat)); 

    /* normalize the matrix */ 
    int i; 
    for (i = 0; i < 3; i++) { 
     float d = (tmat[i][0] * tmat[i][0] + tmat[i][1] * tmat[i][1] + tmat[i][2] * tmat[i][2]); 

     if (d > 1.0e-35f) { 
      d = sqrtf(d); 
      tmat[i][0] /= d; 
      tmat[i][1] /= d; 
      tmat[i][2] /= d; 
     } 
     else { 
      tmat[i][0] = 0.0f; 
      tmat[i][1] = 0.0f; 
      tmat[i][2] = 0.0f; 
      d = 0.0f; 
     } 
    } 


    tr = 0.25 * (double)(1.0f + tmat[0][0] + tmat[1][1] + tmat[2][2]); 

    if (tr > (double)1e-4f) { 
     s = sqrt(tr); 
     q[0] = (float)s; 
     s = 1.0/(4.0 * s); 
     q[1] = (float)((double)(tmat[1][2] - tmat[2][1]) * s); 
     q[2] = (float)((double)(tmat[2][0] - tmat[0][2]) * s); 
     q[3] = (float)((double)(tmat[0][1] - tmat[1][0]) * s); 
    } 
    else { 
     if (tmat[0][0] > tmat[1][1] && tmat[0][0] > tmat[2][2]) { 
      s = 2.0f * sqrtf(1.0f + tmat[0][0] - tmat[1][1] - tmat[2][2]); 
      q[1] = (float)(0.25 * s); 

      s = 1.0/s; 
      q[0] = (float)((double)(tmat[1][2] - tmat[2][1]) * s); 
      q[2] = (float)((double)(tmat[1][0] + tmat[0][1]) * s); 
      q[3] = (float)((double)(tmat[2][0] + tmat[0][2]) * s); 
     } 
     else if (tmat[1][1] > tmat[2][2]) { 
      s = 2.0f * sqrtf(1.0f + tmat[1][1] - tmat[0][0] - tmat[2][2]); 
      q[2] = (float)(0.25 * s); 

      s = 1.0/s; 
      q[0] = (float)((double)(tmat[2][0] - tmat[0][2]) * s); 
      q[1] = (float)((double)(tmat[1][0] + tmat[0][1]) * s); 
      q[3] = (float)((double)(tmat[2][1] + tmat[1][2]) * s); 
     } 
     else { 
      s = 2.0f * sqrtf(1.0f + tmat[2][2] - tmat[0][0] - tmat[1][1]); 
      q[3] = (float)(0.25 * s); 

      s = 1.0/s; 
      q[0] = (float)((double)(tmat[0][1] - tmat[1][0]) * s); 
      q[1] = (float)((double)(tmat[2][0] + tmat[0][2]) * s); 
      q[2] = (float)((double)(tmat[2][1] + tmat[1][2]) * s); 
     } 
    } 


    /* normalize the quat */ 
    float len; 
    len = sqrtf(q[0] * q[0] + q[1] * q[1] + q[2] * q[2] + q[3] * q[3]); 
    if (len != 0.0f) { 
     q[0] /= len; 
     q[1] /= len; 
     q[2] /= len; 
     q[3] /= len; 
    } 
    else { 
     q[1] = 1.0f; 
     q[0] = q[2] = q[3] = 0.0f; 
    } 


    /* -------------------------------------------------------------------- */ 
    /* quaternion to axis angle */ 

    float ha, si; 

    ha = acosf(q[0]); 
    si = sinf(ha); 

    *r_angle = ha * 2; 

    if (fabsf(si) < FLT_EPSILON) 
     si = 1.0f; 

    r_axis[0] = q[1]/si; 
    r_axis[1] = q[2]/si; 
    r_axis[2] = q[3]/si; 
} 
Смежные вопросы