Quaternions comment from my cell

Only unit quaternions represent rotations: is a false statement
Let q be a unit quaternion which represents a rotation. Let p be a coordinate in R3 which we map to H by setting the scalar to zero. Then the equation:

p' = qpq<sup>-1</sup>

is p rotated by q. Multiply q by non zero scalar s.

(sq)p(sq)<sup>-1</sup> = s(qp)(s<sup>-1</sup>q<sup>-1</sup>) = (s/s)qpq<sup>-1</sup> = p'

scalars commute so the terms s and 1/s cancel so it yields the same result.

If we change the equation to using the conjugate then we get the same for unit since q<sup>-1</sup> = q<sup>*</sup> in that case.

p' = qpq<sup>*</sup>

and for non unit the scale factors compose yielding the rotation plus a uniform scaling by s2:

p'' = (sq)p(sq)<sup>*</sup> = s<sup>2</sup>(qpq<sup>*</sup>) = s<sup>2</sup> p'

If we change the mapping of p to setting the scalar to one then we are back to an unscaled rotation.

Some implications:

  • All quaternions except zero can represent a rotation.
  • The set of all quaternion that represent the same rotation fall on a line through the origin.
  • There are only two points the line intersects the unit sphere: q and -q.
  • If two quaternions don’t fall on the same line through the origin then they represent different rotations.

Some slerp basics
Slerp is just the complex number equation: z<sup>n</sup> (principle power function) which linearly parameterizes the arc between one and the angle represented by z. For slerp we want the same between a and b. To get there we transform the system.

Let c = a<sup>*</sup>b

Now between one and c is a linear transformed version of a and b. Performing the operation (ct) and transform the system back to it’s original space (pre-multiply by ‘a’) yields:

s(t)= a(a<sup>*</sup>b)<sup>t</sup> = (ba<sup>*</sup>)<sup>t</sup>a

where the right hand is just performing the pre/post transform operations on the opposite side (since quaternion multiplication doesn’t commute). Note this is the same technique that’s used to represent a rotation about arbitrary point with 3x3 matrices. We can rotate about the origin so to generalize to any point we translate to origin, perform the rotation and translate back.

Or to skip on quaternion specifics then we have the 2D parametric function: (cos(t k), sin(t k)), where ‘k’ is implicit angle between ‘a’ and ‘b’. The ‘x’ direction is ‘a’ and the ‘y’ direction is orthogonal to ‘x’ in the same half plane as ‘b’. So the direction of ‘y’ is simply ‘b’ with b’s parallel projection into ‘a’ removed from it: b-a(b.a) That normalized along with ‘a’ give us our 2D orthonormal basis in our 4D space. So slerp is so:

s(t) = cos(tk) a + sin(tk) || b-a(b.a)) ||

where ||.|| normalizes the expression.

If we start going nuts and replacing everything with as much trig as possible (since trig and inverse trig is so fast on a computer):
a.b = b.a = cos(k) b-a(b.a) = b - a cos(k) |b-a(b.a))| = sin(k)

so now we have:
s(t) = cos(tk) a + sin(tk) (b - a cos(k))/sin(k) = (cos(tk) - cos(k)sin(tk)/sin(k))a + sin(tk)/sin(k)b = ((cos(tk)sin(k) - cos(k)sin(tk))/sin(k))a + sin(tk)/sin(k)b = (sin((1-t)k)/sin(k))a + sin(tk)/sin(k)b

where the final version is the commonly seen form. But the actually interesting form is the second…well once we re-remove all that trig B.S.

Why should slerp() never be used?

Why lerp instead of slerp
Directly implementing the equations above is insanely expensive so Shoemake/Davis reworked into want you see everywhere. But it’s completely ignores that one can approximate the equation to high accuracy. Also there are other methods of exact calculation.

We have two rotations a and b which we want to interpolate. Assuming they are unique we know that they fall on two different lines through the origin.

Given the largest possible minimal angle is pi which translates into pi/2 in H.

https://latex.codecogs.com/png.latex?\dpi{100}&space;\fn_cm&space;Lp\left(t\right)=atan&space;\left(\frac{t\sin&space;(\theta&space;)}{1+t&space;(\cos&space;(\theta&space;)-1)}\right)

https://latex.codecogs.com/png.latex?\dpi{100}&space;\fn_cm&space;Lv\left(t\right)=\frac{\sin&space;(\theta&space;)}{1-2&space;(t-1)&space;t&space;(\cos&space;(\theta&space;)-1)}}

https://latex.codecogs.com/gif.latex?\fn_cm&space;\frac{1}{2}-\frac{\sqrt{\theta&space;\sin&space;(\theta&space;)&space;\left(\sin&space;^2(\theta&space;)-\theta&space;\sin&space;(\theta&space;)+(\cos&space;(\theta&space;)-1)^2\right)}}{2&space;\theta&space;(1-\cos&space;(\theta&space;))}

Did some minor clean-up of my two posts. While waiting for me to be either motivated to type equations on a cell or be back from vacation, you can check out this: http://zeuxcg.org/2015/07/23/approximating-slerp/

I haven’t checked the results, all of the math is overcomplicated IMO and the resulting methods are too expensive (again IMHO)…but still way cheaper than doing shoemake/davis.

Oh and for systems that can be run at a fixed time step (and results perhaps blended from the time steps)…all of this is moot. The problem is easy.