advanced programming for 3d applications ce00383-3
DESCRIPTION
Advanced Programming for 3D Applications CE00383-3. Data Structures for Human Motion Lecture 5. Bob Hobbs Staffordshire university. Example Joint Hierarchy. Skeleton Posing Process. Specify all DOF values for the skeleton - PowerPoint PPT PresentationTRANSCRIPT
Advanced Programming for 3DAdvanced Programming for 3DApplicationsApplicationsCE00383-3CE00383-3
Bob HobbsStaffordshire university
Data Structures for Human Motion
Lecture 5
22
Example Joint HierarchyExample Joint Hierarchy
Root
Torso
Neck
Pelvis
HipL HipR
Head ElbowL
WristL
ElbowR
WristR
KneeL
AnkleL
KneeR
AnkleR
ShoulderL ShoulderR
33
Skeleton Posing ProcessSkeleton Posing Process
1.1. Specify all DOF values for the skeleton Specify all DOF values for the skeleton
2.2. Recursively traverse through the hierarchy Recursively traverse through the hierarchy starting at the root and use forward kinematics starting at the root and use forward kinematics to compute the world matricesto compute the world matrices
3.3. Use world matrices to deform skin & renderUse world matrices to deform skin & render
Note: the matrices can also be used for other things Note: the matrices can also be used for other things such as collision detection, FX, etc.such as collision detection, FX, etc.
44
Joint OffsetsJoint Offsets
• It is convenient to have a 3D offset It is convenient to have a 3D offset vector vector rr for every joint which for every joint which represents its pivot point relative to represents its pivot point relative to its parent’s matrixits parent’s matrix
1
0100
0010
0001
zyx
offset
rrr
L
55
DOF LimitsDOF Limits
• It is nice to be able to limit a DOF to It is nice to be able to limit a DOF to some range (for example, the elbow some range (for example, the elbow could be limited from 0could be limited from 0ºº to 150 to 150ºº))
• Usually, in a realistic character, all Usually, in a realistic character, all DOFs will be limited except the ones DOFs will be limited except the ones controlling the rootcontrolling the root
66
Skeleton RiggingSkeleton Rigging• Setting up the skeleton is an important and Setting up the skeleton is an important and
early part of the rigging processearly part of the rigging process• Sometimes, character skeletons are built before Sometimes, character skeletons are built before
the skin, while other times, it is the oppositethe skin, while other times, it is the opposite• To set up a skeleton, an artist uses an To set up a skeleton, an artist uses an
interactive tool to:interactive tool to:– Construct the treeConstruct the tree– Place joint offsetsPlace joint offsets– Configure joint typesConfigure joint types– Specify joint limitsSpecify joint limits– Possibly more…Possibly more…
77
PosesPoses
• Once the skeleton is set up, one can then adjust Once the skeleton is set up, one can then adjust each of the DOFs to specify the pose of the skeletoneach of the DOFs to specify the pose of the skeleton
• We can define a pose We can define a pose ΦΦ more formally as a vector more formally as a vector of N numbers that maps to a set of DOFs in the of N numbers that maps to a set of DOFs in the skeletonskeleton
Φ = [φΦ = [φ11 φ φ22 … φ … φNN]]
• A pose is a convenient unit that can be manipulated A pose is a convenient unit that can be manipulated by a higher level animation system and then by a higher level animation system and then handed down to the skeletonhanded down to the skeleton
• Usually, each joint will have around 1-6 DOFs, but Usually, each joint will have around 1-6 DOFs, but an entire character might have 100+ DOFs in the an entire character might have 100+ DOFs in the skeletonskeleton
88
Hinge Joints (1-DOF Hinge Joints (1-DOF Rotational)Rotational)
1
0cossin0
0sincos0
0001
zyx
xx
xxxRx
rrr
L
• Rotation around the x-axis:Rotation around the x-axis:
99
Hinge Joints (1-DOF Hinge Joints (1-DOF Rotational)Rotational)
1
0cos0sin
0010
0sin0cos
zyx
yy
yy
yRy
rrr
L
• Rotation around the y-axis:Rotation around the y-axis:
1010
Hinge Joints (1-DOF Hinge Joints (1-DOF Rotational)Rotational)
1
0100
00cossin
00sincos
zyx
zz
zz
zRz
rrr
L
• Rotation around the z-axis:Rotation around the z-axis:
1111
Hinge Joints (1-DOF Hinge Joints (1-DOF Rotational)Rotational)
• Rotation around an arbitrary axis Rotation around an arbitrary axis aa::
1
0)1()1()1(
0)1()1()1(
0)1()1()1(
22
22
22
zyx
zzxzyyzx
xzyyyzyx
yzxzyxxx
Ra
rrr
acasacaasacaa
sacaaacasacaa
sacaasacaaaca
L
1212
Universal Joints (2-DOF)Universal Joints (2-DOF)
• For a 2-DOF joint that first rotates around x For a 2-DOF joint that first rotates around x and then around y:and then around y:
• Different matrices can be formed for different Different matrices can be formed for different axis combinationsaxis combinations
1
0
0
00
,
zyx
yxxyx
yxxyx
yy
yxRxy
rrr
ccssc
cscss
sc
L
1313
Ball & Socket (3-DOF)Ball & Socket (3-DOF)
• For a 3-DOF joint that first rotates around x, y, For a 3-DOF joint that first rotates around x, y, then z:then z:
• Different matrices can be formed for different Different matrices can be formed for different axis combinationsaxis combinations
1
0
0
0
,,
zyx
yxzxzyxzxzyx
yxzxzyxzxzyx
yzyzy
zyxRxyz
rrr
cccssscsscsc
csccssssccss
ssccc
L
1414
Prismatic Joints (1-DOF Prismatic Joints (1-DOF Translation)Translation)• 1-DOF translation along an arbitrary axis 1-DOF translation along an arbitrary axis
aa::
1
0100
0010
0001
zzyyxx
Ta
atratratr
tL
1515
Translational Joints (3-DOF)Translational Joints (3-DOF)
• For a more general 3-DOF For a more general 3-DOF translation:translation:
1
0100
0010
0001
zzyyxx
Txyz
trtrtr
tL
1616
Software ArchitectureSoftware Architecture
• Object orientedObject oriented
• Make objects for things that should Make objects for things that should be objectsbe objects
• Avoid global data & functionsAvoid global data & functions
• Encapsulate informationEncapsulate information
• Provide useful interfacesProvide useful interfaces
• Put different objects in different filesPut different objects in different files
1717
Sample CodeSample Code
• Classes Required:Classes Required:– Vector3Vector3– Matrix34Matrix34– TokenizerTokenizer– CameraCamera– SpinningCubeSpinningCube– TesterTester
1818
Sample Skeleton FileSample Skeleton File
balljoint root {balljoint root {[data for root][data for root]balljoint head {balljoint head {
[data for head][data for head][children of head][children of head]
}}balljoint leg_l {balljoint leg_l {
[data for leg][data for leg][children of leg][children of leg]
}}[more children of root][more children of root]
}}
1919
Skeleton File Data TokensSkeleton File Data Tokens
offsetoffset x y zx y z (joint offset vector)(joint offset vector)
boxminboxmin x y zx y z (min corner of box to draw)(min corner of box to draw)
boxmaxboxmax x y zx y z (max corner of box to draw)(max corner of box to draw)
rotxlimitrotxlimit min maxmin max (x rotation DOF limits)(x rotation DOF limits)
rotylimitrotylimit min maxmin max (y rotation DOF limits)(y rotation DOF limits)
rotzlimitrotzlimit min maxmin max (z rotation DOF limits)(z rotation DOF limits)
posepose x y zx y z (values to pose DOFs)(values to pose DOFs)
balljoint balljoint name { }name { } (child joint)(child joint)
2020
Possible Object BreakdownPossible Object Breakdown
• One should consider making objects One should consider making objects (classes) for the following:(classes) for the following:– DOFDOF– JointJoint– SkeletonSkeleton
2121
Common RoutinesCommon Routines
• Many classes will need functions for Many classes will need functions for some or all of the following:some or all of the following:– Constructor / destructorConstructor / destructor– InitializeInitialize– LoadLoad– Update (move things, pose, animate…)Update (move things, pose, animate…)– DrawDraw– ResetReset
2222
What is a DOF?What is a DOF?
• DataData– ValueValue– Min, maxMin, max
• FunctionsFunctions– SetValue() (can clamp value at the time SetValue() (can clamp value at the time
of setting)of setting)– GetValue()GetValue()– SetMinMax()…SetMinMax()…
2323
What is a Joint?What is a Joint?
• DataData– Local & World matricesLocal & World matrices– Array of DOFsArray of DOFs– Tree data (child/sibling/parent pointers, etc.)Tree data (child/sibling/parent pointers, etc.)
• FunctionsFunctions– Update() (recursively generate local matrix & concatenate)Update() (recursively generate local matrix & concatenate)– Load()Load()– AddChild()AddChild()– Draw()Draw()
• Note: One could also make a Joint base class and derive Note: One could also make a Joint base class and derive various specific joint types. In this case, it would be a various specific joint types. In this case, it would be a good idea to make a virtual function for good idea to make a virtual function for MakeLocalMatrix() that the base traversal routine callsMakeLocalMatrix() that the base traversal routine calls
2424
What is a Skeleton?What is a Skeleton?
• DataData– Joint tree (might only need a pointer to Joint tree (might only need a pointer to
the root joint)the root joint)
• FunctionsFunctions– LoadLoad– Update (traverses tree & computes joint Update (traverses tree & computes joint
matrices)matrices)– DrawDraw
2525
Tree Data StructuresTree Data Structures
• The skeleton requires only the most basic N-The skeleton requires only the most basic N-tree data structuretree data structure
• The main thing the tree needs is an easy The main thing the tree needs is an easy way to perform a depth-first traversalway to perform a depth-first traversal
• There are several options:There are several options:– Use STLUse STL– Implement a tree data structureImplement a tree data structure– Store sibling & first child pointers in the Joint Store sibling & first child pointers in the Joint
itselfitself– Store a linearized tree as an array in the skeletonStore a linearized tree as an array in the skeleton
2626
Update & DrawUpdate & Draw
void Joint::Update(Matrix &parent) {void Joint::Update(Matrix &parent) {… … // Compute LocalMatrix// Compute LocalMatrix… … // Compute WorldMatrix// Compute WorldMatrix… … // Recursively call Update() on children// Recursively call Update() on children
}}
void Joint::Draw() {void Joint::Draw() {.. // Do some OpenGL.. // Do some OpenGL.. // Recursively call Draw() on children.. // Recursively call Draw() on children
}}
2727
LoadLoad
bool Skeleton::Load(const char *file) {bool Skeleton::Load(const char *file) {Tokenizer token;Tokenizer token;token.Open(file,"skel"));token.Open(file,"skel"));token.FindToken("balljoint"));token.FindToken("balljoint"));
// Parse tree// Parse treeRoot=new Joint;Root=new Joint;Root->Load(token);Root->Load(token);
// Finish// Finishtoken.Close();token.Close();return true;return true;
}}
2828
bool Joint::Load(Tokenizer &t) {bool Joint::Load(Tokenizer &t) {token.FindToken("{"));token.FindToken("{"));while(1) {while(1) {
char temp[256];char temp[256];token.GetToken(temp);token.GetToken(temp);if(strcmp(temp,"offset")==0) {if(strcmp(temp,"offset")==0) {
Offset.x=token.GetFloat();Offset.x=token.GetFloat();Offset.y=token.GetFloat();Offset.y=token.GetFloat();Offset.z=token.GetFloat();Offset.z=token.GetFloat();
}}else // Check for other tokenselse // Check for other tokenselse if(strcmp(temp,"balljoint")==0) {else if(strcmp(temp,"balljoint")==0) {
Joint *jnt=new Joint;Joint *jnt=new Joint;jnt->Load(token);jnt->Load(token);AddChild(*jnt);AddChild(*jnt);
}}else if(strcmp(temp,"}")==0) return true;else if(strcmp(temp,"}")==0) return true;else token.SkipLine();else token.SkipLine(); // Unrecognized token// Unrecognized token
}}}}