From Second Life Wiki
Jump to navigation Jump to search

Forget all the below math. If you want to understand quaternions, watch this video by Blender Guru Nathan Vegdahl. For even better understanding, it's part of a 4 chapter series explaining rotations within the Blender training DVD Humane Riging:

  1. Rotation Theory
  2. Axis Angle and Euler Rotations
  3. Quaternion Rotations
  4. Transform Matrices


quaternion is a keyword supported by the LSL compiler that means the same thing as, and is interchangeable with, rotation.

Definition and Properties:

Quaternions are a generalization of complex numbers, invented by William Rowan Hamilton in the mid-19th century. Recall that a complex number is the sum of an ordinary real number a and an imaginary number bi, where i is defined by:

i2 = -1

To construct a quaternion we introduce additional generalized imaginary units j and k with the assumptions:

j2 = -1; k2 = -1; ijk = -1

From these basic definitions it is easy to derive the multiplication relations for these generalized imaginary quantities:

ij = k; jk = i; ki = j


ji = -k; kj = -i; ik = -j

That is, the multiplication of quaternions is not commutative. While non-commutative operations are now a familiar feature of matrix algebra and vector and tensor analysis, at the time of their invention the idea was radical.

A quaternion is then a number of the form

Q = a + bi + cj + dk

where a,b, and c are ordinary real numbers. Adding quaternions is easy enough; one just adds the corresponding multipliers:

(a + bi + cj + dk) + (e + fi + gj + hk) = ( a+e) + (b+f)i + (c+g)j + (d+h)k

The result of multiplying two quaternions can be worked out using the product relations above, remembering to preserve the order of terms in i,j,k since the imaginary units do not commute.

QR = (a + bi + cj + dk)(e + fi + gj + hk) =

ae + afi + agj + ahk + bei - bf + bgij + bhik + cej + cfji - cg + chjk + dek + dfki + dgkj - dh

= ae + afi + agj + ahk + bei - bf + bgk - bhj + cej - cfk - cg + chi + dek + dfj - dgi - dh

= (ae - bf - cg - dh) + (af + be + ch - dg)i + (ag -bh + ce + df)j + (ah + bg - cf + de)k

(And you thought multiplying complex numbers was a mess!)

Now, we can define the analog of a complex conjugate (we'll use the * notation but other notations are also common):

Q*= a - bi - cj - dk

The product of a quaternion and its conjugate is:

QQ* = (a + bi + cj + dk)(a - bi - cj - dk) =

= (a2 + b2 + c2 + d2) + (-ab + ba - cd + dc)i + (-ac + bd + ca - db)j + (-ad - bc + cb + da)k

= (a2 + b2 + c2 + d2)

which looks rather like the square of a Euclidean length. If we regard the triplet (b,c,d) as a vector V, we can rewrite this squared length as:

QQ* = a2 + ||V||2

The first term, a, is thus often referred to as the scalar or sometimes the real part of the quaternion, and the triplet (b,c,d) as the vector part.

Quaternions and Rotations:

The reason we care about quaternions is that Second Life uses them to represent rotations. How is this done? Consider the quaternion representation of a vector V = (b,c,d), which is just a quaternion with a zero real part:

Q(V) = 0 + bi + cj + dk

If we multiply Q by some other quaternion, in general we will get a non-zero real part; that is, we've transformed the vector into a non-vector quaternion, which doesn't look at all like a rotation. However, if we multiply on one side by a quaternion z, and on the other side by the multiplicative inverse of z, z-1, we will get a result with a 0-value real part:

Re[zQ(V)z-1] = 0

-- that is, we'll map a vector into a vector. To see that this is so, note that from the formula for multiplication, the real part of the product of two quaternions is invariant to the order of multiplication, that is:

Re[QR] = Re[RQ].

So we can invert the order of the first and (second*third) quaternions in the mapping without changing the real part:

Re[z(Q(V)z-1)] = Re[(Q(V)z-1)z] = Re[Q(V)(z-1z)] = 0

since quaternion multiplication is associative and we assumed that Q has a zero-value real part. This operation of left-multiplying by a quaternion and right-multiplying by its inverse is known as conjugation by z. Readers familiar with matrix algebra will recognize it as similar to the decomposition of a matrix into a rotation and a pure scaling (a diagonal matrix).

Under what conditions does conjugation of a quaternion give back the original quaternion?

zQz-1 = Q implies zQ = Qz

(which can be easily shown by right-multiplying the first expression by z). When do quaternions commute? From the expression for the product of two quaternions, recalling that the real parts commute in general, we have for example for the part multiplying i:

(af + be + ch - dg)i + ... = (eb+ fa + gd - hc)i + ...

in the case where multiplication is commutative. This can only be true if ch - dg = 0 or c/d = g/h: that is, the slope of the vector part in the (j,k) plane is the same for both quaternions. Since there's nothing special about i, this must also be true of the (i,j) and (i,k) planes: that is, the two quaternions must have vector parts that point in the same direction, or in other words, that are collinear.

It's not too hard to show that conjugation is also linear (that is, the conjugate of the sum is the sum of the conjugates), and it's easy to see that the length of the vector part of Q is preserved under conjugation. What sort of length-conserving linear transformation preserves a vector only when its axis coincides with the vector? Why -- a rotation, of course. So conjugation of Q by z is equivalent to rotating the vector part of Q around the axis defined by the vector part of z.

Let's try a simple case. Consider the vector V = (1,0,0) and corresponding quaternion Q = 0 + i. To rotate around the z-axis we need a quaternion z of the form a + ck. The conjugation is then:

Q' = (a+c k)(i)(a + ck)-1

What is the inverse of z? It's easy to see that if we choose a and c so that the length of the quaternion is 1, then the inverse is equal to the conjugate:

len(z) = 1 = zz* implies z* = z-1

so we can write:

Q' = (a+c k)(i)(a - ck) = (a+c k)(ai + cj) = a2i + acj + caj - c2i = ( a2- c2)i + 2acj

with the constraint:

a2+ c2 = 1

implying that we can write a = cos(θ/2), c = sin(θ/2) for some angle θ (the reason for the factor of 1/2 will become clear in a moment).

Now, the terms in i and j become respectively:

cos2(θ/2) - sin2(θ/2) = cos(θ)


2 cos(θ/2) sin(θ/2) = sin(θ)

So this indeed represents a rotation of the k (z) axis by the angle θ. We can infer that in the general case, to rotate a vector V around an axis A= (b,c,d) (presumed normalized, that is ||A|| = 1) by an angle θ, we construct the quaternion

z = cos(θ/2) + sin(θ/2)A = cos(θ/2) + sin(θ/2){bi + cj + dk}

and then conjugate the quaternion Q = 0 + V with z :

Q' = zQz*

from which we extract the vector part:

Q' = 0 + V'

V' being the rotated vector V.

In Second Life, quaternions representing rotations are given as four floating point numbers. The first three are the vector part, and the last is the scalar part: Q = <Q.x, Q.y, Q.z, Q.s>. In terms of Second Life region directions, the East-West direction is the x-axis, the North-South direction is the y-axis, and the Up-Down direction is the z-axis. Recall that x maps to the imaginary i axis, y to j, and to z to k. We can see that this is a right-handed coordinate system; if you position your right hand such that, without changing it's orientation, your extended fingers point in the plus x direction (East) and flexing your fingers point them in the plus y direction (North), then extending your thumb, in the plane of your palm and perpendicular to you fingers, points it in the plus z direction (Up). Default angles of rotation are defined in radians, from -π (-pi) to π (pi); that is, we can rotate counter-clockwise (in the positive direction - rotating from plus x axis (East) through the plus y axis (North) to the minus x axis (West)) half-way around, or in the clockwise (negative - rotating from plus x axis (East) through minus y axis (South) to minus x axis (West)) direction half-way around, with the two directions giving the same physical result at a rotation angle of 3.141 radians or 180 degrees. Thus a counter-clockwise rotation of a face pointing West, around the z axis by 90 degrees (to point South) is:

<0, 0, 0.707, 0.707>

since the sine and cosine of π/4 (half of the rotation angle) are both 1/20.5.

Example rotation.jpg

Continuing around to point East is either

<0, 0, 1, 0> or <0, 0, -1, 0>

Tilting an object to the right (that is, rotating it counter-clockwise around the x-axis) by e.g. 90 degrees is described by:

<0.707, 0, 0, 0.707>

and pitching forward (clockwise around the y-axis) by the same amount is

<0, -0.707, 0, 0.707>.

It's important to note that the mapping of a single vector does not uniquely specify the corresponding quaternion rotation. For example, in the figure below we see a number of ways to rotate the x axis into the y axis. Different rotations result in different final orientations of the orthogonal (y and z) directions.

Alternate rotations.jpg