2012-04-16 4 views
1

OpenGL 회전 매트릭스에서 일부 데이터를 가져와야합니다. 동등한 오일러 각 (이미 해냈습니다), 등가 쿼터니언 (인터넷에서 복사 한 것) 및 동등한 축 각을 얻어야합니다.회전 행렬에서 축 각도를 얻는 방법?

회전 벡터가 특정 벡터 주위로 일정 각도의 단일 회전으로 표현 될 수 있는지 여부는 알지 못합니다. 이것들은 동등한가? 그렇다면 어떻게하면 다른 것을 얻을 수 있습니까?

또한 쿼터니언의 의미와 회전 행렬의 내부를 더 잘 이해하고 싶습니다. 이 사실을 알기 위해 어디로 가야합니까?

답변

1

예 모든 회전 행렬/단위 쿼터니온은 단일 축을 중심으로 한 회전과 동일합니다. 우리는이 축 n 및 각도 theta를 호출 할 경우,이 회전 사원 수는 다음과 같습니다

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

theta/2을 얻을 수있는 사원 수의 w 요소에이 사용 acos를 재구성하십시오. theta을 얻은 후에는 , yz 구성 요소를 sin(theta/2)으로 나눠 축을 재구성 할 수 있습니다.

+0

고맙습니다. 나는 이것이 내가 필요한 것이라고 생각합니다. :) – 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; 
}