Quaternions and Anim8or

A **quaternion** is a 4 dimensional real number. Mathematically
they are an extension of the more widely used 2 dimensional **complex number**
system. As a special case, **unit quaternions**, those with a magnitude of
1, are useful in representation rotations and orientations if a 3 dimensional
space, allowing a simple implementation of smooth rotations along a single
axis, splines, etc. Anim8or uses unit quaternions for this reason. Through this
discussion the term *quaternion* is synonymous with *unit quaternion*
unless otherwise indicated.

Here quaternions are shown as a 4 vector of scalar values:

**Q** = (x, y, z, w)

Alternate they can by represented as a 3 vector plus a scalar (a format that allows a more elegant mathematical characterization, which is not the purpose of this note):

**Q** = (**v**3, s)

I'll leave the heavy math for later.

Alternately orientations and rotations can be represents by **Euler
angles** which are 3 vectors of real values representing the pitch (rotation
about the X axis), yaw (Y axis), and roll (Z axis):

**E** = (p, y, r)

Here are some simple Euler rotations:

While Euler angles are easier to understand, and to relate
the individual comports to our 3D world, they are difficult to interpolate
smoothly and suffer from **gimbal lock**, a condition that prevents rotation
when two axes are aligned.

To make the discussion easier to illustrate, we'll simply
the discussion to two dimensions. In a 2D Euler world an object can rotate on 2
axes. Assume that we want to smoothly rotate the sphere from its initial point
indicated by the blue arrow *E1** = (0, 0),* to the
position indicate by the red arrow *E2** = (45, 0)*, all that's
needed is to interpolate the X value from 0 to 45 (there is no rotation around
the length of the arrow):

Alternately the orientation of the blue arrow could be
represented by *E1** = (360, 0)*. Then the
obvious way to interpolate between would rotate in the opposite direction,
making almost a full circle:

This is not what we usually want to do. However it is simple
to avoid by adjusting one of the values by 360 so that *| E2 - E1| < 180*
before interpolating. Note that when the difference is exactly 180 there is no
way to know which way the rotation should go.

As mentioned before, interpolating Euler angles in 3 dimensions is more complex, but it is not necessary to understand how to do that here.

Quaternion interpolation always interpolates the shortest
path between values. However, it's the shortest distance *in quaternion space*,
not necessarily the same as in 3D space. To better understand this behavior,
and how to avoid undesirable rotation, we need a little more background.

Each orientation has 2 distinct quaternions. Negating all 4 scalar values does not change the orientation. That is:

**Q** = (x, y, z, w) and **Q' **= (-x, -y, -z, -w)

are identical orientations.

Quaternions are interpolated using a function called **slerp**,
or **spherical linear interpolation**

**slerp**(**Q1**, **Q2**, t), 0 <= t <= 1

It's not necessary at this time to understand its
implementation, just to note that it smoothly rotates from one orientation to
another based on the value of *t*.

However ** slerp**
treats

**slerp**(**Q1**, **Q2**, t) ≠ **slerp**(**Q1'**,
**Q2**, t)

One formula rotates along the shorter path in 3D space,
while the other follows the longer one. It's easier to understand how this
works if you visualize an orientation as a point on the surface of a Mobius strip.
As in the Euler example above, the angle around a Mobius strip represents one
of the angles in an orientation. The gold and copper balls represent the same
orientation but two quaternions**
Q1** and

Now let's see how far, in degrees, it is from ** Q1**to

If you instead start at**
Q1'** the counterclockwise direction requires 315 to reach

How does this relate to the ** slerp** function and Anim8or?

__Problem:__ You are creating .an8 files for an
animation. You are converting Euler angles into quaternions. Occasionally between
two key orientations, ** Qn**
and

__What's happening: __ ** Qn+1** is incorrect. Instead you need
to use

__How do you know when to use ____Q'____?__ Fortunately
there is an easy solution. If the *dot(Qn,
Qn+1) **<
0* then *slerp**( Qn, Qn+1, t)*
will rotate more than 180 degrees, where:

**dot(Q1, Q2)** = **Q1**.x***Q2**.x +** Q1**.y***Q2**.y
+** Q1**.z***Q2**.z +** Q1w**x***Q2**.w

So if the dot product is negative, use ** Qn+1'** by negating
all the values in

--- Steve, July 18, 2015.