FABRIKChain.cs 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. using UnityEngine;
  2. using System.Collections;
  3. namespace RootMotion.FinalIK {
  4. /// <summary>
  5. /// Branch of FABRIK components in the FABRIKRoot hierarchy.
  6. /// </summary>
  7. [System.Serializable]
  8. public class FABRIKChain {
  9. #region Main Interface
  10. /// <summary>
  11. /// The FABRIK component.
  12. /// </summary>
  13. public FABRIK ik;
  14. /// <summary>
  15. /// Parent pull weight.
  16. /// </summary>
  17. [Range(0f, 1f)]
  18. public float pull = 1f;
  19. /// <summary>
  20. /// Resistance to being pulled by child chains.
  21. /// </summary>
  22. [Range(0f, 1f)]
  23. public float pin = 1f;
  24. /// <summary>
  25. /// The child chain indexes.
  26. /// </summary>
  27. public int[] children = new int[0];
  28. /// <summary>
  29. /// Checks whether this FABRIKChain is valid.
  30. /// </summary>
  31. public bool IsValid(ref string message) {
  32. if (ik == null) {
  33. message = "IK unassigned in FABRIKChain.";
  34. return false;
  35. }
  36. if (!ik.solver.IsValid(ref message)) return false;
  37. return true;
  38. }
  39. #endregion Main Interface
  40. /*
  41. * Initiate the chain
  42. * */
  43. public void Initiate() {
  44. ik.enabled = false;
  45. }
  46. /*
  47. * Solving stage 1 of the FABRIK algorithm from end effectors towards the root.
  48. * */
  49. public void Stage1(FABRIKChain[] chain) {
  50. // Solving children first
  51. for (int i = 0; i < children.Length; i++) chain[children[i]].Stage1(chain);
  52. // The last chains
  53. if (children.Length == 0) {
  54. ik.solver.SolveForward(ik.solver.GetIKPosition());
  55. return;
  56. }
  57. ik.solver.SolveForward(GetCentroid(chain));
  58. }
  59. /*
  60. * Solving stage 2 of the FABRIK algoright from the root to the end effectors.
  61. * */
  62. public void Stage2(Vector3 rootPosition, FABRIKChain[] chain) {
  63. // Solve this chain backwards
  64. ik.solver.SolveBackward(rootPosition);
  65. // Solve child chains
  66. for (int i = 0; i < children.Length; i++) {
  67. chain[children[i]].Stage2(ik.solver.bones[ik.solver.bones.Length - 1].transform.position, chain);
  68. }
  69. }
  70. // Calculate the centroid of child positions
  71. private Vector3 GetCentroid(FABRIKChain[] chain) {
  72. Vector3 position = ik.solver.GetIKPosition();
  73. // The chain is pinned, ignore the children
  74. if (pin >= 1f) return position;
  75. // Get the sum of the pull values of all the children
  76. float pullSum = 0f;
  77. for (int i = 0; i < children.Length; i++) pullSum += chain[children[i]].pull;
  78. // All pull values are zero
  79. if (pullSum <= 0f) return position;
  80. if (pullSum < 1f) pullSum = 1f;
  81. // Calculating the centroid
  82. Vector3 centroid = position;
  83. for (int i = 0; i < children.Length; i++) {
  84. // Vector from IKPosition to the first bone of the child
  85. Vector3 toChild = chain[children[i]].ik.solver.bones[0].solverPosition - position;
  86. // Weight of the child
  87. float childWeight = chain[children[i]].pull / pullSum;
  88. // Adding to the centroid
  89. centroid += toChild * childWeight;
  90. }
  91. // No pinning
  92. if (pin <= 0f) return centroid;
  93. // Pinning
  94. return centroid + (position - centroid) * pin;
  95. }
  96. }
  97. }