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
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.

- 5,637
- 1
- 23
- 28
-
2fyi 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. – johnbakers Jun 13 '13 at 02:26
-
Nice. So boost can do pretty much everything is what I'm finding. – Sep 01 '13 at 14:59
-
1See also: http://stackoverflow.com/questions/1274936/flipping-a-quaternion-from-right-to-left-handed-coordianates 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!) – david van brink Sep 26 '16 at 22:36
-
1That `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`. – Yakov Galka Apr 30 '17 at 21:28
-
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? – anonymous Jan 04 '23 at 07:17
-
That depends on the order of the operations. It makes a difference whether you translate first and then rotate, or the other way around. You can try this by putting the translation into a separate translation matrix and then switch the order of matrix multiplication. – Malte Clasen Jan 06 '23 at 11:14
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...

- 43,505
- 7
- 82
- 96
-
-
Mathematically correct, but computationally more expensive to do it like this. – teodron Mar 18 '13 at 15:28
-
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... – Gerasimos R Apr 27 '13 at 14:04
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,775
- 2
- 17
- 24
using glm, you can simply use a casting operator. so to convert from a matrix4 to quaternion, simply write
glm::mat4_cast(quaternion_name)

- 21
- 1