Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống
1
/ 20 trang
THÔNG TIN TÀI LIỆU
Thông tin cơ bản
Định dạng
Số trang
20
Dung lượng
462,52 KB
Nội dung
346 Character Animation with Direct3D Because I’m using a plane (calculated from the hit position and the triangle normal) to calculate the UV coordinates of the decal, there will be some stretching when the decal is applied to curved surfaces. You can see this in Figure 14.15 where the positions of the vertices in the texture surface aren’t spread out uniformly (even though the distance on the mesh surface between the vertices is). This is a problem related to that of using the straight line distance from the hit to the vertex described earlier. If you can calculate the actual distance over the mesh surface from the hit position to the vertex, then you can also improve on the UV coordinate calculation. CONCLUSIONS This chapter introduced the concept of adding real-time scratches, bullet holes, etc., to your character using decals. Decals are a great way of adding extra detail or ran- domness to your characters without having a major impact on texture memory. One thing I haven’t covered in this chapter is how to handle a large number of decals. In a first-person shooter game, for example, the number of bullet-hole- induced decals can quickly rise to several thousands. At some point you need to start removing the decals from the scene or your frame rate will start to drop. Usually, you’ll need to implement some form of decal manager that keeps track of all the decals in the world and which can remove them according to: FIGURE 14.15 Decal UV coordinates over a curved surface. Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark. Chapter 14 Character Decals 347 Decal position (relative to the player) Decal age First-in, first-out Once a decal has been flagged for removal, you can either just pop it out of existence, fade it out, or wait until the player is looking the other way and then remove it (you can easily check the decal position against the player view frustum). One big improvement to this decal system would also be to have normal-mapped decals, making it possible to add dents, etc., to the character. Hopefully you’ve gotten enough out of this chapter to be able to create your own decal system (with all the possible improvements mentioned in this chapter and more). CHAPTER 14 EXERCISES Also create decals for static meshes (pulse rifle, helmet). Note that you need to disregard the skinning information when creating the decal mesh; otherwise, it is pretty much the same process. Use the D3DXIntersect method to find all intersections of a mesh. Use this also to create exit wounds of the ray. Create a normal-mapped wound decal. Create a particle system and tie it to the decal (e.g., blood pouring from a wound). Make a more accurate implementation of the “triangle-bounding sphere” test used to determine whether or not a triangle belongs to the decal mesh. Find the point on the triangle closest to the bounding sphere. Use different decals for the character’s armor and the face. Please 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. 349 Hair Animation15 In this chapter I’ll briefly cover the topic of dynamic hair animation. When I say “hair animation” I don’t mean a simple pony tail animated with a few bones, but the generic “any-hair-style” case. This topic is closely linked to the topic of cloth animation (they share many similarities). Hair animation is a component that most games leave out completely. The primary reason is because it is quite costly (thousands of small triangles are required, which can, in most cases, give you more bang-for-your-buck somewhere else). The second reason is that it is very hard to get hair animation to look good. So, because of these issues, most developers just opt for leaving out animated hair Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark. 350 Character Animation with Direct3D completely from their game characters. Usually, they stick with either a static mesh for the characters’ hair or cover the heads with some form of helmets or other headwear. The following topics will be covered in this chapter: Single hairs versus strips of hair Generating hair strips from control splines Animating control splines HAIR REPRESENTATION OK, so you want to have a dynamically animated haircut for your game character. Well, the first issue to solve is how to represent, or render, the hair. The two most common ways to represent hair are either as a bunch of splines or as a set of meshes (strips) with an alpha-blended hair texture (see Figure 15.1). FIGURE 15.1 Individual hair strands versus hair strips. Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark. Chapter 15 Hair Animation 351 NVIDIA has made a very nice demo of a mermaid, which renders individual hair strands as splines. Although this option may be viable in future games, it is, at the time this book was written, a far too costly option (nevertheless, I strongly recommend you check out NVIDIA’s Nalu demo). You can find a really good article about the hair animation in this demo at the following URL: http://http.developer.nvidia.com/GPUGems2/gpugems2_chapter23.html It seems rendering/simulating individual hair strands is a bit too expensive for today’s hardware. This leaves us with the option of simulating multiple hair strands using a mesh strip and a texture. HAIR MODELING The problem of creating the hair mesh for the character can be approached in many ways. The most straightforward approach to grasp is, of course, to do it by hand. Simply model and texture all the hair strips of the character in modeling software like 3D Studio Max, Maya, or Lightwave, etc. Then, import this hair mesh into your game somehow and animate and render it. This is, of course, a rather expensive process and one that requires considerable artistic talent (something that, not surprisingly, most programmers lack). It also means that for each new haircut you will have to do all the work over again from scratch. So, instead, let’s try to make a system for this and “grow” hair for our characters in code. This will be done by importing just a few splines (aka control splines) from some modeling software and then generating the hairs (either strands or strips) between the control splines in code. Figure 15.2 shows an example of this. FIGURE 15.2 Example of control hairs and interpolated hairs. Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark. 352 Character Animation with Direct3D Even though Figure 15.2 only shows how this could be used to generate hair strands, you can easily use this technique to generate strips as well. In either case, this technique lets you (or your artist) quickly create or shape new haircuts without all the manual polygonal modeling and texturing. THE CONTROL HAIR CLASS Let’s start by looking at a single control hair. The control hair consists of a list of points that define the location of the control hair. Since the control hairs will be used only for the growing of the more detailed hair strips and to update the hair simulation, it is good to keep the number of points used in the control hair to a minimum. Just because the control hair has a low level of detail (i.e., few points) doesn’t mean the final hair strips will, since these are cubically interpolated from the points in the control hair, as shown in Figure 15.3. This is a great thing, because it gives you complete control over the amount of polygons and detail you have for your haircuts (as opposed to pre-created hair meshes). To represent a control hair, I’ve created the following class: class ControlHair { public: ControlHair(); float GetSegmentPercent(float prc); pair<int, int> GetBlendIndices(float prc); D3DXVECTOR3 GetBlendedPoint(float prc); FIGURE 15.3 Control hair and generated strip. Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark. void Render(); public: vector<D3DXVECTOR3> m_points; }; As said before, the control hair just consists of a list of control points. The GetSegmentPercent(), GetBlendIndices(), and GetBlendedPoint() helper functions are used when calculating the cubically blended spline. These three functions take a percentage float value in the range 0 to 1, where 0 is the start of the hair and 1 is the end point of the hair. Figure 15.4 shows how these three functions are used. Chapter 15 Hair Animation 353 FIGURE 15.4 The control hair helper functions. Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark. Figure 15.4 shows the result if you pass 55% (or 0.55f) to these three helper func- tions. The first helper function, GetSegmentPercent(), converts a percentage value from the whole hair to a percentage value between two points of the hair. So first you need to calculate between which two points the value lies and then calculate the new percentage value as shown in code here: float ControlHair::GetSegmentPercent(float prc) { //Calculate percentage step between two points in the control hair float step = 1.0f / (float)(m_points.size() - 1); int numSteps = (int)(prc / step); //Convert prc to the [0-1] range of the segment return (prc - numSteps * step) / step; } Next is the GetBlendIndices() function. This function retrieves the two indices of the segment described by a certain hair percentage value as shown here: pair<int, int> ControlHair::GetBlendIndices(float prc) { //Less than zero if(prc <= 0.0f) return pair<int, int>(0, 0); //Greater than one if(prc >= 1.0f) return pair<int, int>( (int)m_points.size() - 1, (int)m_points.size() - 1); //Get first segment index int index1 = (int)(prc * (m_points.size() - 1)); //Get second segment index (no greater than num points - 1) int index2 = min(index1 + 1, (int)m_points.size() - 1); return pair<int, int>(index1, index2); } 354 Character Animation with Direct3D Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark. Chapter 15 Hair Animation 355 This function simply figures out which two points define the segment on which a certain percentage value lies. This information must be known when you attempt to blend between two points, which coincidentally is something that the next helper function does. To get smooth blending between the control points (as opposed to basic linear interpolation, which would produce very blocky hairs), I use cubic interpolation for the hair strips. Consider the points shown in Figure 15.5. A cubically interpolated point (p n ) needs to take the four neighboring points (p 1 , p 2 , p 3 and p 4 ) into consideration. The point p n can be calculated according to the following formula, where t is the percentage between the points p 1 and p 2 : P = (p 3 – p 2 )–(p 0 – p 1 ) Q = (p 0 – p 1 ) – P R = (p 2 – p 0 ) S = p 1 p n = P ϫ t 3 + Q ϫ t 2 + R ϫ t + S This formula is used in the GetBlendedPoint() function, which makes use of the two previous helper functions to return a cubically blended point along the control hair: D3DXVECTOR3 ControlHair::GetBlendedPoint(float prc) { //Get two affected indices pair<int, int> indices = GetBlendIndices(prc); //Get the four point indices int index0 = max(indices.first - 1, 0); FIGURE 15.5 Cubic interpolation. Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark. [...]...356 Character Animation with Direct3D int index1 = indices.first; int index2 = indices.second; int index3 = min(indices.second + 1, (int)m_points.size() - 1); //Get segment percentage float t = GetSegmentPercent(prc);... GetBlendedPoint(D3DXVECTOR2 pos, float prc); HairVertex GetBlendedVertex(D3DXVECTOR2 pos, float prc, bool oddVertex); ease purchase PDF Split-Merge on www.verypdf.com to remove this watermark 358 Character Animation with Direct3D vector GetStripPlacements(float sizePerHairStrip); void CreateHairStrips(int numSegments, float sizePerHairStrip, float stripSize); void Render(); public: ID3DXMesh*... the next, depending on what performance requirements the game you’re working on has However, with this way of growing the hair dynamically you can even plug in these two values in an LOD system Simply increase the number of strips and the detail of these the closer to the camera a character is Let’s start with the simpler of the two problems—namely, where to place the strips One way is, of course,... valid; h++) { D3DXVECTOR3 diff = hairPos - strips[h]; if(D3DXVec2Length(&diff) < sizePerHairStrip) valid = false; } ease purchase PDF Split-Merge on www.verypdf.com to remove this watermark 360 Character Animation with Direct3D //Add hair if valid if(valid) strips.push_back(hairPos); } //Order strips for correct alpha blending for(int i=0; i . watermark. 350 Character Animation with Direct3D completely from their game characters. Usually, they stick with either a static mesh for the characters’ hair or cover the heads with some form of helmets. watermark. 349 Hair Animation1 5 In this chapter I’ll briefly cover the topic of dynamic hair animation. When I say “hair animation I don’t mean a simple pony tail animated with a few bones, but the. pair<int, int>(index1, index2); } 354 Character Animation with Direct3D Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark. Chapter 15 Hair Animation 355 This function simply