Reputation: 4314
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?
Upvotes: 12
Views: 21766
Reputation: 272
A unit quaternion is NOT the same as an identity quaternion. A quaternion is just any number in 'quaternion space', like 3 + 2i - 7j + 6k
.
When we are using quaternions to calculate rotations we are always talking about unit quaternions and always have a length of 1, just like a unit vector. Multiplying unit quaternions is a very efficient way of calculating a rotation, but the length must stay the same, 1.
An identity quaternion is a quaternion that doesn't change any quaternion it is multiplied with, thus 1 + 0i + 0j + 0k
or 1
. An identity quaternion is thus a unit quaternion with a rotation of nothing.
Upvotes: 26
Reputation: 4314
Unit and identity quaternions are the same thing. The guide is badly written and confusing.
glm::quat q;
does NOT create an identity quaternion. It creates an invalid quaternion. The best way to create an identity quaternion is either by glm::quat q(glm::vec3(0.0, 0.0, 0.0));
or by glm::quat q(1.0, 0.0, 0.0, 0.0);
. The first generates the quaternion based on a vector of all zero Euler rotations. The second explicitly initialises it to the identity quaternion.
Note that although quaternions are often described as [x y z w]
, they are stored and initialised as (w, x, y, z)
.
Upvotes: 3