Character Animation with Direct3D- P20

Character Animation with Direct3D- P20

Character Animation with Direct3D- P20:This book is primarily aimed at teaching indie and hobby game developers how to
create character animation with Direct3D. Also, the seasoned professional game
developer may find some interesting things in this book.
You will need a solid understanding of the C++ programming language as well
as general object-oriented programming skills.

Nội dung Text: Character Animation with Direct3D- P20

366 Character Animation with Direct3D
//Get position from the four control hairs
float3 ch1 = GetHairPos(0, IN.hairIndices[0],
IN.hairIndices[1], IN.position.z);
float3 ch2 = GetHairPos(1, IN.hairIndices[0],
IN.hairIndices[1], IN.position.z);
float3 ch3 = GetHairPos(2, IN.hairIndices[0],
IN.hairIndices[1], IN.position.z);
float3 ch4 = GetHairPos(3, IN.hairIndices[0],
IN.hairIndices[1], IN.position.z);
//Blend linearly in 2D
float3 px1 = ch2 * IN.position.x + ch1 * (1.0f - IN.position.x);
float3 px2 = ch3 * IN.position.x + ch4 * (1.0f - IN.position.x);
float3 pos = px2 * IN.position.y + px1 * (1.0f - IN.position.y);
//Transform to world coordinates
float4 posWorld = mul(float4(pos.xyz, 1), matW);
OUT.position = mul(posWorld, matVP);
//Copy texture coordinates
OUT.tex0 = IN.tex0;
return OUT;
}
Here, the exact same operations are done as described earlier in the GetBlended-
Point() function of the HairPatch class. The blended position of each of the four
control hairs is obtained from the ControlHairTable using the GetHairPos() helper
function. Note that the indices passed to the helper function have been pre-computed
and stored in the vertex data. Next, the points returned from the control hairs are
blended depending on the 2D position of the hair vertex. The resulting point will be
in object space, so to get it to the correct position on the screen it is multiplied with
the world and the view-projection matrix. As said before, the beauty of going the long
way about this is that you now can update the control hairs on the CPU and the mesh
in the hair patch will just follow suit “automagically.”
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.

Chapter 15 Hair Animation 367
EXAMPLE 15.1
In Example 15.1 a single hair patch is created and rendered. The four control
hairs are animated with a simple noise function, and the mesh is updated
and animated completely on the GPU.
C REATING A H AIRCUT
So how would you go about creating these 10 to 20 control hairs needed to create
a decent-looking haircut for a character? Well, the most obvious way is to enter
them manually as was done with the four control hairs in Example 15.1. Although
it doesn’t take many minutes to realize that to model a set of 3D lines with a text
editor is probably not the way to go. The best way is to use 3D modeling software
(Max, Maya, or whatever other flavor you prefer). Figure 15.7 shows an image of
a “haircut” created in 3D Studio Max as a set of lines.
ease purchase PDF Split-Merge on www.verypdf.com to remove this watermark.

368 Character Animation with Direct3D
FIGURE 15.7
Control hairs used to create a haircut.
I was lucky enough to know Sami Vanhatalo (Senior Technical Artist at Remedy
Entertainment) who was kind enough to write an exporter for 3D Studio Max for
me. With this exporter it becomes very easy to dump a set of lines from 3D Studio
Max to either a text or a binary file. I won’t cover the exporter here in this book since
it is written in Max Script and is out of the scope of this book. However, you’ll find
both the text and binary version of the exporter on the accompanying CD-ROM,
along with detailed instructions on how to use them. For the next example I’ll use
the data that has been outputted from the binary exporter. The data is in Table 15.1.
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.

Chapter 15 Hair Animation 369
TABLE 15.1 THE BINARY HAIR FORMAT
Type Description
long File version number
long Number of lines
long Number of points for Line 1
float X value Line 1, Point 1
float Y value Line 1, Point 1
float Z value Line 1, Point 1
float X value Line 1, Point 2
float Y value Line 1, Point 2
float Z value Line 1, Point 2
…
float X value Line N, Point 1
float Y value Line N, Point 1
float Z value Line N, Point 1
The file structure is very simple and doesn’t contain any superfluous information.
Feel free to modify the exporter according to your own needs. In any case, to read a
set of lines from a binary file with this format, I’ve created the LoadHair() function to
the Hair class. The following code segment is an excerpt from this function showing
how to read one of these haircut data files:
ifstream in(hairFile, ios::binary);
if(!in.good())
return;
//Version number
long version;
in.read((char*)&version, sizeof(long));
//Number splines
long numSplines = 0;
in.read((char*)&numSplines, sizeof(long));
ease purchase PDF Split-Merge on www.verypdf.com to remove this watermark.

370 Character Animation with Direct3D
//Read splines
for(int i=0; i

Chapter 15 Hair Animation 371
FIGURE 15.8
Physical setup of the hair animation.
I’ve created a very simple bounding sphere class to be used for the character
head representation. The BoundingSphere class is defined as follows:
class BoundingSphere
{
public:
BoundingSphere(D3DXVECTOR3 pos, float radius);
void Render();
bool ResolveCollision(D3DXVECTOR3 &hairPos, float hairRadius);
private:
static ID3DXMesh* sm_pSphereMesh;
D3DXVECTOR3 m_position;
float m_radius;
};
Not so surprisingly, this class contains a position and a radius used to define the
bounding sphere. The static sm_pSphereMesh and the Render() function is just for
debugging and visualization purposes. The most important function in this class is
the ResolveCollision() function. This function tests whether a point collides with
the bounding sphere, and, if so, it moves the point away from the sphere until the
point no longer touches the sphere:
ease purchase PDF Split-Merge on www.verypdf.com to remove this watermark.

372 Character Animation with Direct3D
bool BoundingSphere::ResolveCollision(D3DXVECTOR3 &hairPos,
float hairRadius)
{
//Difference between control hair point and sphere center
D3DXVECTOR3 diff = hairPos - m_position;
//Distance between points
float dist = D3DXVec3Length(&diff);
if(dist < (m_radius + hairRadius))
{
//Collision has occurred; move hair away from bounding sphere
D3DXVec3Normalize(&diff, &diff);
hairPos = m_position + diff * (m_radius + hairRadius);
return true;
}
return false;
}
Once you have this function up and running and a few spheres placed to roughly
represent the character head, you can start simulating in some fashion. To get a hair
animation to look good, there’s a whole lot of black magic needed. For instance, you
can’t use gravity in the same way you would for other physical simulations. If you
used only gravity for simulating the hairs, the result would end up looking like a
drenched cat with hair hanging straight down. In reality, haircuts tend to roughly stay
in their original shape. To quickly emulate this, I’ve stored the original points of the
control hair points as the haircut is created. Then, at run time, I have a small spring
force between the current control hair’s position and its original position. This will
keep the haircut from deforming completely. To show a quick hair simulation in
action, I’ve added the UpdateSimulation() function to the ControlHair class:
void ControlHair::UpdateSimulation(
float deltaTime,
vector &headSpheres)
{
const float SPRING_STRENGTH = 10.0f;
const D3DXVECTOR3 WIND(-0.2f, 0.0f, 0.0f);
for(int i=1; i

374 Character Animation with Direct3D
class Hair
{
public:
Hair();
~Hair();
void LoadHair(const char* hairFile);
void CreatePatch(int index1,
int index2,
int index3,
int index4);
void Update(float deltaTime);
void Render(D3DXVECTOR3 &camPos);
int GetNumVertices();
int GetNumFaces();
public:
vector m_controlHairs;
vector m_hairPatches;
IDirect3DTexture9* m_pHairTexture;
vector m_headSpheres;
};
One important thing to mention is that the Render() function in this class sorts
all the hair patches in Z depth from the camera before rendering them to the screen.
The Update() function takes care of calling the UpdateSimulation() function in the
ControlHair objects, providing the m_headSpheres vector for the physical simulation.
If you want to extend this example, it would probably be in the Hair class that
you would, for example, keep a pointer to the head bone of the character. Using this
bone pointer you would then update the position of all the control hairs as the head
moves around.
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.

Chapter 15 Hair Animation 375
EXAMPLE 15.2
In this example a complete haircut is created and simulated in real time.
You can control the angle of the camera by clicking and dragging the
mouse. By pressing space, you will see the physical representation of the head along
with the control hairs as they are animated.
ease purchase PDF Split-Merge on www.verypdf.com to remove this watermark.

376 Character Animation with Direct3D
Figure 15.9 shows a series of frames taken from the animated hair.
FIGURE 15.9
A haircut animated with the system covered in this chapter.
C ONCLUSIONS
After reading this chapter, you should have a good understanding of the difficulties
you’re faced with when trying to implement hair animation. To increase the quality
of the hair animation presented in this chapter, there are two obvious improve-
ments. First, create a proper physical simulation instead of the “random wind” force
I’ve used here. Second, attach the hair to the character head bone and let it inherit
motion from the head of the character. When doing this you’ll see some wonderful
secondary motion as the character moves and then suddenly stops, etc.
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.

Chapter 15 Hair Animation 377
Another thing I haven’t covered in this chapter is the rendering of hair. There
are many advanced models of how light scatters on a hair surface. A really great
next stop for you is the thesis titled “Real-Time Hair Simulation and Visualization
for Games” by Henrik Halen [Halen07]. You can find this thesis online using the
following URL:
http://graphics.cs.lth.se/theses/projects/hair/
In the next and final chapter of this book, I’ll put most of the concepts covered
throughout this book into a single character class.
C HAPTER 15 E XERCISES
Create a Hair class supporting multiple levels of details. Scale the number of
segments used in hair strips and the number of hair strips used in total.
Try to create a longer haircut. (This may require a more detailed physical
representation of the character.)
Attach the haircut to a moving character head.
Implement a triangle hair patch relying on three control hairs instead of four.
F URTHER R EADING
[Halen07] Halen, Henrik, “Real-Time Hair Simulation and Visualization for
Games.” Available online at: http://graphics.cs.lth.se/theses/projects/hair/
report.pdf, 2007.
[Jung07] Jung, Yvonne, “Real Time Rendering and Animation of Virtual Characters.”
Available online at http://www.ijvr.org/issues/issue4-2007/6.pdf, 2007.
[Nguyen05] Nguyen, Hubert, “Hair Animation and Rendering in the Nalu Demo.”
Available online at http://http.developer.nvidia.com/GPUGems2/gpugems2_
chapter23.html, 2005.
[Ward05] Ward, Kelly, “Modeling Hair Using Levels-of-Detail.” Available online
at: http://www.cs.unc.edu/Research/ProjectSummaries/hair05.pdf, 2005.
ease purchase PDF Split-Merge on www.verypdf.com to remove this watermark.

This page intentionally left blank
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.

16 Putting It All Together
Welcome, dear reader, to the final chapter of this book! Throughout this book
you’ve had a quick glance at some of the major topics and techniques needed to
create a moving, talking, and falling character with Direct3D. In this chapter I
won’t present anything new, really, but will instead try to tie it all together and
create the final glorious Character class. Finally, for some of the topics I have not
covered in this book, I’ve added a few pages of discussion at the end. In this final
chapter, you’ll find the following:
379
ease purchase PDF Split-Merge on www.verypdf.com to remove this watermark.

380 Character Animation with Direct3D
Mixing facial animation with skeletal animation
The Character class
Future improvements
Alan Wake case study
Final thoughts
A TTACHING THE H EAD TO THE B ODY
So far, the facial animation examples in this book have been based on a standalone
face (i.e., one of those faces not attached to a body). I guess you’ll agree with me
when I say that this isn’t how you usually see characters in a game. So to remedy this
problem, this section covers how to attach an animated head (i.e., the Face class) to
a skinned mesh.
You’ve already come across this problem a bit in Chapter 8, Example 3, where a
running human character was morphed into a werewolf. I’ll show you in this section
how to do (almost) the same thing with a character’s face. Remember that the face
can be generated by the FaceFactory class, for example, and doesn’t have to look the
same as the one in the actual skinned model. There is, of course, the limitation that
both the source mesh (random generated face) and the target mesh (face in skinned
model) must have the same amount of vertices and index buffer. Figure 16.1 shows
the pieces involved.
The head of the skinned mesh (black wireframe) is just another skinned mesh
with blend weights, blend indices, etc. The Face class, on the other hand, supports
all facial animation features (and can also be generated by the FaceFactory class).
Your job now is to replace the skinned mesh head with a Face object but while still
keeping the skinned information. This way, the new animated face will also turn if
there’s some keyframe animation involving the head (or if you use some Look-At
IK, and so on).
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.