22

Basically, given a quaterion (qx, qy, qz, qw)... How can i convert that to an OpenGL rotation matrix? I'm also interested in which matrix row is "Up", "Right", "Forward" etc... I have a camera rotation in quaternion that I need in vectors...

4 Answers 4

39

The following code is based on a quaternion (qw, qx, qy, qz), where the order is based on the Boost quaternions:

boost::math::quaternion<float> quaternion;
float qw = quaternion.R_component_1();
float qx = quaternion.R_component_2();
float qy = quaternion.R_component_3();
float qz = quaternion.R_component_4();

First you have to normalize the quaternion:

const float n = 1.0f/sqrt(qx*qx+qy*qy+qz*qz+qw*qw);
qx *= n;
qy *= n;
qz *= n;
qw *= n;

Then you can create your matrix:

Matrix<float, 4>(
    1.0f - 2.0f*qy*qy - 2.0f*qz*qz, 2.0f*qx*qy - 2.0f*qz*qw, 2.0f*qx*qz + 2.0f*qy*qw, 0.0f,
    2.0f*qx*qy + 2.0f*qz*qw, 1.0f - 2.0f*qx*qx - 2.0f*qz*qz, 2.0f*qy*qz - 2.0f*qx*qw, 0.0f,
    2.0f*qx*qz - 2.0f*qy*qw, 2.0f*qy*qz + 2.0f*qx*qw, 1.0f - 2.0f*qx*qx - 2.0f*qy*qy, 0.0f,
    0.0f, 0.0f, 0.0f, 1.0f);

Depending on your matrix class, you might have to transpose it before passing it to OpenGL.

Sign up to request clarification or add additional context in comments.

6 Comments

fyi this looks like a row-major interpretation, for anyone looking at this. It should work-as is when passing to OpenGL since column-major and row-major result in same linear array. However if using this with a column-major library to multiply with another matrix, you could get issues depending on how your library works.
Nice. So boost can do pretty much everything is what I'm finding.
See also: stackoverflow.com/questions/1274936/… which mentions that Quaternions do NOT have handedness, but that matrixes DO. So you may have to modify 6 cells of the above transform, conjugating them sort-of. Cells 21,31,32,12,13,23. (Apart from that, I just pasted this code and changed slightly for my particular library, and it worked great. Thanks!)
That sqrt calculation is unnecessary. Instead take n = 2.f/(qx*qx+qy*qy+qz*qz+qw*qw) and replace all the 2.0f factors in the matrix with n.
I would like to ask where I put (tx, ty, tz). Do I put them on the [0][3], [1][3] and [2][3] matrix?
|
11

One way to do it, which is pretty easy to visualize, is to apply the rotation specified by your quaternion to the basis vectors (1,0,0), (0,1,0), and (0,0,1). The rotated values give the basis vectors in the rotated system relative to the original system. Use these vectors to form the rows of the rotation matrix. The resulting matrix, and its transpose, represent the forward and inverse transformations between the original system and the rotated system.

I'm not familiar with the conventions used by OpenGL, so maybe someone else can answer that part of your question...

3 Comments

Yeah I forgot I could do this... I'll give it a go
Mathematically correct, but computationally more expensive to do it like this.
I would test it, because this version uses instructions that some hardware (I am specifically thinking of GPU shaders) might be specifically optimized for, so while probable, I would not be so sure it is more computationally expensive...
1

You might not have to deal with a rotation matrix at all. Here is a way that appears to be faster than converting to a matrix and multiplying a vector with it:

  // move vector to camera position co (before or after rotation depending on the goal)
  v -= co;

  // rotate vector v by quaternion q; see info [1]
  vec3 t = 2 * cross(q.xyz, v);
  v = v + q.w * t + cross(q.xyz, t);

[1] http://mollyrocket.com/forums/viewtopic.php?t=833&sid=3a84e00a70ccb046cfc87ac39881a3d0

1 Comment

The link is dead.
1

using glm, you can simply use a casting operator. so to convert from a matrix4 to quaternion, simply write

glm::mat4_cast(quaternion_name)

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.