# Character Animation with Direct3D- P14

Chia sẻ: Cong Thanh | Ngày: | Loại File: PDF | Số trang:20

0
31
lượt xem
4

## Character Animation with Direct3D- P14

Mô tả tài liệu

Character Animation with Direct3D- P14: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.

Chủ đề:

Bình luận(0)

Lưu

## Nội dung Text: Character Animation with Direct3D- P14

1. 246 Character Animation with Direct3D EXAMPLE 11.1 This is the first inverse kinematics example featuring a simple Look-At example. The soldier will look at the mouse cursor just like in the earlier examples with the eyeballs, except in this example the head bone is manipulated to turn the whole head to face the cursor. As you can see in this example, the IK are applied on top of normal keyframed animation. T WO -J OINT I NVERSE K INEMATICS Now I’ll show you how to attack the Two-Joint “Reach” IK problem. To solve this problem easier, you must take the information you know about people in general and put it to good use. For example, in games the elbow joint is treated like a hinge joint with only one degree of freedom (1-DoF), while the shoulder joint is treated like a ball joint (3-DoF). The fact that you treat the elbow (or knee) joint as a hinge makes this a whole lot simpler. You know that the arm can be fully extended, completely bent, or something in between. So, in other words, you know that the angle between the upper and lower arm has to be between 0 and 180 degrees. This in turn makes it pretty easy for you to calculate the reach of an arm when you know the length of the upper and lower arm. Consider Figure 11.7, for example. Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
2. Chapter 11 Inverse Kinematics 247 FIGURE 11.7 Within an arm’s reach? The black line in Figure 11.7 defines all the points that this arm can reach, assuming that the elbow joint can bend from 0 to 180 degrees. Let’s say that you’re trying to make your character reach a certain point with his arm. Your first task is to figure out the angle of the elbow joint given the distance to the target. Using the Law of Cosines, this becomes a pretty straightforward task, since you know the length of all sides of the triangle. The formula for the Law of Cosines is: C 2 = A2 + B 2 – 2ABcos(x) Trivia: You might recognize part of the Law of Cosines as the Pythagorean Theorem. Actually, the Pythagorean Theorem is a special case of the Law of Cosines where the angle x is 90 degrees. Since the cosine for 90 degrees is zero, the term -2ABcos(x) can be removed. ease purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
3. 248 Character Animation with Direct3D FIGURE 11.8 The Law of Cosines. Figure 11.7 shows the Law of Cosines applied to the elbow problem. In Figure 11.8, C is known because it is the length from the shoulder to the IK target. A and B are also known because they are simply the length of the upper and lower arm. So to solve the angle x, you just need to reorganize the Law of Cosines as follows: 2 2 2 x = acos A + B – C 2AB First you have to bend the elbow to the angle that gives you the right “length.” Then you just rotate the shoulder (a ball joint, remember?) using the same simple Look-At IK approach covered in the previous example. The ApplyArmIK() function has been added to the InverseKinematics class to do all this: void InverseKinematics::ApplyArmIK(D3DXVECTOR3 &hingeAxis, D3DXVECTOR3 &target) { // Set up some vectors and positions D3DXVECTOR3 startPosition = D3DXVECTOR3( m_pShoulderBone->CombinedTransformationMatrix._41, m_pShoulderBone->CombinedTransformationMatrix._42, m_pShoulderBone->CombinedTransformationMatrix._43); D3DXVECTOR3 jointPosition = D3DXVECTOR3( m_pElbowBone->CombinedTransformationMatrix._41, m_pElbowBone->CombinedTransformationMatrix._42, m_pElbowBone->CombinedTransformationMatrix._43); Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
4. Chapter 11 Inverse Kinematics 249 D3DXVECTOR3 endPosition = D3DXVECTOR3( m_pHandBone->CombinedTransformationMatrix._41, m_pHandBone->CombinedTransformationMatrix._42, m_pHandBone->CombinedTransformationMatrix._43); D3DXVECTOR3 startToTarget = target - startPosition; D3DXVECTOR3 startToJoint = jointPosition - startPosition; D3DXVECTOR3 jointToEnd = endPosition - jointPosition; float distStartToTarget = D3DXVec3Length(&startToTarget); float distStartToJoint = D3DXVec3Length(&startToJoint); float distJointToEnd = D3DXVec3Length(&jointToEnd); // Calculate joint bone rotation // Calculate current angle and wanted angle float wantedJointAngle = 0.0f; if(distStartToTarget >= distStartToJoint + distJointToEnd) { // Target out of reach wantedJointAngle = D3DXToRadian(180.0f); } else { //Calculate wanted joint angle (using the Law of Cosines) float cosAngle = (distStartToJoint * distStartToJoint + distJointToEnd * distJointToEnd – distStartToTarget * distStartToTarget) / (2.0f * distStartToJoint * distJointToEnd); wantedJointAngle = acosf(cosAngle); } //Normalize vectors D3DXVECTOR3 nmlStartToJoint = startToJoint; D3DXVECTOR3 nmlJointToEnd = jointToEnd; D3DXVec3Normalize(&nmlStartToJoint, &nmlStartToJoint); D3DXVec3Normalize(&nmlJointToEnd, &nmlJointToEnd); //Calculate the current joint angle float currentJointAngle = acosf(D3DXVec3Dot(&(-nmlStartToJoint), &nmlJointToEnd)); ease purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
5. 250 Character Animation with Direct3D //Calculate rotation matrix float diffJointAngle = wantedJointAngle - currentJointAngle; D3DXMATRIX rotation; D3DXMatrixRotationAxis(&rotation, &hingeAxis, diffJointAngle); //Apply elbow transformation m_pElbowBone->TransformationMatrix = rotation * m_pElbowBone->TransformationMatrix; //Now the elbow “bending” has been done. Next you just //need to rotate the shoulder using the Look-at IK algorithm //Calcuate new end position //Calculate this in world position and transform //it later to start bones local space D3DXMATRIX tempMatrix; tempMatrix = m_pElbowBone->CombinedTransformationMatrix; tempMatrix._41 = 0.0f; tempMatrix._42 = 0.0f; tempMatrix._43 = 0.0f; tempMatrix._44 = 1.0f; D3DXVECTOR3 worldHingeAxis; D3DXVECTOR3 newJointToEnd; D3DXVec3TransformCoord(&worldHingeAxis, &hingeAxis, &tempMatrix); D3DXMatrixRotationAxis(&rotation,&worldHingeAxis,diffJointAngle); D3DXVec3TransformCoord(&newJointToEnd, &jointToEnd, &rotation); D3DXVECTOR3 newEndPosition; D3DXVec3Add(&newEndPosition, &newJointToEnd, &jointPosition); // Calculate start bone rotation D3DXMATRIX mtxToLocal; D3DXMatrixInverse(&mtxToLocal, NULL, &m_pShoulderBone->CombinedTransformationMatrix); D3DXVECTOR3 localNewEnd; //Current end point D3DXVECTOR3 localTarget; //IK target in local space D3DXVec3TransformCoord(&localNewEnd,&newEndPosition,&mtxToLocal); D3DXVec3TransformCoord(&localTarget, &target, &mtxToLocal); D3DXVec3Normalize(&localNewEnd, &localNewEnd); D3DXVec3Normalize(&localTarget, &localTarget); Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
6. Chapter 11 Inverse Kinematics 251 D3DXVECTOR3 localAxis; D3DXVec3Cross(&localAxis, &localNewEnd, &localTarget); if(D3DXVec3Length(&localAxis) == 0.0f) return; D3DXVec3Normalize(&localAxis, &localAxis); float localAngle = acosf(D3DXVec3Dot(&localNewEnd, &localTarget)); // Apply the rotation that makes the bone turn D3DXMatrixRotationAxis(&rotation, &localAxis, localAngle); m_pShoulderBone->CombinedTransformationMatrix = rotation * m_pShoulderBone->CombinedTransformationMatrix; m_pShoulderBone->TransformationMatrix = rotation * m_pShoulderBone->TransformationMatrix; // Update matrices of child bones. if(m_pShoulderBone->pFrameFirstChild) m_pSkinnedMesh->UpdateMatrices( (BONE*)m_pShoulderBone->pFrameFirstChild, &m_pShoulderBone->CombinedTransformationMatrix); } There! This humongous piece of code implements the concept of Two-Joint IK as explained earlier. As you can see in this function we apply any rotation of the joints both to the transformation matrix and the combined transformation matrix of the bone. This is because the SkinnedMesh class recalculates the combined transformation matrix whenever the UpdateMatrices() function is called. So if you haven’t applied the IK rotation to both matrices it would be lost when the UpdateMatrices() function is called. ease purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
7. 252 Character Animation with Direct3D EXAMPLE 11.2 Example 11.2 has all the code for the Two-Joint IK solution covered in this section. You move the target point around with the mouse, and the character will attempt to reach it with one arm. Try to modify this example by limiting the freedom of the shoulder joint so that the arm can’t move through the rest of the body. Also, see if you can apply Two-Joint IK to the other limbs (legs and other arm) as well. C ONCLUSIONS This chapter covered the basics of inverse kinematics (IK) and explained that as a general problem it is quite tough to solve (even though there are quite a few approaches to doing so). I covered two specific IK applications for character animation: Look-At and Two-Joint “Reach” IK. The Two-Joint IK can also be used for placing legs on uneven terrain, making a character reach for a game- world object, and much more. You would also need IK to make a character hold an object (such as a staff, for example) with both hands. This could, of course, be done with normal keyframe animation as well, but it then often results in one hand not “holding on” perfectly and sometimes floating through the staff (due to interpolation between keyframes). Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
8. Chapter 11 Inverse Kinematics 253 Hopefully this chapter served as a good IK primer for you to start implementing your own “hands-on” characters. This chapter essentially wraps up the many individual parts of character ani- mation in this book. C HAPTER 11 E XERCISES Add weights to the IK functions enabling you to blend between keyframed animation and IK animation. A good next step for you would be to combine a keyframed animation such as opening a door with IK. As the animation is in the state of holding the door handle, blend in the Two-Joint IK with the door handle as the IK target. The soldier is holding the rifle with two hands. Glue the other hand (the one that is not the parent of the rifle) to it using IK. Implement IK for the legs and make the character walk on uneven terrain. Implement aiming for the soldier. F URTHER R EADING [Melax00] Melax, Stan, “The Shortest Arc Quaternion,” Game Programming Gems. Charles River Media, 2000. ease purchase PDF Split-Merge on www.verypdf.com to remove this watermark.