Honeycomb Engine: Dev Blog 3 ~ Quaternions for Rotations

Quaternions. The mere mention of these mathematical constructs would’ve sent shivers down my spine a couple of years ago. They’re really weird and complex. However, when you’re making a game engine and you have to model the rotations of objects, you’d be crazy not to use them for several reasons.

The easiest way for people to think about an arbitrary rotation in 3D space is to think of three separate rotations around the x-, y- and z-axes respectively. This way of representing a rotation is commonly known as Euler angles. The advantage is that it’s easy for someone to reason about a rotation represented in Euler angles because they’re so simple – I just rotate around x, then y, then z, it’s that easy. However, this brings a couple of problems with it too; namely, it’s inefficient to do three separate rotations for every single rotation you apply, and Euler angles can run into a problem called Gimbal lock.

In a system where three gimbals each provide an axis of movement around a central point, it is possible to lose one degree of freedom by rotating one of the gimbals 90° such that its axis converges on one of the other gimbals. When this happens, the other two gimbals will rotate along the same axis. The word ‘lock’ is a tad misleading, because you can fix the problem simply by rotating the first gimbal back, but it still leads to weird behaviour sometimes. It’s best explained through an animated diagram.

Quaternions fix both of these issues. Firstly, Euler’s rotation theorem (Yes, Euler got around a lot) tells us that we can represent any rotation or sequence of rotations around a fixed point as one single composite rotation around some axis through that point. As it turns out, we can model rotations around an arbitrary axis as a quaternion!

img_20161109_003123

Rotating around an axis rather than three rotations around x, y and z axes.

To understand how this works, we first need to know what a quaternion is. I’m not going to go into too much detail, because I want to keep this post relevant to how we can use them for rotations. At their most basic level, a quaternion, q, is made up of four real numbers, x, y, z and w, where:

q = w + xi + yj + zk

Here, i, j and k represent versors, or unit quaternions. Don’t worry about what they mean too much, because your head might go nuclear trying to wrap your brain around them. What we want to do is represent x, y, z and w in a way that’s useful to us. Luckily, it’s really simple: take our axis to be a three-dimensional vector (a, b, c) and our angle to be θ. Then our quaternion’s real number parts are:

x = a * sin(θ/2)
y = b * sin(θ/2)
z = c * sin(θ/2)
w = cos(θ/2)

Now we have a quaternion that represents an angle-axis rotation, immune from the problem of gimbal lock. To apply the rotation to an object, we multiply the point we want to rotate by the rotation quaternion. To figure out what the quaternion is doing, we can take x, y, z and w and calculate the angle and axis from them – first of all we can find the angle:

θ = 2 * cos⁻¹(w)

Then, we can use this angle to figure out what the rotational axis – a 3D vector – is:

a = x / sin(θ/2)
b = y / sin(θ/2)
c = z / sin(θ/2)

With this in mind, it’s a little easier to reason about what quaternions are doing. Keep in mind that all these rotations are about the origin, so if you want to rotate around an arbitrary point, you’ll need to translate your object by the inverse position vector of the point, do the rotation, then translate by the position vector of the point to undo the first translation.

rotation-by-translation

This image is about 2D translations, but the general idea still applies.

To make a rotation by compositing two different rotations, we can just multiply their respective quaternion rotations together, paying attention to the order:

new_rotation = second_rotation * first_rotation

The other great thing about quaternions is that we can mix between two rotations really easily, with more believable results that using Euler angles. Whereas we’d use a regular lerp operation (linear interpolation) to move from one rotation vector to another if we were using Euler angles, we can use the more sophisticated slerp (spherical linear interpolation) technique for quaternion-based rotations.

To imagine the difference between these two techniques, imagine you were stood on a completely flat world, whether it be in 2D or 3D, and I asked you to walk from point A to point B on that surface in a straight line at a constant speed – that’s you using a lerp. Now imagine doing the same, but on the surface of a perfectly spherical meteorite instead – of course, walking in a straight line would end up with you inside the meteorite, which is impossible, but if you walk across the surface directly to your destination, that’s what a slerp is doing. Super simple stuff!

on-top-of-the-world

The flag looks like the USB logo, but it’s supposed to be an angle-axis diagram.

That rounds off pretty much all I know about quaternions and how much I could be bothered to look up online. If I got anything wrong, please do tell me because it’s definitely possible. Remember, if quaternions start to hurt your head, which happened plenty of times to me, keep in mind the most important thing: Don’t Worry About It™. You don’t need to know them inside out to be able to use them.

Advertisements

Radicool Trip 2 ~ WGD ‘Broken’ Two-Week Competition

The first thing I notice as I write this is that this is my 100th post on this blog! That averages out to a post every 10 or so days, so I really need to increase the frequency of my posts. I did want to do something special when this milestone came by, but I couldn’t think of anything I could do, so I’m just going to post as I normally would. Thanks to all my readers for supporting me up to this point! Hopefully there are many more posts to come. Also, I’m 13 days late with this post, since it’s the day before the two-week following this one. Ah well, I’m not known for my punctuality.

The themes for this jampetition was Broken, but due to an extra talk scheduled by the society, it lasted three weeks instead of the usual two. I guess that makes the title of this post quite misleading, but that’s not my fault! I decided to make a sequel to my previous game, Radicool Trip, although the gameplay is completely different. The game is also a sort-of 2D-3D hybrid, in which the world is 3D but you can only view the world from one plane at a time with an orthographic camera – that is, one that ‘looks straight’. It’s hard to explain, so here’s a screenshot:

radicool_trip_2_01

I like how the psychedelic colours for the background turned out.

The flagship mechanic of the game, which is unfortunately very difficult to show off with images, is the ability to flip the world around in the X, Y and Z axes. Imagine Fez, but instead of just rotating the world left and right, you can rotate it up, down, clockwise and anticlockwise too. That’s what the UI in the bottom-right corner is for. The controls are a bit awkward, but it’s the only way to represent three-axis world rotations. I’ve tried this before unsuccessfully in a 3D game, so I was happy to figure out how to accomplish it. You can move the player left and right using A and D, or by flipping the world so there’s empty space below you. But beware, falling off the world will respawn you from the beginning of the level.

radicool_trip_2_02

Of course I spent ages on text engines. What do you take me for?

A lot of the development time went on improving the text engine from Radicool Trip 1. It’s far more efficient and uses a better font than the previous engine. It’s also far easier to use, although I rushed the end of the game so it’s also very buggy. It worked out for the best though, because that made it fit the theme! There’s a bug where rotating the world and falling through two text triggers in a row causes them both to try and render at the same time, and another bug in the penultimate level that sometimes crashes the game inexplicably. I also set the wrong target level on the penultimate level’s goal so it sends you back to the first level, so it’s almost like some pretentious view on the repetitive, cyclic nature of life or something like that. But I swear it’s not.

I tried to write a bit of humour into the characters’ lines, although I also wrote them in about an hour before the jampetition showcase so it’s probably a little rusty. I’d really like to make an RPG of some kind at some point, so hopefully my shiny (yet broken) text engine will be of a lot of use for a project like that.

Anyway, you can find the game lurking in a corner of the internet somewhere! That horrifying corner is located on the very convenient link below.

The theme for the next two-week competition is Power, so you’ll very soon be seeing something I’ve been saving for a while. Plus, I’ll be posting about the WGD 48-hour game jam that happened this weekend even sooner; the theme for that was Translation.

download_banner