Transcript Document

Skeletons
CSE169: Computer Animation
Instructor: Steve Rotenberg
UCSD, Winter 2004
Linear Algebra Review
Coordinate Systems

Right handed coordinate system
y
x
z
Vector Arithmetic

a  ax
ay
az


a b a b 
a  b  a  b a  b a  b 
 a   a  a  a 
s * a  s * a s * a s * a 
a  b  a x  bx
x
x
x
y
y
z
z
y
y
z
z
y
x
z
y
z
Vector Magnitude

The magnitude (length) of a vector is:
v  v v v
2
x

2
y
2
z
Unit vector (magnitude=1.0)
v
v
Dot Product
a  b  a xbx  a y by  a z bz   ai bi
a  b  a b cos 
Example: Angle Between Vectors

How do you find the angle θ between
vectors A and B?
b
θ=?
a
Example: Angle Between Vectors
 a b 

  cos 

a
b


1
b
θ
a
Dot Products with Unit Vectors
0 < a·b < 1
a·b = 0
a·b = 1
b
-1 < a·b < 0
a·b = -1
θ
a
a  b  1.0
a  b  cos 
Dot Products with Non-Unit Vectors

If a and b are arbitrary (non-unit) vectors,
then the following are still true:



If θ < 90º then a·b > 0
If θ = 90º then a·b = 0
If θ > 90º then a·b < 0
Dot Products with One Unit Vector

If |u|=1.0 then a·u is the length of the projection
of a onto u
a
u
a·u
*Example: Distance to Plane
Cross Product
i
j
k
a  b  ax
bx
ay
by
az
bz

a  b  a y bz  a z by
a z bx  a x bz
a x by  a y bx

Properties of the Cross Product
a  b  a b sin 
a  b  area of parallelogram ab
a  b is perpendicular to both a and b,
in the direction defined by the right
hand rule
Example: Area of a Triangle

Find the area of the triangle defined by 3D
points a, b, and c
c
b
a
Example: Area of a Triangle
1
area  b  a  c  a 
2
c
c-a
b
a
b-a
Example: Alignment to Target

An object is at position p with a unit length
heading of h. We want to rotate it so that the
heading is facing some target t. Find a unit axis
a and an angle θ to rotate around.
•
•
p
h
t
Example: Alignment to Target
h  t  p 
a
h  t  p 
 h  t  p  

  cos 



t

p


• t
1
a
t-p
θ
•
p
h
Matrices


Computer graphics apps commonly use 4x4
homogeneous matrices
A rigid 4x4 matrix transformation looks like this:
ax
b
x

M
 cx

d x

ay
by
az
bz
cy
dy
cz
dz
0
0
0

1
b
y
c
d
a
x
z
Where a, b, & c are orthogonal unit length vectors
representing orientation, and d is a vector representing
position
Matrices


The right hand column can cause a
projection, which we won’t use in
character animation, so we leave it as
0,0,0,1
Some books store their matrices in a
transposed form. This is fine as long as
you remember that:
A·B = BT·AT
Transformations

To transform a vector v by matrix M:
v’=v·M

If we want to apply several transformations, we can just
multiply by several matrices:
v’=(((v·M1)·M2)·M3)·M4…

Or we can concatenate the transformations into a single
matrix:
Mtotal=M1·M2·M3·M4…
v’=v·Mtotal
Trigonometry
cos2θ + sin2θ = 1
1.0
θ
cos θ
sin θ
Laws of Sines and Cosines


α
Law of Sines:
a
b
c


sin  sin  sin 
Law of Cosines:
c  a  b  2ab cos 
2
2
2
b
γ
c
β
a
Skeletons
Kinematics




Kinematics: The analysis of motion independent of
physical forces. Kinematics deals with position, velocity,
acceleration, and their rotational counterparts,
orientation, angular velocity, and angular acceleration.
Forward Kinematics: The process of computing world
space geometric data from DOFs
Inverse Kinematics: The process of computing a set of
DOFs that causes some world space goal to be met
(I.e., place the hand on the door knob…)
Note: Kinematics is an entire branch of mathematics and
there are several other aspects of kinematics that don’t
fall into the ‘forward’ or ‘inverse’ description
Skeletons



Skeleton: A pose-able framework of joints
arranged in a tree structure. The skeleton is
used as an invisible armature to manipulate the
skin and other geometric data of the character
Joint: A joint allows relative movement within the
skeleton. Joints are essentially 4x4 matrix
transformations. Joints can be rotational,
translational, or some non-realistic types as well
Bone: Bone is really just a synonym for joint for
the most part. For example, one might refer to
the shoulder joint or upper arm bone (humerus)
and mean the same thing
DOFs





Degree of Freedom (DOF): A variable φ
describing a particular axis or dimension of
movement within a joint
Joints typically have around 1-6 DOFs (φ1…φN)
Changing the DOF values over time results in
the animation of the skeleton
In later weeks, we will extend the concept of a
DOF to be any animatable parameter within the
character rig
Note: in a mathematical sense, a free rigid body
has 6 DOFs: 3 for position and 3 for rotation
Example Joint Hierarchy
Root
Torso
Pelvis
Neck
ShoulderL
ShoulderR
HipL
HipR
Head
ElbowL
ElbowR
KneeL
KneeR
WristL
WristR
AnkleL
AnkleR
Joints

Core Joint Data




DOFs (N floats)
Local matrix: L
World matrix: W
Additional Data




Joint offset vector: r
DOF limits (min & max value per DOF)
Type-specific data (rotation/translation axes,
constants…)
Tree data (pointers to children, siblings, parent…)
Skeleton Posing Process
1.
Specify all DOF values for the skeleton (done by higher
level animation system)
2.
Recursively traverse through the hierarchy starting at
the root and use forward kinematics to compute the
world matrices (done by skeleton system)
3.
Use world matrices to deform skin & render (done by
skin system)
Note: the matrices can also be used for other things such
as collision detection, FX, etc.
Forward Kinematics

In the recursive tree traversal, each joint first
computes its local matrix L based on the values
of its DOFs and some formula representative of
the joint type:
Local matrix L = Ljoint(φ1,φ2,…,φN)

Then, world matrix W is computed by
concatenating L with the world matrix of the
parent joint
World matrix W = L · Wparent
Joint Offsets

It is convenient to have a 3D offset vector
r for every joint which represents its pivot
point relative to its parent’s matrix
L offset
1
0

0

rx
0
1
0
0
0
ry
1
rz
0

0
0

1
DOF Limits


It is nice to be able to limit a DOF to some
range (for example, the elbow could be
limited from 0º to 150º)
Usually, in a realistic character, all DOFs
will be limited except the ones controlling
the root
Skeleton Rigging



Setting up the skeleton is an important and early
part of the rigging process
Sometimes, character skeletons are built before
the skin, while other times, it is the opposite
To set up a skeleton, an artist uses an
interactive tool to:





Construct the tree
Place joint offsets
Configure joint types
Specify joint limits
Possibly more…
Poses


Once the skeleton is set up, one can then adjust each of
the DOFs to specify the pose of the skeleton
We can define a pose Φ more formally as a vector of N
numbers that maps to a set of DOFs in the skeleton
Φ = [φ1 φ2 … φN]



A pose is a convenient unit that can be manipulated by a
higher level animation system and then handed down to
the skeleton
Usually, each joint will have around 1-6 DOFs, but an
entire character might have 100+ DOFs in the skeleton
Keep in mind that DOFs can be also used for things
other than joints, as we will learn later…
Joint Types
Joint Types

Rotational



Hinge: 1-DOF
Universal: 2-DOF
Ball & Socket: 3-DOF



Euler Angles
Quaternions
Translational



Prismatic: 1-DOF
Translational: 3-DOF
(or any number)
Compound





Non-Rigid




Free
Screw
Constraint
Etc.
Scale
Shear
Etc.
Design your own...
Hinge Joints (1-DOF Rotational)

Rotation around the x-axis:
1
0
L Rx  x   
0

rx
0
cos  x
0
sin  x
 sin  x
cos  x
ry
rz
0
0
0

1
Hinge Joints (1-DOF Rotational)

Rotation around the y-axis:
cos  y
 0
L Ry  y   
 sin  y

 rx
0
1
 sin  y
0
0
cos  y
ry
rz
0
0
0

1
Hinge Joints (1-DOF Rotational)

Rotation around the z-axis:
 cos  z
 sin 
z

L Rz  z  
 0

 rx
sin  z
cos  z
0
0
0
1
ry
rz
0
0
0

1
Hinge Joints (1-DOF Rotational)

Rotation around an arbitrary axis a:
L Ra   
 a x2  c (1  a x2 )

a x a y (1  c )  a z s
a x a z (1  c )  a y s

rx

a x a y (1  c )  a z s
a y2  c (1  a y2 )
a y a z (1  c )  a x s
ry
a x a z (1  c )  a y s
a y a z (1  c )  a x s
a z2  c (1  a z2 )
rz
0

0
0

1
Universal Joints (2-DOF)

For a 2-DOF joint that first rotates around
x and then around y:
 cy
s s
x y

L Rxy  x , y  
c x s y

 rx

0
cx
 sy
sxcy
 sx
cxc y
ry
rz
0
0
0

1
Different matrices can be formed for
different axis combinations
Ball & Socket (3-DOF)

For a 3-DOF joint that first rotates around
x, y, then z:
c y cz

s s c  c s
x y z
x z

L Rxyz  x , y , z  
c x s y c z  s x s z

rx


cy sz
sx s y sz  cx cz
 sy
sxcy
cx s y sz  sx cz
ry
cx c y
rz
Different matrices can be formed for
different axis combinations
0
0
0

1
Quaternions

q  qx
qy
qz
qw

q  q x2  q y2  q z2  q w2  1


q  a x sin
2

a y sin
 1  2q y2  2q z2

2q x q y 2q w q z

L Q q  
2q x q z 2q w q y

rx


2
a z sin

2

cos 
2
2q x q y 2q w q z
2q x q z 2q w q y
1  2q x2  2q z2
2q y q z 2q w q x
ry
2q y q z 2q w q x
1  2q x2  2q y2
rz
0

0
0

1
Prismatic Joints (1-DOF Translation)

1-DOF translation along an arbitrary axis a:


L Ta t   


rx
1
0
0
 t  ax
0
1
0
0
0
ry  t  a y
1
rz  t  a z
0

0
0

1
Translational Joints (3-DOF)

For a more general 3-DOF translation:


L Txyz t   


rx
1
0
0
0
1
0
0
0
1
ry  t y
rz  t z
 tx
0
0
0

1
Other Joints

Compound





Free
Screw
Constraint
Etc.
Non-Rigid



Scale (1 axis, 3 axis, volume preserving…)
Shear
Etc.
Programming Project #1: Skeleton
Software Architecture






Object oriented
Make objects for things that should be
objects
Avoid global data & functions
Encapsulate information
Provide useful interfaces
Put different objects in different files
Sample Code



Some sample code is provided on the course
web page listed as ‘project0’
It is an object oriented demo of a spinning cube
Classes:






Vector3
Matrix34
Tokenizer
Camera
SpinningCube
Tester
Project 1 Assignment




Load a skeleton from a ‘.skel’ file and
display it in 3D
All joints in the skeleton should be 3-DOF
rotational joints
Compute world matrices yourself and use
glLoadMatrixf()
Due: Monday, Jan 19, 11:59pm
Sample Skel File
balljoint root {
[data for root]
balljoint head {
[data for head]
[children of head]
}
balljoint leg_l {
[data for leg]
[children of leg]
}
[more children of root]
}
Skel File Data Tokens
offset
boxmin
boxmax
rotxlimit
rotylimit
rotzlimit
pose
balljoint
xyz
xyz
xyz
min max
min max
min max
xyz
name { }
(joint offset vector)
(min corner of box to draw)
(max corner of box to draw)
(x rotation DOF limits)
(y rotation DOF limits)
(z rotation DOF limits)
(values to pose DOFs)
(child joint)
Possible Object Breakdown

One should consider making objects
(classes) for the following:



DOF
Joint
Skeleton
Common Routines

Many classes will need functions for some
or all of the following:






Constructor / destructor
Initialize
Load
Update (move things, pose, animate…)
Draw
Reset
What is a DOF?

Data



Value
Min, max
Functions



SetValue() (can clamp value at the time of
setting)
GetValue()
SetMinMax()…
What is a Joint?

Data




Functions





Local & World matrices
Array of DOFs
Tree data (child/sibling/parent pointers, etc.)
Update() (recursively generate local matrix & concatenate)
Load()
AddChild()
Draw()
Note: One could also make a Joint base class and
derive various specific joint types. In this case, it would
be a good idea to make a virtual function for
MakeLocalMatrix() that the base traversal routine calls
What is a Skeleton?

Data


Joint tree (might only need a pointer to the
root joint)
Functions



Load
Update (traverses tree & computes joint
matrices)
Draw
Tree Data Structures


The skeleton requires only the most basic N-tree
data structure
The main things the tree needs:



An easy way to add a new child to a node
A way for each node to iterate through its children
There are several options:



Use STL
Implement a tree data structure
Store sibling & first child pointers in the Joint itself
*Tree Data Structure
*Sibling/Child Tree
Sibling & Child Pointers
class Joint {
Joint *Sibling,*Child;
… // other data
public:
bool Load(Tokenizer &t);
bool AddChild(Joint &c);
void Update(Matrix &parent);
void Draw();
… // other functions
};
AddChild()
bool Joint::AddChild(Joint &c) {
c.Sibling=Child;
Child=&c;
return true;
}



Ideally, it should do some error checking as well (such
as verifying that c isn’t already a child of another node)
Note that Child & Sibling must be set to 0 initially in the
constructor!
Also, notice that this routine adds c as the first child on
the list (essentially adding them in reverse order)
Update & Draw
void Joint::Update(Matrix &parent) {
… // Compute LocalMatrix
… // Compute WorldMatrix
if(Sibling) Sibling->Update(parent);
if(Child) Child->Update(WorldMatrix);
}
void Joint::Draw() {
.. // Do some OpenGL
if(Sibling) Sibling->Draw();
if(Child) Child->Draw();
}
Load
bool Skeleton::Load(const char *file) {
Tokenizer token;
token.Open(file,"skel"));
token.FindToken("balljoint"));
// Parse tree
Root=new Joint;
Root->Load(token);
// Finish
token.Close();
return true;
}
bool Joint::Load(Tokenizer &t) {
token.FindToken("{"));
while(1) {
char temp[256];
token.GetToken(temp);
if(strcmp(temp,"offset")==0) {
Offset.x=token.GetFloat();
Offset.y=token.GetFloat();
Offset.z=token.GetFloat();
}
else // Check for other tokens
else if(strcmp(temp,"balljoint")==0) {
Joint *jnt=new Joint;
jnt->Load(token);
AddChild(*jnt);
}
else if(strcmp(temp,"}")==0) return true;
else token.SkipLine(); // Unrecognized token
}
}
Notes About Sibling/Child Trees




Hard to implement a tree with less code
A bit on the ‘quick and dirty’ side though
Not abstracting the tree structure away
means that code will be duplicated if other
classes need to be in their own trees
The double recursion in the traversal
routines can tend to lead to unnecessarily
deep runtime stacks (stack overflows)