I am going to show you how 3D rotations can be done with quaternions. There are other tools than quaternions for 3D rotations. However, when I was in high school I looked a long time for a way to do 3D rotations. All the resources I found seemed happy to do some 2D rotations in 3D for theory’s sake and leave the rest to me. I think I had given up when I came across quaternions and noticed they had the property of being able to represent 3D rotations. Anyway, again, there are other tools for 3D rotations, but quaternions, for me, were the bridge from “Does anyone actually know this?” to “Yeah there’re lots of ways.” so maybe they can help you too. And if you’re at least as into math as I am, they’re cool regardless.
In most first person shooter games, your body stays vertical most of the time, you walk parallel to the ground, and you jump perpendicular to the ground. As such, all rotations and movements can be accomplished with two axes of rotation, whose measures I’ll call with yaw (left and right) and pitch (up and down). So, given a world, a player location, a yaw, and a pitch, you can rotate the world about a vertical axis centered at the player for yaw, then rotate about the axis that points goes from left to right for pitch. For walking directions, you only have to rotate by yaw because you always walk parallel to the ground. For jumping, you don’t have to rotate at all because your body is always vertical and you always jump up. But this is only a small and easy subset of all possible 3D rotations.
There’s a video game I really like called Descent (and its sequel). Descent is a first person shooter, but more specifically a six degrees of freedom (6DOF) game. You don’t play as a humanoid that walks on the ground; you’re in a spaceship that can rotate in all 3 axes and moves relative to the direction it is facing, not the direction of the ground (in fact, the only notion of ground is created by the looks of the environment). You can also move right, left, up, and down, hence 6 degrees of freedom (3 rotational, 3 translational). I’ll call the measure of rotation along the third axis of rotation roll. It’s akin to tilting your head.
Now our original system fails. The way I see the problem is this: if you pitch up a bit and then yaw, you are yawing along an arbitrary axis, not a vertical axis as before. I tried modifying the system, keeping the idea of a sequence of rotations along axes, but never succeeded. It is possible though. But that’s not what we’re doing here.
Math time now. The notion of numbers you are familiar with hasn’t always been around, and it’s always evolving. At one time, there were only whole number greater than or equal to 1. If you asked what 1-1 is, there wasn’t a good answer. I’m not joking. Thankfully though, someone invented 0 and the notion of numbers got more robust since it could survive something like 1-1. If you asked what 1-2 is, there’s no answer again. Some kindergarten teachers still say this is so. But it’s not; negative numbers are used. Then there’s the question of what 1/2 is. It’s not 0. It’s not 1. It’s in between them. These are called rational numbers. It is here I think the familiar notion of numbers starts to end, because there are numbers like pi, e, or the square root of 3 which can’t be expressed the way rational numbers can be; you’d need an infinite number of digits to do it. These are called irrationals, since they can’t be expressed as a rational. Together, rationals and irrationals make what are called, for no good reason as we’ll see in a second, real numbers. Next, we ask what the square root of -1 is and there’s no good answer. So an answer was invented. It’s commonly represented as a letter: i for mathematicians, and j for engineers, among others. We’ll use i. Unfortunately this number was called “imaginary” as if it exists less than the other numbers. Don’t let yourself be seduced by the name. i exists as much as 0 does. You can’t see 0 apples and you can’t see i apples but the two numbers still exist. You can’t write i as a sequence of digits, but neither can you an irrational. A number that can be represented as a+bi where a and b are real numbers is called a complex number.
The sexy thing about complex numbers is that there aren’t any more questions to ask that don’t have answers, or if there are I’m excited to hear them. But that doesn’t mean there aren’t further notions of numbers with meaning. And so, one day, Mr. Hamilton decided to expand on complex numbers to create quaternions. Between real and complex numbers he saw in some sense a doubling of the available numbers. Where there was only real, there came real and imaginary. So he applied the same thing to complex numbers and ended up with numbers that can be represented like a+bi+cj+dk, where a, b, c, and d are real, i is the square root of -1, and j and k (also square roots of -1) relate as follows:
Exactly how these rules were chosen is probably a cool thing to know, but I don’t, so we’ll skip it and get back to 3D rotations sooner.
First though, another thing about quaternions: their multiplication is not commutative. That means if you multiply quaternion A by quaternion B, you get a different result than multiplying quaternion B by quaternion A. Normally multiplication is assumed to be commutative, so having to remember what goes where when someone says “A multiplied by B” is a bit unnatural. But subtraction isn’t commutative, so it’s really just a conditioning thing. If someone asks you to reduce the thermostat by 5 degrees, you’d never accidentally subtract the current setting from 5 and set it to that. And you might be asking how any meaningful notion of numbers can lack multiplicative commutativity. Well, we’re going to represent rotations with quaternions, and the application of rotations as multiplication, so not only should we expect it, we should demand it, because rotations are not commutative. Let me convince you of that. Take a textbook. Place it on a flat surface in front of you so you can read the title. Rotate the book clockwise by a quarter rotation, toward you by a half rotation, clockwise by a quarter rotation, and then toward you by a half rotation. If I was explicit enough in my instructions, you’ll end up with the book in the same position as before, so you can read the title. Let’s apply those same four rotations in a different order. Rotate the book clockwise by a quarter rotation twice, then rotate toward you by a half rotation twice. Now the title is upside down. That’s not the same as before! So we should expect that whatever mathematical operations we use to represent rotations act the same. If equation (1) seemed to suggest i, j, and k were identical before, it shouldn’t anymore.
One final thing about quaternions: they have conjugates. I’m going to write the conjugate of a quaternion A with A’. Conjugates work like this:
So here’s how quaternions relate to rotations. We’re going to rotate a point p by an angle t about an axis defined by the normalized vector n to some new point q. Let
Then we can find Q, and therefore q, as follows:
Here’s some Python code which implements a 6DOF environment using quaternions. You can move with wasd for forward, left, backward, and right; rf for rise and fall; jl for yaw; ik for pitch; and uo for roll.