3

After figuring out the answer to my previous question I have found the cause to be some kind of mathematical oddity.

Using the GLM (OpenGL) library I create an orientation as follows

glm::gtx::quaternion::orientation = 
    glm::gtx::quaternion::angleAxis(pitchAccum, 1.0f, 0.0f, 0.0f) * 
    glm::gtx::quaternion::angleAxis(yawAccum, 0.0f, 1.0f, 0.0f);

Now if I create a matrix from this orientation it is no longer column major but somehow becomes row major

    glm::mat4 view = glm::gtx::quaternion::toMat4(orientation); 

In other words the 3 coordinates axes are found by accessing the matrix using row major indices

view[0][0], view[1][0], view[2][0]  // X axis
view[0][1], view[1][1], view[2][1]  // Y axis
view[0][2], view[1][2], view[2][2]  // Z axis

In other words the transpose of the rotation part.

The translation part of the matrix should still be set using column major in order for the final view matrix to work as intended.

view[3][0] = -glm::dot(glm::vec3(view[0][0], view[1][0], view[2][0]), position);    // Right
view[3][1] = -glm::dot(glm::vec3(view[0][1], view[1][1], view[2][1]), position);    // Up
view[3][2] = -glm::dot(glm::vec3(view[0][2], view[1][2], view[2][2]), position);    // Forward

Why is the rotation matrix flipped from column major to row major (transposed?) when using the orientation?

EDIT:

// Move forward
if (glfwGetKey('W') == GLFW_PRESS)
{
    //movement += glm::vec3(view[2][0], view[2][1], view[2][2]);  // incorrect
    movement += -glm::vec3(view[0][2], view[1][2], view[2][2]);   // correct
}
// Move backward
if (glfwGetKey('S') == GLFW_PRESS)
{
    //movement += -glm::vec3(view[2][0], view[2][1], view[2][2]); // incorrect
    movement += glm::vec3(view[0][2], view[1][2], view[2][2]);    // correct
}
// Strafe left
if (glfwGetKey('A') == GLFW_PRESS)
{
    //movement += -glm::vec3(view[0][0], view[0][1], view[0][2]);  // incorrect
    movement += -glm::vec3(view[0][0], view[1][0], view[2][0]);    // correct
}
// Strafe right
if (glfwGetKey('D') == GLFW_PRESS)
{
    //movement += glm::vec3(view[0][0], view[0][1], view[0][2]);  // incorrect
    movement += glm::vec3(view[0][0], view[1][0], view[2][0]);    // correct
}
Community
  • 1
  • 1
user1423893
  • 766
  • 4
  • 15
  • 26
  • 1
    What makes you say that it's flipped? It's a rotation matrix; it's transpose is also its inverse. Which means you could simply be looking at the rotation direction not being what you expect. – Nicol Bolas Aug 30 '12 at 23:20
  • Also, please stop using Euler angles. And yes, you're still using them even though you're using quaternions. – Nicol Bolas Aug 30 '12 at 23:21
  • _What makes you say that it's flipped?_ The rotation axes are only correct when accessed using row major methods. They are no stored in a column major fashion which is odd considering the library deals with OpenGL. – user1423893 Aug 30 '12 at 23:24
  • 1
    _Also, please stop using Euler angles._ Can you please point me to an example that doesn't use them and I'll implement that after I've understood it? – user1423893 Aug 30 '12 at 23:26
  • "*The rotation axes are only correct when accessed using row major methods.*" How do you know what is *correct*? That's what I'm asking. – Nicol Bolas Aug 30 '12 at 23:32
  • If I use the values to translate the camera or for drawing rays then the column major values do not work. Row major indices do work. See my edit for an example. – user1423893 Aug 31 '12 at 01:02
  • 1
    @NicolBolas I too would like to know the alternative to using Euler angles with quaternions; since a quaternion is fundamentally expressed as an axis vector and a rotation angle around this vector (x,y,z,w), this might explain why so many quaternion-generating functions in libraries take regular angles. If there is a better way that you mention, it would be helpful to know what it is. – johnbakers Jun 10 '13 at 14:20
  • @Fellowshee, see my answer at http://stackoverflow.com/a/17047931/423105. And I'd be interested on your feedback on it, as I'm not a graphics or math expert. – LarsH Jun 11 '13 at 15:25
  • P.S. I'd certainly rather hear the answer from the horse's mouth (@NicolBolas). – LarsH Jun 11 '13 at 15:40

1 Answers1

7

A matrix M which transforms from the space A to the space B has the basis vectors of space A, but expressed relative to space B.

The camera matrix transforms from world space to camera space. Thus, the basis vectors of the camera matrix are the basis vectors of world space, as seen from camera space. Not the basis vectors of camera space.

The orientation of the camera, relative to world space, is the inverse of this transformation. And since the inverse of a rotation matrix is it's transpose, you have your issue.

The problem isn't with the matrix; the problem is with the difference between what you think the matrix says and what it actually says.

Nicol Bolas
  • 449,505
  • 63
  • 781
  • 982