IKMappingLimb.cs 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. using UnityEngine;
  2. using System.Collections;
  3. namespace RootMotion.FinalIK {
  4. /// <summary>
  5. /// Maps a 3-segmented bone hierarchy to a node chain of an %IK Solver
  6. /// </summary>
  7. [System.Serializable]
  8. public class IKMappingLimb: IKMapping {
  9. #region Main Interface
  10. /// <summary>
  11. /// Limb Bone Map type
  12. /// </summary>
  13. [System.Serializable]
  14. public enum BoneMapType {
  15. Parent,
  16. Bone1,
  17. Bone2,
  18. Bone3
  19. }
  20. /// <summary>
  21. /// The optional parent bone (clavicle).
  22. /// </summary>
  23. public Transform parentBone;
  24. /// <summary>
  25. /// The first bone (upper arm or thigh).
  26. /// </summary>
  27. public Transform bone1;
  28. /// <summary>
  29. /// The second bone (forearm or calf).
  30. /// </summary>
  31. public Transform bone2;
  32. /// <summary>
  33. /// The third bone (hand or foot).
  34. /// </summary>
  35. public Transform bone3;
  36. /// <summary>
  37. /// The weight of maintaining the third bone's rotation as it was in the animation
  38. /// </summary>
  39. [Range(0f, 1f)]
  40. public float maintainRotationWeight;
  41. /// <summary>
  42. /// The weight of mapping the limb to it's IK pose. This can be useful if you want to disable the effect of IK for the limb.
  43. /// </summary>
  44. [Range(0f, 1f)]
  45. public float weight = 1f; // Added in 0.2
  46. /// <summary>
  47. /// Disable this to maintain original sampled rotations of the limb bones relative to each other.
  48. /// </summary>
  49. [System.NonSerializedAttribute] public bool updatePlaneRotations = true;
  50. /// <summary>
  51. /// Determines whether this IKMappingLimb is valid
  52. /// </summary>
  53. public override bool IsValid(IKSolver solver, ref string message) {
  54. if (!base.IsValid(solver, ref message)) return false;
  55. if (!BoneIsValid(bone1, solver, ref message)) return false;
  56. if (!BoneIsValid(bone2, solver, ref message)) return false;
  57. if (!BoneIsValid(bone3, solver, ref message)) return false;
  58. return true;
  59. }
  60. /// <summary>
  61. /// Gets the bone map of the specified bone.
  62. /// </summary>
  63. public BoneMap GetBoneMap(BoneMapType boneMap) {
  64. switch(boneMap) {
  65. case BoneMapType.Parent:
  66. if (parentBone == null) Warning.Log("This limb does not have a parent (shoulder) bone", bone1);
  67. return boneMapParent;
  68. case BoneMapType.Bone1: return boneMap1;
  69. case BoneMapType.Bone2: return boneMap2;
  70. default: return boneMap3;
  71. }
  72. }
  73. /// <summary>
  74. /// Makes the limb mapped to the specific local directions of the bones. Added in 0.3
  75. /// </summary>
  76. public void SetLimbOrientation(Vector3 upper, Vector3 lower) {
  77. boneMap1.defaultLocalTargetRotation = Quaternion.Inverse(Quaternion.Inverse(bone1.rotation) * Quaternion.LookRotation(bone2.position - bone1.position, bone1.rotation * -upper));
  78. boneMap2.defaultLocalTargetRotation = Quaternion.Inverse(Quaternion.Inverse(bone2.rotation) * Quaternion.LookRotation(bone3.position - bone2.position, bone2.rotation * -lower));
  79. }
  80. #endregion Main Interface
  81. private BoneMap boneMapParent = new BoneMap(), boneMap1 = new BoneMap(), boneMap2 = new BoneMap(), boneMap3 = new BoneMap();
  82. public IKMappingLimb() {}
  83. public IKMappingLimb(Transform bone1, Transform bone2, Transform bone3, Transform parentBone = null) {
  84. SetBones(bone1, bone2, bone3, parentBone);
  85. }
  86. public void SetBones(Transform bone1, Transform bone2, Transform bone3, Transform parentBone = null) {
  87. this.bone1 = bone1;
  88. this.bone2 = bone2;
  89. this.bone3 = bone3;
  90. this.parentBone = parentBone;
  91. }
  92. public void StoreDefaultLocalState() {
  93. if (parentBone != null) boneMapParent.StoreDefaultLocalState();
  94. boneMap1.StoreDefaultLocalState();
  95. boneMap2.StoreDefaultLocalState();
  96. boneMap3.StoreDefaultLocalState();
  97. }
  98. public void FixTransforms() {
  99. if (parentBone != null) boneMapParent.FixTransform(false);
  100. boneMap1.FixTransform(true);
  101. boneMap2.FixTransform(false);
  102. boneMap3.FixTransform(false);
  103. }
  104. /*
  105. * Initiating and setting defaults
  106. * */
  107. public override void Initiate(IKSolverFullBody solver) {
  108. if (boneMapParent == null) boneMapParent = new BoneMap();
  109. if (boneMap1 == null) boneMap1 = new BoneMap();
  110. if (boneMap2 == null) boneMap2 = new BoneMap();
  111. if (boneMap3 == null) boneMap3 = new BoneMap();
  112. // Finding the nodes
  113. if (parentBone != null) boneMapParent.Initiate(parentBone, solver);
  114. boneMap1.Initiate(bone1, solver);
  115. boneMap2.Initiate(bone2, solver);
  116. boneMap3.Initiate(bone3, solver);
  117. // Define plane points for the bone maps
  118. boneMap1.SetPlane(solver, boneMap1.transform, boneMap2.transform, boneMap3.transform);
  119. boneMap2.SetPlane(solver, boneMap2.transform, boneMap3.transform, boneMap1.transform);
  120. // Find the swing axis for the parent bone
  121. if (parentBone != null) boneMapParent.SetLocalSwingAxis(boneMap1);
  122. }
  123. /*
  124. * Presolving the bones and maintaining rotation
  125. * */
  126. public void ReadPose() {
  127. boneMap1.UpdatePlane(updatePlaneRotations, true);
  128. boneMap2.UpdatePlane(updatePlaneRotations, false);
  129. // Clamping weights
  130. weight = Mathf.Clamp(weight, 0f, 1f);
  131. // Define plane points for the bone maps
  132. boneMap3.MaintainRotation();
  133. }
  134. public void WritePose(IKSolverFullBody solver, bool fullBody) {
  135. if (weight <= 0f) return;
  136. // Swing the parent bone to look at the first node's position
  137. if (fullBody) {
  138. if (parentBone != null) {
  139. boneMapParent.Swing(solver.GetNode(boneMap1.chainIndex, boneMap1.nodeIndex).solverPosition, weight);
  140. //boneMapParent.Swing(boneMap1.node.solverPosition, weight);
  141. }
  142. // Fix the first bone to it's node
  143. boneMap1.FixToNode(solver, weight);
  144. }
  145. // Rotate the 2 first bones to the plane points
  146. boneMap1.RotateToPlane(solver, weight);
  147. boneMap2.RotateToPlane(solver, weight);
  148. // Rotate the third bone to the rotation it had before solving
  149. boneMap3.RotateToMaintain(maintainRotationWeight * weight * solver.IKPositionWeight);
  150. // Rotate the third bone to the effector rotation
  151. boneMap3.RotateToEffector(solver, weight);
  152. }
  153. }
  154. }