Jump to content
  • Advertisement
Sign in to follow this  

converting between quaternions and matrices

This topic is 4675 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I have two functions, one to create a 4x4 matrix from a quaternion, and one to create a quaternion from a 4x4 matrix. To test them I create an identity matrix and an identity quaternion identity matrix: 1.000000 0.000000 0.000000 0.000000 0.000000 1.000000 0.000000 0.000000 0.000000 0.000000 1.000000 0.000000 0.000000 0.000000 0.000000 1.000000 identity quaternion: 0.000000 0.000000 0.000000 1.000000 quat_from_matrix output: 0.000000 0.000000 0.000000 1.000000 matrix_from_quat output: 0.250000 0.375000 -0.500000 0.000000 0.250000 0.500000 0.500000 0.000000 0.000000 0.000000 0.000000 1.000000 0.000000 0.000000 0.000000 1.000000 quat_from_matrix output: 0.250000 0.375000 -0.500000 0.000000 something seems to be wrong as i can't convert twice and get the same thing back. here are my two functions:
void quat_from_matrix4(quat q, matrix4 m)
{   float trace=m[0]+m[5]+m[10]+1;
    if (trace>EPSILON)
    {   float s=0.5f/sqrtf(trace);
        q[0]=(m[9]-m[6])*s;
        q[1]=(m[2]-m[8])*s;
        q[2]=(m[4]-m[1])*s;
        q[3]=0.25f/s;
    }
    else
    {   if (m[0] > m[5] && m[0] > m[10])
        {   float s=2.0f*sqrtf(1.0f+m[0]-m[5]-m[10]);
            q[0]=0.25f/s;
            q[1]=(m[1]+m[4])*s;
            q[2]=(m[2]+m[8])*s;
            q[3]=(m[6]-m[9])*s;
        }
        else if (m[5] > m[10])
        {   float s=2.0f*sqrtf(1.0f+m[5]-m[0]-m[10]);
            q[0]=(m[1]+m[4])*s;
            q[1]=0.25f*s;
            q[2]=(m[6]+m[9])*s;
            q[3]=(m[2]-m[8])*s;
        }
        else
        {   float s=2.0f*sqrtf(1.0f+m[0]-m[5]-m[10]);
            q[0]=(m[2]+m[8])*s;
            q[1]=(m[6]+m[9])*s;
            q[2]=0.25f*s;
            q[3]=(m[1]-m[4])*s;
        }
    }
}

void matrix4_from_quat(matrix4 mat, quat q)
{   float xx=q[0]*q[0];
    float xy=q[0]*q[1];
    float xz=q[0]*q[2];
    float xw=q[0]*q[3];

    float yy=q[1]*q[1];
    float yz=q[1]*q[2];
    float yw=q[1]*q[3];

    float zz=q[2]*q[2];
    float zw=q[2]*q[3];

    //first column
    mat[0]=1.0f-2.0f*(yy+zz);
    mat[1]=2.0f*(xy-zw);
    mat[2]=2.0f*(xz+yw);
    mat[3]=0.0f;
    //second column 
    mat[4]=2.0f*(xy+zw);
    mat[5]=1.0f-2.0f*(xx+zz);
    mat[6]=2.0f*(yz-xw);
    mat[7]=0.0f;
    //third column
    mat[8]=2.0f*(xz-yw);
    mat[9]=2.0f*(yz+xw);
    mat[10]=1.0f-2.0f*(xx+yy);
    mat[11]=0.0f;
    //fourth column
    mat[12]=0.0f;
    mat[13]=0.0f;
    mat[14]=0.0f;
    mat[15]=1.0f;
}

can anyone spot any mistakes?

Share this post


Link to post
Share on other sites
Advertisement
Should this:

else {
float s=2.0f*sqrtf(1.0f+m[0]-m[5]-m[10]);

Be:

else {
float s=2.0f*sqrtf(1.0f+m[10]-m[0]-m[5]);

?

Share this post


Link to post
Share on other sites
You're right, nice catch.

I made the correction and the output is unchanged, though. If you look at the output the quat_from_matrix4 function appears to produce correct output (i.e. identity quat from an identity transformation matrix).

it's the matrix4_from_quat that doesn't produce identity from identity. i'm wondering if this is a special case the function doesn't handle...

oh yeah, in case this wasn't obvious the matrices are stored in column-major ordering and the the quaternions are in the order x,y,z,w.

Share this post


Link to post
Share on other sites
I couldn't find an error in your quat-to-matrix code. Something is a little suspicious, though, because in the output that you posted, element 14 is 1, but the code should have set it to zero. If you haven't already found the problem, you might try stepping through the code line be line.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!