Sei sulla pagina 1di 119

Understanding Rotations

Jim Van Verth Senior Engine Programmer, Insomniac Games jim@essentialmath.com

Introductions. Name a little misleading, as truly understanding rotations would require a deep understanding of group theory, which I honestly neither have, nor have time to present. So a better name might be

Understanding Rotation Formats


Jim Van Verth Senior Engine Programmer, Insomniac Games jim@essentialmath.com

Which isnt say I wont be covering other aspects of rotation, its just that that will be the primary focus of this talk.

Intro
Discuss

various rotation reps

Angle (2D), Euler angles/Axis-angle (3D) Matrix (2D & 3D) Complex numbers (2D), Quaternion (3D)

The order here is an attempt to compare similar formats across 2D and 3D.

Intro
Issues

to consider

# elements Concatenation Interpolation Rotation

Intro

Interpolating not as simple as position, but more important E.g. camera control

Store orientations for camera, interpolate Body location stored as point Joints stored as rotations

E.g. character animation


Intro
Orientation relative to reference frame

On the previous slide, I mentioned orientation and rotation. Throughout the talk I may use them interchangeably, and I want to make sure that the distinction between them is clear. Orientation refers to where the axes of the reference frame (or coordinate system) lie.

Intro
Orientation relative to reference frame

Those axes are relative to a fixed reference frame, marked in green in this diagram.

Intro
Orientation relative to reference frame Rotation changes object from one orientation to another

Rotation is the operation that takes us from one orientation to another one, represented here by the black arrow.

Intro
Orientation relative to reference frame Rotation changes object from one orientation to another Hence, represent orientation as a rotation

So, it is possible to represent orientation as a rotation from the reference frame, which is what we usually do.

Ideal Rotation Format


Represent degrees of freedom with minimum number of values Allow concatenations of rotations Math should be simple and efficient

concatenation interpolation rotation

So what do we look for in an ideal rotation format?

Topics

Angle (2D) Euler Angles (3D) Axis-Angle (3D) Matrix (2D) Matrix (3D) Complex number (2D) Quaternion (3D)

Topics

Angle (2D) Euler Angles (3D) Axis-Angle (3D) Matrix (2D) Matrix (3D) Complex number (2D) Quaternion (3D)

2D Angle

The simplest rotation format is just the angle between the original coordinate axes and the new ones. Its the same for x and y axes, so

2D Angle

To simplify things Ill just use the angle between the old and new x axes.

2D Angle

This angle can also be negative, btw.

2D Angle: Concatenation

Concatenation is very simple. If we rotate by an angle theta and then an angle phi

2D Angle: Concatenation

We can represent this by a single angle theta plus phi

2D Angle: Concatenation

Note: 2D rotation is commutative

Note that because addition is commutative, this concatenation is commutative, so rotating by phi first and then theta we get the same result.

2D Angle: Concatenation

And so we have the final rotation.

2D Angle: Interpolation

Blending between angles is just about as simple, but there are some gotchas to be aware of. So suppose we have a rotation theta and a rotation phi (a different phi than the previous one, in this case)

2D Angle: Interpolation

Q(,,t) =?

And we want to find a rotation between them, using an interpolation factor t that varies from 0 to 1.

2D Angle: Interpolation

Q(,,t) = (1-t)+t

This is pretty simple, we can just do a linear interpolation between theta and phi. This formula should seem familiar after Squirrels talk.

2D Angle: Interpolation
What if = 30 & = 390? Expect always same angle But (1-t)+t will vary from 30 to 390

However, as mentioned, there are gotchas. Suppose we have angles of 30 degrees and 390 degrees. These are the same rotation, but if we do a straight linear interpolation, well end up with angles between 30 and 390, when wed expect to not rotate at all.

2D Angle: Interpolation
Problem One: angles not well-formed Infinite # of values can represent one rotation: 30 = 390 = -330 Can constrain to [0,360) or [0, 2)

So thats one problem with angles: you can have an infinite number of values that represent one rotation. The simplest solution here is to just constrain the angles to a range, 0 to 360 or 0 to 2 pi if youre using radians.

2D Angle: Rotation
Idea: vector/point coordinates relative to coordinate frame Change in frame gives change of coordinates

How about rotation. Here things get a little more complicated, but not too bad. As the slide says, the coordinates that we use for both vectors and points are relative to the coordinate frame were using. So if we track how the frame changes, we can compute the new coordinates. Its all part of the magic of vector spaces or affine spaces in this case.

2D Angle: Rotation

So, returning to our original diagram, with both angles in this case.

2D Angle: Rotation
sin "

! !

cos"

sin "

cos" !
The original axes have coordinates (1,0) for the x axes and (0,1) for the y axes. Their length is one, so by trigonometry, we can easily compute the coordinates of the new axes relative to the new ones, namely (show) cos theta here and sin theta here. And the same for the y axes.

2D Angle: Rotation
( " sin # ,cos # )

sin "

(0,1)

(cos" ,sin " )

! !

cos"

sin "
(1,0)

cos" !
!
So our new coordinates are cos theta, sin theta for the x axis and -sin theta cos theta for the y-axis.

2D Angle: Rotation
( " sin # ,cos # )

(0,1)

(cos" ,sin " )

(1,0)

!
Simplifying, just to make it a little more clear.

2D Angle: Rotation
Point Point

in old frame ( x, y ) = x (1,0) + y (0,1) in new frame

R( x, y," ) = x (cos" ,sin " ) + y ( # sin " ,cos" ) = ( x cos" , x sin " ) + ( # y sin " , y cos " ) = ( x cos" # y sin " , x sin " + y cos " )
So as I mentioned, the coordinates that we use are relative to our current frame. So for a point x, y, this just means that we take x and multiply it by (1,0) and take y and multiply it by (0,1). That gives us x,y as we expect. For the new frame, we just take our original x, y and multiply by the new axes. So thats x times cos theta, sin theta, and y times -sin theta cos theta, which simplifies to this final result for our rotation equation.

2D Angle: Rotation
So

rotation of vector (x,y)

R( x, y," ) = ( x cos" # y sin " , x sin " + y cos " )


Problem two: have to calc sin and cos to rotate

!
So we derived our rotation formula, but as we can see, in order to compute this well have to compute a sin and cos, which is not always the fastest operation.

2D Angle: Summary

Compact (1 value) Concat easy (add) Interpolation doable Rotation not ideal Be careful of infinite values

Topics

Angle (2D) Euler Angles (3D) Axis-Angle (3D) Matrix (2D) Matrix (3D) Complex number (2D) Quaternion (3D)

So thats angles in 2D. Now were going to look at formats that use angles for 3D rotation. Well begin with Euler angles.

Euler Angles
Three

ordered rotations around orthogonal axes

o
Could

be world or local axes Order important! 3D non-commutative

y
Demo

Euler angles are just like single 2D angle, except that instead of rotating around a single (implied) axis, were rotating around 3 different axes. This follows from Eulers theorem that all 3D rotations can be represented by three ordered rotations, hence the name.

Euler Angles vs. Fixed Angles


Euler

angle - rotates around local axes Fixed angle - rotates around world axes Rotations are reversed

x-y-z Euler angles == z-y-x fixed angles

Often there are differences in terminology for these -- some people like to refer to Euler angles as those rotate only around the local axes of the object, while they refer to rotations around the world axes as fixed angles. They behave similarly - to get from one to the other you just reverse the rotation order. But often times youll just see both kinds referred to as Euler angles, so just be aware of which axes youre rotating around.

Euler Angle Issues


No

easy concatenation of rotations Still has interpolation problems Can lead to gimbal lock

Euler angles, despite being compact, have some serious problems that make it undesirable as a general rotation format. First, our easy addition of angles goes out the window with Euler angles. Secondly, our interpolation problems are even worse. Finally, when axes align after a series of rotations, we can end up with something called gimbal lock, where we lose one degree of freedom. Lets look at these problems in turn.

Euler Angle Concatenation


Can't

just add or multiply components Best way:


Convert to matrices Multiply matrices Extract euler angles from resulting matrix

Not

cheap

Euler Angle Interpolation


Example:

Halfway between (0, 90, 0) & (90, 45, 90) Lerp directly, get (45, 67.5, 45) Desired result is (90, 22.5, 90)

Can

use Hermite curves to interpolate


Assumes you have correct tangents

AFAIK,

slerp not even possible

Gimbal Lock
Euler/fixed

angles even less well-formed Different values can give same rotation Example with z-y-x fixed angles:

( 90, 90, 90 ) = ( 0, 90, 0 )

Why?

Rotation of 90 around y aligns x and z

axes Rotation around z cancels x rotation


Demo

Euler Angles

Good for interface Not so good for in-engine

So in summary: Euler angles -- avoid them!

Topics

Angle (2D) Euler Angles (3D) Axis-Angle (3D) Matrix (2D) Matrix (3D) Complex number (2D) Quaternion (3D)

So lets look at another 3D angle format and see if that works better for us: axis-angle.

Axis and Angle


Specify vector, rotate ccw around it Can interpolate, messy to concatenate

Euler also proved that any 3D rotation can be represented as a rotation around an arbitrary axis. So axis-angle is just as it sounds -- we specify an axis and how much were going to rotate around it, in a counterclockwise direction (right-hand rule). Im not going to spend a lot of time on axis-angle as it has its own brand of problems. Interpolation is pretty simple - you can just blend the axis and angle separately and get a reasonable result. However, concatenation is much the same as Euler angles -- you have to convert to a matrix (or another format, which well get to) -- concatenate, then convert back. In my opinion, its just not worth it.

Axis and Angle

Rotation
," ) = cos " # p + (1 $ cos " )(p r )r + sin " (r % p) R(p, r

However, it is convenient at times to be able to rotate something by an axis-angle representation, so heres the formula for that. As you can see, this is not the simplest operation either.

Axis and Angle


More of a transitional format I.e. convert to axis-angle, manipulate angle or axis, convert back

Well see an example of this with 3D matrices in a bit.

Topics

Angle (2D) Euler Angles (3D) Axis-Angle (3D) Matrix (2D) Matrix (3D) Complex number (2D) Quaternion (3D)

Ok, now were going to bounce back to 2D and consider a much nicer and (hopefully) familiar format, the matrix.

2D Matrix

Recall
( " sin # ,cos # )

(0,1)
(cos" ,sin " )

!
!

(1,0)

So going back to our original axis diagram, ! recall that our original axes change coordinates to these value.

2D Matrix
Idea: Bake new frame in matrix and multiply by vector to rotate Matrix represents transformation

The idea of a matrix is simple: we bake this new frame in the matrix, and then matrix multiplication will do the coordinate transformation for us. By the way, if you understand this -and I am going to go a bit fast on this, so I apologize -- but if you understand it, you can handle any transformation you need to compute. If you want one area of linear algebra to study that will help you be successful in computer graphics or even physics, this is it.

2D: Matrix
Change

in frame

(1,0) " (cos# ,sin # ) (0,1) " ( # sin $ ,cos$ )

Rotation matrix $ cos" ! & %# sin " !

sin " ' ) cos" (

(assumes row vectors)

!
So in the standard case, where were working with Euclidean frames, we dont need to do anything special, just drop the new frame in. Assuming that were using row vectors, that is, our multiplication order is from left to right, then were going to insert our new frame in as the rows of the rotation matrix.

2D: Matrix
Change

in frame

(1,0) " (cos# ,sin # ) (0,1) " ( # sin $ ,cos$ )

Rotation matrix $ cos" ! & %# sin " !

sin " ' ) cos" (

(assumes row vectors)

!
Just to make it more clear, our first row is the same as our new x-axis

2D: Matrix
Change

in frame

(1,0) " (cos# ,sin # ) (0,1) " ( # sin $ ,cos$ )

Rotation matrix $ cos" ! & %# sin " !

sin " ' ) cos" (

(assumes row vectors)

!
And the second row is the same as the new y-axis.

2D Matrix: Rotation

[x

$ cos " y ]& % # sin "

sin " ' ) = [ x cos" # y sin " cos " (

x sin " + y cos" ]

And multiplying it out, we get the same result as before from our angle formula.

2D Matrix: Concatenation
$ cos" & %# sin " sin " '$ cos * )& cos" (% # sin * sin * ' $ cos(" + * ) )=& cos * ( %# sin(" + * ) sin(" + * ) ' ) cos(" + * ) (

Concatenation also uses multiplication, but this time were multiplying two rotation matrices together. After multiplying and using some trigonometric identities to simply, we can see that we get the result we expect: the angle in the new matrix is just the sum of the original two angles. Note again that the multiplication order doesnt matter here because were doing 2D rotation. That wont be the case when we get to 3D.

2D Matrix: Interpolation
Lerp

values:
" 1 0% "0 (1% " 0.5 (0.5% 0.5$ ' + 0.5$ ' =$ ' # 0 1& #1 0 & # 0.5 0.5 &

isnt a rotation matrix! ! Need Gram-Schmidt orthonormalization


So rotating a vector and concatenating rotations are fairly nice. What about interpolation. Well, here things start to fall apart. If we take these two rotation matrices: one with no rotation and the other a rotation of negative 90 degrees, and try to do a linear interpolation between them, we get a bad result. The resulting row vectors are not unit length, so this is not a rotation matrix. Now, we can do Gram-Schmidt orthonormalization to solve this problem, but it doesnt solve all of our problems.

Result

2D: Matrix
Lerp

values:
# 0 "1& # 0 1& #0 0& 0.5% ( + 0.5% ( =% ( 1 0 " 1 0 $ ' $ ' $ 0 0'

Not

even a valid affine transformation

!
For example, interpolating from a rotation of negative 90 degrees to a rotation of positive 90 degrees, gives us an extremely bad matrix. So what can we do about this?

2D Matrix: Interpolation
Example

Lets take a look at whats going on here, by examining where the axis vectors go. So here are the frames for two possible rotations, the red being about a rotation of -45 degrees, the blue being a rotation of about positive 90 degrees.

2D Matrix: Interpolation
Example

And suppose we want to interpolate between them.

2D Matrix: Interpolation
Look

at just x-axis

To simplify things, lets just look at the x-axis.

2D Matrix: Interpolation
Lerp

If we linearly interpolate between the two x-axes, thats basically just drawing a line from vector tip to vector tip

2D Matrix: Interpolation
Lerp

And picking points along the line. Here Ive spaced them out at t values of 1/4, 1/2, and 3/4. Note that they are clearly shorter than our original vectors, so theyre no longer unit length. Now, we could do our orthonormalization process, which would make these vectors unit length again.

2D Matrix: Interpolation

Lerp, extended to unit length

And here we see the result of that. However, now we have another problem.

2D Matrix: Interpolation
But

equal time != equal spacing

Note that along the line, the vectors are equally spaced, but along the rotation arc theyre not. What wed really like is that as we move in time, using our interpolant t, that our rotation would move equally as well.

2D Matrix: Interpolation
Subdivide

arc, not line

Spherical

linear interpolation, or slerp

So heres a diagram showing that -- note that now the arc of rotation is now subdivided equally. This is called spherical linear interpolation, or (as Ken Shoemake says, because its fun): slerp.

2D Matrix: Interpolation
Idea: compare position operations to orientation
Be

x + y " xy x # y " xy #1 ax " x a

careful of order! (important for 3D)

!
So how can we compute slerp? One way to think about this -and for any mathematicians in the audience this is admittedly not a formal proof, but perfectly appropriate -- we can take the operations we use for linear interpolation and take them up one level to get the appropriate operations for rotation matrices. Then we can use this to convert our linear interpolation formula to a spherical linear interpolation formula. So where we would add two angles, we multiply two matrices. Where we would subtract one angle from another, we multiply by the matrix inverse. And where we would scale an angle, we instead take the rotation matrix to the same power.

2D Matrix: Interpolation

Apply to lerp

x + y " xy x # y " xy #1 ax " x a

( x1 " x 0 ) t + x 0

Gives slerp formula

(M1M 0 "1 ) t M 0

!
Apply this to our lerp formula, we get the following slerp ! formula. And as I mentioned on the previous slide, this order is important -- while any order is reasonable for 2D rotations because (all together now) theyre commutative, this is not the same for 3D rotations. However, both of these slides do bring up a question.

2D Matrix: Interpolation

But what is M t ? General: Taylor series 2D rotation simpler:


t ( M ) ! " = M t"

(M1M 0 "1 ) t M 0

What is M to the t? For general matrices, this is just a function, and you can compute an approximation by using a Taylor series expansion (Gino will say more about Taylor series in the next talk). However, in our case were only considering rotation matrices, so the answer is much simpler. All you need to do is pull the angle out of the matrix, multiply it by t, and generate a new matrix for that angle.

2D Matrix: Interpolation

Process:

Compute Then

M = M1M 0

"1

(M1M 0 "1 ) t M 0

Finally

" = atan2(M 0,1, M 0,0 )

!
!

M t" M 0

So the process is just this. Note that M0,1 is sin theta, and m0,0 is cos theta, so we can take the arc tangent to get the correct angle.

2D Matrix: Interpolation

An alternative (only for 2D):


Lerp the first row Renormalize Rotate 90 degrees to get the second row Build new matrix But need to correct for time (discuss later)

2D Matrix: Interpolation

Blend multiple matrices, e.g. skinning


Maya gives you weights, just lerp Can use De Castlejaus Algorithm w/slerp Alternative: dual quaternions

2D Matrix: Recap

Rotation: fast Concatenation: fast Lerp/slerp: unwieldy Also: 4 values to represent 1 d.o.f.

Topics

Angle (2D) Euler Angles (3D) Axis-Angle (3D) Matrix (2D) Matrix (3D) Complex number (2D) Quaternion (3D)

3D: Matrix
Much

the same as 2D matrix

Map transformed axes, store as rows of matrix Rotate via vector-matrix mult Concatenate via matrix-matrix multiplication (but no longer commutative)

3D Matrix: Interpolation
Lerp

same problems as before

9 values to interpolate dont interpolate well

Slerp

even harder to compute

t (M( r ) = M( r ," ) , t" )

3D Matrix: Summary
Workhorse of 3D graphics Great for rotation and concatentation (especially w/vector processors) Inconvenient for interpolation

Topics

Angle (2D) Euler Angles (3D) Axis-Angle (3D) Matrix (2D) Matrix (3D) Complex number (2D) Quaternion (3D)

2D: Complex Numbers


Review:

a + bi
where

i = "1

!
!

But

ignore that imaginary crap

2D: Complex Numbers

First important bit


Imaginary

a + bi

b
!

Real

2D: Complex Numbers

Second important bit


( a + bi)(c + di) = ( ac " bd ) + (bc + ad )i

Another way to think of it


( a, b)" (c, d ) = ( ac # bd, bc + ad )

2D: Complex Numbers

Suppose: restrict to unit length


Imaginary

cos" + sin "i sin "

" !
Real

Also

! written as cos" + i sin " = e i" !

cos"

2D: Complex Numbers


Multiply general complex number by unit one

( x + yi)(cos" + sin "i) = ( x cos " # y sin " ) + ( x sin " + y cos " )i

Look familiar? Gives us rotation

2D: Complex Numbers

Concatenation
(cos" + sin "i)(cos # + sin #i) = (cos(" + # )) + (sin(" + # ))i

2D: Complex Interpolation


Lerp

similar, but can normalize (nlerp)

Lerping our complex numbers is much like matrixes, except in this case each arrow represents an entire complex number instead of just the x-axis of a matrix. So rather than doing the full orthonormalization process we can just perform our linear interpolation and then just do one normalization operation. This is often called nlerp. That said, the same problems still remain with non-equal subdivision of our rotation arc, so lets look at slerp again.

2D: Complex Interpolation

Slerp

Want to find qt

q1 qt t q0

In generating a formula for slerp with complex numbers we can take a different approach than with matrices. Suppose we have two complex numbers q0 and q1 and we want to blend between them. The angle between them is alpha, and we want to find the complex number thats alpha t between the two.

2D: Complex Interpolation

Slerp

q" 1

Create basis

q1 qt t q0

Suppose we can find a perpendicular to q0 based on q1 -well just call that q1. That gives us a coordinate frame..

2D: Complex Interpolation

Slerp

q" 1

Generate coords

q1 qt t q0

sin "t

cos "! t
And we can use this frame to generate coordinates for our new q_t. As before, the distance along the q0 axis is just cos ! the q1 axis is sin alpha t. alpha t, and the distance along

Complex Number Interpolation

Slerp

q" 1

Then

q1 qt t q0

qt = cos "tq0 + sin "tq1 # ! !

sin "t

cos "! t
So for an arbitrary q0 and q1, our slerped complex number is this.

2D: Complex Interpolation

Finding q" 1

In 2D can do

q0"

q" 1

q1 qt t q0

!
!

That leaves one open question: how to we compute this q1? Well, in 2D we can just rotate q0 90 degrees to get the perpendicular.

2D: Complex Interpolation

Finding q" 1

q" 1

In general, q1 # (q0 q1 )q0 q1 "= q1 # (q0 q1 )q0 Simplifies to

q1 qt t q0

!
!

q" 1 =

q1 # cos $q 0 sin 2 $

But lets consider the general case -- this will be useful when we get to quaternions. We can compute this by projecting q1 onto q0, subtracting the result from q1, and then normalizing. This is just one step in Gramm-Schmidt orthonormalization. For the case of our unit complex numbers (or any unit vector, for that matter), this just simplifies to this.

2D: Complex Interpolation

Slerp

Combine qt = cos "tq0 + sin "tq1 #


q" 1 = q1 # cos $q 0 sin 2 $!

q" 1

q1 qt t q0

!
!

Get
qt = sin(1 " t )# sin t# q0 + q sin # sin # 1

Combining our two formulas together we get the following,

2D: Complex Interpolation

Slerp

Combine qt = cos "tq0 + sin "tq1 #


q" 1 = q1 # cos $q 0 sin 2 $!

q" 1

q1 qt t q0

!
!

Get
qt = sin(1 " t )# sin t# q0 + q sin # sin # 1

which is our final slerp formula.

2D: Complex Interpolation

Slerp

Combine qt = cos "tq0 + sin "tq1 #


q" 1 = q1 # cos $q 0 sin 2 $!

q" 1

q1 qt t q0
"1 Same as: qt = q0 (q0 q1 ) t

!
!

Get
qt = sin(1 " t )# sin t# q0 + q sin # sin # 1

Btw, it can be shown that this gives the same !result as our other slerp formula. However, this one is more practical to compute.

2D Complex Interpolation

Slerp not ideal


qt =

sin(1 " t )# sin t# q0 + q sin # sin # 1

Computing , sin , sin t slow Numeric error as 0

Also, depending on how we calculate alpha, this can be noncommutative as well, I.e. slerping from q0 to q1 is not the same as slerping from q1 to q0 -- you end up going different ways around the circle. That said, most implementations assume that alpha is greater than 0, which will make it commutative.

Faster Slerp
Lerp

is pretty close to slerp Just varies in speed at middle Idea: can correct using simple spline to modify t (adjust speed) From Jon Blows column, Game Developer, March 2002 Lerp speed w/slerp precision
Demo

Faster Slerp

In practice, we have small angles nlerp alone may well be good enough

Complex Numbers

Note:

complex multiplication is commutative, as is 2D rotation

Complex Numbers

Half-angle form
q = (cos(" /2) + sin(" /2)i)

Then rotation could be


Rot(p," ) = qpq

!
Still

unit length

Complex Numbers: Half Angle


Oddity:

negatives apply same rotation


Imaginary

cos" /2 + sin " /2i


" /2
Real

" cos# /2 " sin # /2i

!
!

Complex Numbers: Half Angle


Semi-circle

rep. all rotations

Imaginary

cos" /2 + sin " /2i


" /2
Real

" cos# /2 " sin # /2i

!
!

Complex Numbers: Summary


In

practice not used all that often Not sure why -- probably because angles are simple enough

Topics

Angle (2D) Euler Angles (3D) Axis-Angle (3D) Matrix (2D) Matrix (3D) Complex number (2D) Quaternion (3D)

What is a Quaternion?
Created

as extension to complex numbers

becomes
Can Or

rep as coordinates

scalar/vector pair

What is Rotation Quaternion?


Unit

quat is rotation representation

also avoids f.p. drift

Why 4 values?
One

way to think of it: 2D rotation ->


One degree of freedom
Unit

complex number ->


One degree of freedom Three degrees of freedom

3D

rotation -> quaternion ->


Three degrees of freedom

Unit

What is Rotation Quaternion?


Unit

quat (w, x, y, z) w represents angle of rotation y, z from normalized rotation axis ^ r ^ (x y z) = v = sin(/2)r Often write as (w,v) In other words, modified axis-angle
x,

w = cos(/2)

Creating Rotation Quaternion


So

for example, if want to rotate 90 around z-axis:

Creating Rotation Quaternion


Another

example

Have vector v1, want to rotate to v2 Need rotation vector ^ r, angle


r v1 v2

Plug into previous formula

Thats gives a particular solution. But suppose we want to generate a quaternion a little more programmatically. A case that comes up often is that we have a vector pointing in one direction, and we want to generate a quaternion that will rotate it to a new direction. One way we might think of doing this is just take the cross product to get our axis of rotation r, then take the dot product of the normalized vectors, and take the arccos of that to get the angle, and plug the result into the quaternion.

Creating Rotation Quaternion


From

Game Gems 1 (Stan Melax) Use trig identities to avoid arccos


Normalize v1, v2 Build quat

More stable when v1, v2 near parallel

In most cases that will work, but there are some problems when v1 and v2 are pointing pretty much the same direction. Stan Melax has a great solution for this, which is to normalize v1 and v2, compute these quantities r and s, and then plug into the quaternion as follows.

Multiplication
More

complex (har) than complex Take q0 = (w0, v0) q1 = (w1, v1)

Non-commutative:

So that provides a way to create a quaternion. Suppose we want to concatenate them. As with matrices and complex numbers, multiplication does the trick. However, in this case the multiplication operator is a little more complicated. Still, its all simple vector math, so it isnt too bad. Note again that due to the cross product this is non-commutative.

Identity and Inverse


Identity

quaternion is (1, 0, 0, 0)

applies no rotation remains at reference orientation

q-1

is inverse
q . q-1 gives identity quaternion

Inverse

is same axis but opposite angle

Computing Inverse
(w,

v)-1 = ( cos(/2), sin(/2) . ^ r)

Only

true if q is unit i.e. r ^is a unit vector

Vector Rotation
Have

vector p, quaternion q Treat p as quaternion (0, p) Rotation of p by q is q p q-1 Vector p and unit quat (w, v) boils down to

Possible to show that this formula is the same as the rotation formula for axis and angle.

Vector Rotation (contd)


Why does q p q-1 work? Similar to complex w/half angle:


first multiply rotates halfway and into 4th dimension second multiply rotates rest of the way, back into 3rd

See references for more details

Vector Rotation (contd)


Can

concatenate rotation

q1 (q0 p q0-1) q1-1 = (q1 q0) p (q1 q0)-1


Note

multiplication order: right-to-left

Quaternion Interpolation

As with complex numbers

Lerp
qt = (1 " t )q0 + tq1

Slerp
qt = sin(1 " t )# sin t# q0 + q sin # sin # 1

Quaternion Interpolation

Technique used depends on data Lerp generally good enough for motion capture (lots of samples)

Need to normalize afterwards Blows method for simple interpolation (Also need to normalize)
Demo

Slerp only needed if data is sparse


These days, Blow says just use lerp. YMMV.

Interpolation Caveat
and q rotate vector to same place But not quite the same rotation q has axis r, with angle 2- Causes problems with interpolation (different hemispheres)
q r w 2 -r v

This is due to the half-angle form of quaternions.

Interpolation Caveat

How to test? If dot product of two interpolating quats is < 0, takes long route around sphere Solution, negate one quat, then interpolate Preprocess to save time

As mentioned

Operation Wrap-Up
Multiply to concatenate rotations Addition only for interpolation (dont forget to normalize) Be careful with scale

Quick rotation assumes unit quat Dont do (0.5 q) p Use lerp or slerp with identity quaternion

Summary

Talked about orientation Formats good for internal storage


Angle Matrices (2D or 3D) Quaternions Euler angles Axis-angle

Formats good for UI


Complex numbers not really used

References

Shoemake, Ken, Animation Rotation with Quaternion Curves, SIGGRAPH 85, pp. 245-254. Shoemake, Ken, Quaternion Calculus for Animation, SIGGRAPH Course Notes, Math for SIGGRAPH, 1989. Hanson, Andrew J., Visualizing Quaternions, Morgan Kaufman, 2006. Blow, Jonathan, Hacking Quaternions, Game Developer, March 2002. Busser, Thomas, PolySlerp: A fast and accurate polynomial approximation of spherical linear interpolation (Slerp), Game Developer, February 2004. Van Verth, Jim, Vector Units and Quaternions, GDC 2002. http://www.essentialmath.com

Potrebbero piacerti anche