I have been using the guide at www.opengl-tutorial.org/intermediate-tutorials/tutorial-17-quaternions/ for learning OpenGL. This guide says that...
glm::quat q;
...creates an identity quaternion (no rotation).
Experimentation shows that q = [0, 0, 0, 0]. Using this as the parent orientation of the root bone causes none of the bones to rotate at all. They lose all rotation.
The guide says that...
A quaternion is a set of 4 numbers, [x y z w], which represents rotations the following way:
// RotationAngle is in radians
x = RotationAxis.x * sin(RotationAngle / 2)
y = RotationAxis.y * sin(RotationAngle / 2)
z = RotationAxis.z * sin(RotationAngle / 2)
w = cos(RotationAngle / 2)
... and ...
[0 0 0 1] (w=1) means that angle = 2*acos(1) = 0, so this is a unit quaternion, which makes no rotation at all.
I have been experimenting with a skeleton system where each bone inherits its parents' orientation before applying its own rotations on top of that.
If I use an "identity" quaternion as the "parent" orientation for the root bone, then none of the bones are rotated at all. If I use the "unit" rotation all is well.
When I set a bone's initial orientation to either the "identity" or "unit" quaternion it displays as I want to. However when I convert user entered Euler angles to an orientation I get a 180 degree rotation. The conversion I did was:
glm::vec3 eulers(glm::radians(pose.lng_rotate),
glm::radians(pose.lat_rotate),
glm::radians(pose.att_rotate));
pose.orientation = glm::quat(eulers);
Note: I use "lng", "lat", and "att" rotate here because by the time a bone has inherited a parent rotation the "x" axis is probably no longer the "x" axis any more.
The last weird thing I noticed was that I used glm::mat4_cast
on each type of quaternion and then multiplied by an identity glm::vec4
. The "identity" quaternion left the vector unrotated, but the "unit" quaternion caused the vector to invert (multiply by -1) the x and y components of the vector.
I want to understand quaternions better, especially with respect to their use in code.
Conceptually, how is a "unit" quaternion different to an "identity" quaternion?
Where should I use a "unit" quaternion and where should I use an "identity" quaternion?
Am I just being confused by a badly written guide?
glm::quat q; printf("%s, %s, %s, %s\n", std::to_string(q.x).c_str(), std::to_string(q.y).c_str(), std::to_string(q.z).c_str(), std::to_string(q.w).c_str());
The reason I use the string conversions is because there is something weird about the underlying type and using %f or %lf causes weird values to be displayed. I am lazy to figure out why. – AlastairGglm::quat(1.0, 0.0, 0.0, 0.0)
works perfectly. I failed to notice that although the guide expresses a quaternion as [x, y, z, w] it states that you initialise it explicitly asglm::quat(w,x,y,z)
. – AlastairG