## Using Quaternion to Perform 3D rotationsBy confuted The title of
this tutorial is
short and sweet. The tutorial itself will not be. First, an
introduction. Quaternions are the things that scare all manner of
mice
and men. They are the things that go bump in the night.
They are
the reason your math teacher gave you an F. They are all that you
have
come to fear, and more. Quaternions are your worst nightmare. A quaternion represents two things. It has an x, y, and z component, which represents the axis about which a rotation will occur. It also has a w component, which represents the amount of rotation which will occur about this axis. In short, a vector, and a float. With these four numbers, it is possible to build a matrix which will represent all the rotations perfectly, with no chance of gimbal lock. (I actually managed to encounter gimbal lock with quaternions when I was first coding them, but it was because I did something incorrectly. I'll cover that later). So far, quaternions should seem a lot like the axis angle
representation. However, there are some large differences, which
start....now.A quaternion is technically four numbers, three of which have
an
imaginary component. As many of you probably know from math
class, i
is defined as sqrt(-1). Well, with quaternions, i = j
=
k = sqrt(-1). The quaternion itself is defined as q = w + xi
+
yj + zk. w, x, y, and z are all real numbers.
The
imaginary components are important if you ever have a math class with
quaternions, but they aren't particularly important in the
programming.
Here's why: we'll be storing a quaternion in a class with four member
variables: float w, x, y, z;. We'll be ignoring i, j,
and k,
because we never liked them anyway. Okay, so we're actually just
ignoring
them because we don't need them. We'll define our quaternions (w,
x, y, z).You may have guessed by now that w is the amount of rotation about the axis defined by <x, y, z>. (Warning: the math is going to start getting pretty heavy. I'll explain the quaternion specific stuff, though). Much like unit vectors are necessary for much of what is done in a 3d engine, with lighting, back-face culling, and the like, unit quaternions are needed to perform the operations we'll be doing below. Luckily, normalizing a quaternion isn't much harder than normalizing a vector. The magnitude of a quaternion is given by the formula magnitude = sqrt(w ^{2} + x^{2}
+ y^{2} + z^{2}). For the unit quaternions, the
magnitude
is one. Which means that, already, an optimization is in
order. Floating-point
numbers aren't perfect. Eventually, you'll lose accuracy with
them, and
you may want to check to see if you need to re-normalize your unit
quaternion,
to prevent math errors. This can be done by checking the
magnitude, which
will need to be one... but if you're checking to see if it's one, there
is no
need for the sqrt() at all (sqrt(1) = 1). So, if (w^{2} +
x^{2}
+ y^{2} + z^{2}) is more than a certain tolerance away
from 1,
you'll know that your quaternion needs to be normalized, and you will
have
saved taking a square root in the cases when it is within
tolerance.
Every few clock cycles count. But if you ever need to actually
normalize
a quaternion, here's how it would be done:
magnitude =
sqrt(w
Let Q
/*to
keep with the conventions I've followed in some posts
on cprogramming.com, I Before I try
to explain that
any more, I need to teach you how to generate local_rotation.
You'll need
to have the axis and angle prepared, and this will convert them to a
quaternion. Here's the formula for generating the //axis is a unit
vector
Hang in there; we're almost done. All that is left for this tutorial is generating the matrix from the quaternion to rotate our points.
Amazing. Well, maybe not amazing, but
pretty
cool. You'll regenerate these matrices each frame. Most
importantly, you
Previous: Uses for What You've Learned Back to Graphics tutorials index |