Part of the Khronos Group
OpenGL.org

The Industry's Foundation for High Performance Graphics

from games to virtual reality, mobile phones to supercomputers

Results 1 to 4 of 4

Thread: a to convert a matrix to a quaternion

  1. #1
    Junior Member Newbie
    Join Date
    Jun 2012
    Posts
    15

    Unhappy a to convert a matrix to a quaternion

    Hi everyone

    I am new to the forum and just learning and in top of that I am not a native english speaker so please bear with me.

    I am working with some animation and want to make a mesh move and rotate according to a bezier path I have manage to make it move but the way I came with to make it rotate is to make a lookat matrix look from the current to the next position in the bezier curve, I'm not very good at math so, I don't know how to make a lookat quaternion so I use lookat matrix and convert it to a quaternion. All my rotation need to be in quaternion because all the interpolation is already done that way my scene graph, I tested my lookat matrix and is fine but the conversion to quaternion is wrong the function I am using is the one I have been seen around the web every where

    void CQuaternion::FromMatrix(CMatrix& m)
    {
    float trace = 1 + m.m11 + m.m22 + m.m33;
    float s = 0;

    if (trace > 0.0000001)
    {
    s = (float)sqrt(trace) * 2;
    x = (m.m23 - m.m32) / s;
    y = (m.m31 - m.m13) / s;
    z = (m.m12 - m.m21) / s;
    w = 0.25f * s;
    }
    else
    {
    if (m.m11 > m.m22 && m.m11 > m.m33)
    {
    // Column 0:
    s = (float)sqrt(1.0 + m.m11 - m.m22 - m.m33) * 2;
    x = 0.25f * s;
    y = (m.m12 + m.m21) / s;
    z = (m.m31 + m.m13) / s;
    w = (m.m23 - m.m32) / s;
    }
    else if (m.m22 > m.m33)
    {
    // Column 1:
    s = (float)sqrt(1.0 + m.m22 - m.m11 - m.m33) * 2;
    x = (m.m12 + m.m21) / s;
    y = 0.25f * s;
    z = (m.m23 + m.m32) / s;
    w = (m.m31 - m.m13) / s;
    }
    else
    {
    // Column 2:
    s = (float)sqrt(1.0 + m.m33 - m.m11 - m.m22) * 2;
    x = (m.m31 + m.m13) / s;
    y = (m.m23 + m.m32) / s;
    z = 0.25f * s;
    w = (m.m12 - m.m21) / s;
    }
    }
    }
    and this is my lookat matrix method just to be more clear

    void CMatrix::LookAt(CVector3 Pos, CVector3 Target, CVector3 y)
    {
    CVector3 x, z;

    z = Target - Pos;
    z.Normalize();

    if(!z.x && z.y == 1.0f && !z.z)
    {
    Rotate(-1.5707963267948966f, 0.0f, 0.0f);
    // Translate( Pos.x, Pos.y, Pos.z);
    return;
    }else
    if(!z.x && z.y == -1.0f && !z.z)
    {
    Identity();
    Rotate(1.5707963267948f, 0.0f, 0.0f);
    // Translate( Pos.x, Pos.y, Pos.z);
    return;
    }

    x.CrossProduct(z, y);
    //x.Normalize();

    y.CrossProduct(x, z);
    y.Normalize();

    m11 = x.x;
    m12 = x.y;
    m13 = x.z;

    m21 = y.x;
    m22 = y.y;
    m23 = y.z;

    m31 = z.x;
    m32 = z.y;
    m33 = z.z;

    /*don't need position
    m14 = m24 = m34 = 0;
    m41 = Pos[0];
    m42 = Pos[1];
    m43 = Pos[2];*/
    m44 = 1.0f;
    }

    please help, and thank you

  2. #2
    Senior Member OpenGL Pro
    Join Date
    Jan 2012
    Location
    Australia
    Posts
    1,117
    You Matrix - Quaternion is quite different to mine. Are you sure the matrix is from OpenGL and not DirectX. You may need to find the original maths; mine is based on Allan and Mark Watt's "Advanced Animation and Rendering Techniques".

  3. #3
    Senior Member OpenGL Guru Dark Photon's Avatar
    Join Date
    Oct 2004
    Location
    Druidia
    Posts
    3,194
    Looking at your MatrixToQuat code, looks nearly equivalent to what I'm using (regrouping terms, of course). Two differences. One is my if/elif conditions for the nested if (i.e. those in the trace <= 0 case) are >= instead of > (a minor point). And second is that for greater numerical stability, it's better for the first if if you check for (trace-1) > 0, not trace > 0. This corresponds to a w^2 > 1/4 case as opposed to the w^2 > 0. Additionally, this gets rid of the need for that 0.0000001 you're using to test against.

    Note that the above routine presumes "row-major operator-on-the-right " math order (e.g. y=x*M), which generates the same results as OpenGL's "column-major operator-on-the-left" math order (y=M*x).

    Haven't sifted your LookAt code. Cut it out of the picture and do some MatrixToQuat followed by QuatToMatrix -- make sure you get the same thing back out. That's a pretty good test.

  4. #4
    Junior Member Newbie
    Join Date
    Jun 2012
    Posts
    15
    it was basically what you mansion darkphoton I just realize my FromMatrix was row major while the lookat matrix was column major the funny thing was that I thought about it and decided to swap the column before using my FromMatrix method and the result were wrong too until I realize that by negating the z vector of my lookat matrix plus swapping from row to column major on the FromMatrix works fine.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •