|
Features

Animation With Cg
Vertex
Skinning
Another
approach to animating characters is vertex skinning. Many 3D modeling
packages author 3D content suitable for vertex skinning. The technique
is also known as matrix palette blending.
The
Theory of Vertex Skinning
Rather
than have key frames for each pose of a character, vertex skinning maintains
a single default pose and a large set of matrices that appropriately rotate
and translate various subregions of the default pose's polygonal mesh.
For reasons that will become apparent, these various matrix transforms
are often called "bones."
One
or more of these matrices control each vertex in the default pose's polygonal
mesh. Each matrix is assigned a weighting factor (from 0 to 100 percent),
which indicates how much that matrix affects each vertex. Only a small
number of matrices usually control each vertex, meaning that only these
few matrices have positive and significant weighting factors for a given
vertex. We call this small set of matrices the bone set for each
vertex. We assume that the weighting factors for all the matrices in a
vertex's bone set always sum to 100 percent.
When
rendering this type of model, you first transform every vertex by each
matrix in the vertex's bone set, then weight the results of each matrix
transform according to the matrix's corresponding weighting factor, and
finally sum the results. This new position is the skinned vertex position.
When
all the matrices are identity matrices (no rotation, no translation),
the mesh is in the default pose. 3D artists often pick a default pose
in which the character is standing and facing forward, with legs apart
and arms outstretched.
Constructing
Poses from Matrices
By
controlling the matrices, you can create novel poses. For example, a vertex
on a character's forearm close to the elbow might use 67 percent of the
forearm matrix, 21 percent of the elbow matrix, and 12 percent of the
upper arm matrix. The animator who creates a model for vertex skinning
must appropriately localize each matrix so that, for example, the matrix
that controls the left shoulder has no effect on vertices near the ankle.
Often, the number of matrices affecting any given vertex is limited to
no more than four. For the 3D artist, once all the weights and matrices
are assigned to the model's default pose, constructing a new pose is a
matter of manipulating the matrices appropriately, rather than attempting
to position each individual vertex. Posing and animating the model is
much simpler when it is authored for vertex skinning.
For
a character model, the most significant matrices represent the way rigid
bones in the character's body move and rotate; hence, the vertex-skinning
matrices are called bones. The vertices represent points on the
skin. Vertex skinning simulates how bones, represented as matrices, tug
and reposition various points, represented as vertices, on the character's
skin.
Lighting
For
correct lighting, you can compute the same sort of transformed and weighted
average used for positions, except that you transform normals by the inverse
transpose of each matrix rather than by the matrix itself. Weighted normals
may no longer be unit length, so normalization is required.
Assuming
that the bone matrices are merely rotations and translations simplifies
the transformation of the normals for lighting, because the inverse transpose
of a matrix without scaling or projection is the matrix itself.
Storage
Requirements Compared with Key Frames
With
the key frame approach, every pose requires a distinct set of vertex positions
and normals. This becomes unwieldy if huge numbers of poses are required.
However,
with vertex skinning, each pose requires just the default pose-shared
by all poses-and the matrix values for the given pose. There are generally
substantially fewer matrices per character than vertices, so representing
a pose as a set of bone matrices is more compact than representing the
pose with a key frame. With vertex skinning, you can also create novel
poses dynamically, either by blending existing bone matrices from different
poses or by controlling matrices directly. For example, if you know what
matrices control an arm, you can wave the arm by controlling those matrices.
In
addition to requiring the matrices for each pose, the model's default
pose needs each vertex to have a default position, a default normal, some
number of matrix indices to identify which subset of matrices control
the vertex, and the same number of weighting factors, corresponding to
each respective matrix.
This
data for the default pose is constant for all other poses. Generating
a new pose requires only new matrices, not any changes to the default
pose data. If the GPU can perform all the vertex-skinning computations,
this means that the CPU needs to update only the bone matrices for each
new pose, but not otherwise manipulate or access the default pose data.
Vertex
skinning is quite amenable to storing and replaying motion-capture sequences.
You can represent each motion-capture frame as a set of bone matrices
that you can then apply to different models that share the same default
pose and matrix associations. Inverse kinematics solvers can also generate
bone matrices procedurally. An inverse kinematics solver attempts to find
an incremental sequence of bone matrices that transition from one given
pose to another given pose in a realistic, natural manner.
Vertex
Skinning in a Vertex Program
The
C6E5v_skin4m vertex program
in Example 6-5 implements vertex skinning, assuming that no more than
four bone matrices affect each vertex (a common assumption).
An
array of 24 bone matrices, each a 3x4 matrix, represents each pose. The
entire array is a uniform parameter to the program. The program assumes
that each bone matrix consists of a translation and a rotation (no scaling
or projection).
The
per-vertex matrixIndex
input vector provides a set of four bone-matrix indices for accessing
the boneMatrix array. The
per-vertex weight input
vector provides the four weighting factors for each respective bone matrix.
The program assumes that the weighting factors for each vertex sum to
100 percent.
For
performance reasons, the program treats boneMatrix
as an array of float4
vectors rather than an array of float3x4
matrices. The matrixIndex
array contains floating-point values instead of integers, and so the addressing
of a single array of vectors is more efficient than accessing an array
of matrices. The implication of this is that the indices in the matrixIndex
vector should be three times the actual matrix index. So, the program
assumes 0 is the first matrix in the array, 3 is the second matrix, and
so on. The indices are fixed for each vertex, so you improve performance
by moving this "multiply by 3" outside the vertex program.
A
for loop, looping four
times, transforms the default pose position and normal by each bone matrix.
Each result is weighted and summed.
The
program computes both the weighted position and normal for the pose. The
same computeLighting internal
function from Example 6-4 computes per-vertex object-space lighting with
the weighted position and normal.
Although
this example is rather limited, you could generalize it to handle more
bone matrices, general bone matrices (for example, allowing scaling),
and matrices influencing each vertex-and to compute a better lighting
model.
|
|
void C6E5v_skin4m(float3 position : POSITION,
float3
normal : NORMAL,
float2
texCoord : TEXCOORD0,
float4
weight : TEXCOORD1,
float4
matrixIndex : TEXCOORD2,
out float4
oPosition : POSITION,
out float2
oTexCoord : TEXCOORD0,
out float4
color : COLOR,
uniform Light light,
uniform float4 boneMatrix[72],
// 24 matrices
uniform float4x4 modelViewProj)
{
float3 netPosition = 0, netNormal = 0;
for (int i = 0; i < 4; i++) {
float index = matrixIndex[i];
float3x4 model = float3x4(boneMatrix[index
+ 0],
boneMatrix[index
+ 1],
boneMatrix[index
+ 2]);
float3
bonePosition = mul(model, float4(position, 1));
// Assume no scaling in matrix, just rotate &
translate
float3x3 rotate = float3x3(model[0].xyz,
model[1].xyz,
model[2].xyz);
float3
boneNormal = mul(rotate, normal);
netPosition += weight[i] * bonePosition;
netNormal += weight[i] * boneNormal;
}
netNormal = normalize(netNormal);
oPosition = mul(modelViewProj, float4(netPosition,
1));
oTexCoord = texCoord;
color = computeLighting(light, netPosition, netNormal);
}
|
 |
 |
 |
Example 6-5. The C6E5v_skin4m
Vertex Program
|
Further
Reading
Cg
builds on a host of concepts in computer language design, computer hardware
design, and computer graphics. Doing justice to all these contributions
in the context of this tutorial is not always practical. What we attempt
in the "Further Reading" section is to offer you pointers to
learn more about the contributions that underlie the topics in each chapter.
There
are plenty of books on C. The C Programming Language, Third Edition
(Prentice Hall, 2000), by Brian Kernighan and Dennis Ritchie, is a classic;
the authors invented the C language. Cg includes concepts from both C
and C++. There now may actually be more books about C++ than about C.
The classic C++ book is The C++ Programming Language, Third Edition
(Addison-Wesley, 2000), by Bjarne Stroustrup, who invented the language.
To
learn more about the RenderMan Shading Language, read The RenderMan
Companion: A Programmer's Guide to Realistic Computer Graphics (Addison-Wesley,
1989), by Steve Upstill. Pat Hanrahan and Jim Lawson published a SIGGRAPH
paper about RenderMan called "A Language for Shading and Lighting
Calculations" (ACM Press) in 1990.
Robert
Cook's 1984 SIGGRAPH paper titled "Shade Trees" (ACM Press)
motivated the development of RenderMan.
The
development of programmable graphics hardware and its associated languages
has been an active and fruitful research area for almost a decade. Anselmo
Lastra, Steven Molnar, Marc Olano, and Yulan Wang at UNC published an
early research paper in 1995 titled "Real-Time Programmable Shading"
(ACM Press). Researchers at UNC also published several papers about their
programmable PixelFlow graphics architecture. Marc Olano and Anselmo Lastra
published a SIGGRAPH paper titled "A Shading Language on Graphics
Hardware: The PixelFlow Shading System" (ACM Press) in 1998.
Kekoa
Proudfoot, Bill Mark, Svetoslav Tzvetkov, and Pat Hanrahan published a
SIGGRAPH paper in 2001 titled "A Real-Time Procedural Shading System
for Programmable Graphics Hardware" (ACM Press) that describes a
GPU-oriented shading language developed at Stanford.
Real-Time
Rendering, Second Edition (A. K. Peters, 2002), written by Eric Haines
and Tomas Akenine-Möller, is an excellent resource for further information
about graphics hardware and interactive techniques.
The
OpenGL Graphics System: A Specification documents the OpenGL 3D programming
interface. The best tutorial for learning OpenGL programming is the OpenGL
Programming Guide: The Official Guide to Learning OpenGL, Third Edition
(Addison- Wesley, 1999), by Mason Woo, Jackie Neider, Tom Davis, and Dave
Shreiner. The www.opengl.org
website serves up much more information about OpenGL.
Documentation
for the Direct3D programming interface is available from Microsoft's msdn.microsoft.comWeb
site. NVIDIA provides further information about the Cg runtime, CgFX,
and Cg itself on its Developer website at developer.nvidia.com/Cg.
If
you are interested in the physics behind the particle system you created,
you can learn more by reviewing kinematics in any high school or college
physics textbook.
Jeff
Lander wrote a series of articles in 1998 and 1999 for Game Developer
Magazine about various animation techniques. You can find these articles
on the www.darwin3d.com
website. For particle systems, read "The Ocean Spray in Your Face."
For vertex skinning, check out "Skin Them Bones: Game Programming
for the Web Generation."
The
original volume of Game Programming Gems (Charles River Media,
2000), edited by Mark DeLoura, contains several gems related to key-frame
animation and vertex skinning. Check out these articles: "Interpolated
3D Keyframe Animation," by Herbert Marselas; "A Fast and Simple
Skinning Technique," by Torgeir Hagland; and "Filling the Gaps-Advanced
Animation Using Stitching and Skinning," by Ryan Woodland.
John
Vince's book 3-D Computer Animation (Addison-Wesley, 1992) covers
many of the techniques described in this chapter, as well as others, such
as free-form deformation (FFD).
DirectX
8 added point sprites to Direct3D. OpenGL implementations from multiple
hardware vendors support the NV_point_sprite
extension. The specification for this OpenGL extension is available at
the www.opengl.org website.
______________________________________________________
|