Menu â–¾ â–´

#10 Quaternion-to-matrix identity rotated

closed
nobody
bug (5)
2017-12-26
2017-12-20
Anonymous
No

Originally created by: winduptoy

I'm seeing the following behavior for quaternion to matrix conversion.

versor rotation = GLM_QUAT_IDENTITY_INIT;
fprintf(stderr, "-- Quaternion --\n%.4f %.4f %.4f %.4f\n\n", rotation[0], rotation[1], rotation[2], rotation[3]);

mat4 rotMatrix = GLM_MAT4_IDENTITY_INIT;
glm_quat_mat4(rotation, rotMatrix);
fprintf(stderr, "-- Matrix --\n%.4f %.4f %.4f %.4f\n%.4f %.4f %.4f %.4f\n%.4f %.4f %.4f %.4f\n%.4f %.4f %.4f %.4f\n", rotMatrix[0][0], rotMatrix[0][1], rotMatrix[0][2], rotMatrix[0][3], rotMatrix[1][0], rotMatrix[1][1], rotMatrix[1][2], rotMatrix[1][3], rotMatrix[2][0], rotMatrix[2][1], rotMatrix[2][2], rotMatrix[2][3], rotMatrix[3][0], rotMatrix[3][1], rotMatrix[3][2], rotMatrix[3][3]);

outputs

-- Quaternion --
0.0000 0.0000 0.0000 1.0000

-- Matrix --
-1.0000 0.0000 0.0000 0.0000
0.0000 -1.0000 0.0000 0.0000
0.0000 0.0000 1.0000 0.0000
0.0000 0.0000 0.0000 1.0000

The identity quaternion is what I expect, but the matrix seems to be flipped 180 degrees on X and Y. I noticed this because everything I render is flipped upside down. Shouldn't rotMatrix[0][0] and rotMatrix[1][1] equal positive 1 instead of negative 1 when using an identity quaternion? Or maybe I don't understand quaternions fully.

Platform:
Linux 64-bit
gcc v7.2.1
cglm v0.3.1

Discussion

  • Anonymous

    Anonymous - 2017-12-22

    Originally posted by: winduptoy

    @recp Any ideas on this?

     
  • Anonymous

    Anonymous - 2017-12-26

    Originally posted by: recp

    @winduptoy sorry I didn't see this issue until now, fell free to ping me again

    I think identity versor (GLM_QUAT_IDENTITY_INIT) is wrong.

    GLM_QUAT_IDENTITY_INIT  {0.0f, 0.0f, 0.0f, 1.0f}
    
    :::C
    versor rotation2;
    glm_quat(rotation2, 0, 0, 0, 0);
    

    gives {1.0f, 0.0f, 0.0f, 0.0f} so it must be

    GLM_QUAT_IDENTITY_INIT  {1.0f, 0.0f, 0.0f, 0.0f}
    

    but GLM_QUAT_IDENTITY_INIT {0.0f, 0.0f, 0.0f, 0.0f} also seems valid for your case. I'll fix this ASAP, but if you want to fix that, PR is welcome :)

    These functions also creates versor for you:

    CGLM_INLINE void glm_quat(versor q, float angle, float x, float y, float z);
    CGLM_INLINE void glm_quatv(versor q, float angle, vec3 v);
    
    versor rotation;
    glm_quat(rotation, glm_deg(45.0f), 1.0f, 0.0f, 0.0f);
    
    /* or  */
    
    glm_quatv(rotation, glm_deg(45.0f), (vec3){1.0f, 0.0f, 0.0f}); 
    /* v postrix means it accepts vector parameter */
    /* this axis vector maybe stored somewhere-else  */
    

    q is out parameter, I must change its name.

    Addition

    You don't have to initialize dest (or out) parameters. In your case you dont have to initialize rotMatrix because it is dest/out parameter which means glm_quat_mat4 is already creating matrix for you. But [in, out] parameter may need to be initialized e.g. glm_vec_normalize(vec) vec is in and out, read the header file. I will add docs to quad header too

    mat4 rotMatrix;
    glm_quat_mat4(rotation, rotMatrix);
    

    would be enough, but since function is inline I think compiler will ignore identity initialization (I hope)

    Also I would use built-in print utils to print them, it would save you to write huge printf :)

    Print matrix: glm_mat4_print(rotMatrix, stderr);
    Print Versor: glm_versor_print(rotation2, stderr);
    Print Vec3: glm_vec3_print(vec, stderr)
    Print Vec4: glm_vec4_print(vec, stderr)

    Important

    Some resources / tools / libraries may use x, y, z, w order but cglm uses w, x, y, z order to represent quaternion: [angle, axis]

    So you may see Quaternion.Identity = [0, 0, 0, 1] in MSDN or Unity or somewhere else, but it is [1, 0, 0, 0] in cglm and some other libraries

    I doesn't matter for me, if it must be x, y, z, w then we can change this.

     
  • Anonymous

    Anonymous - 2017-12-26

    Originally posted by: winduptoy

    Ah thank you for pointing out the print functions! I must have missed those. I'd like to help you with documentation soon.

    I did not realize that cglm used w, x, y, z, I simply assumed it was x, y, z, w. I don't really have a preference, but I think it would be important to document this in a very visible place.

    Thank you! Hope you had a good holiday wherever in the world you may be.

     
  • Anonymous

    Anonymous - 2017-12-26

    Originally posted by: recp

    I'd like to help you with documentation soon.

    That would be wonderful

    I did not realize that cglm used w, x, y, z, I simply assumed it was x, y, z, w. I don't really have a preference, but I think it would be important to document this in a very visible place.

    I'm confused now, probably most people may assume that is x, y, z, w. For C++ classes probably most people accessing those values by ctor or its name like quat->x, quat->w so it doesn't matter for them I think, but since we have stored them as array order is matter. versor is stored as vec4 (aligned) because it is perfectly fits with SIMD instuctions to optimize them. Maybe documentation would prevent any confusion here

    Thank you! Hope you had a good holiday wherever in the world you may be.

    Thank you very much, I hope you too.

     
  • Anonymous

    Anonymous - 2017-12-26

    Ticket changed by: recp

    • status: open --> closed
     
  • Anonymous

    Anonymous - 2017-12-26

    Originally posted by: recp

    Fixed by: https://github.com/recp/cglm/pull/11

     

Log in to post a comment.