Advertisement
Guest User

Kraken IK Solver (WIP)

a guest
Feb 10th, 2016
159
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. require InlineDrawing;
  2. require Kraken;
  3. require Math;
  4. require Animation;
  5.  
  6.  
  7. object TwoBoneStretchyIKSolver : KrakenSolver {
  8.   Xfo initPose[];
  9. };
  10.  
  11.  
  12. // Default Constructor
  13. function TwoBoneStretchyIKSolver()
  14. {
  15.  
  16. }
  17.  
  18.  
  19. function TwoBoneStretchyIKSolver(
  20.   Xfo initPose[])
  21. {
  22.   this.initPose = initPose;
  23. }
  24.  
  25.  
  26. // Return Arguments for Kraken
  27. function KrakenSolverArg[] TwoBoneStretchyIKSolver.getArguments(){
  28.   KrakenSolverArg args[] = this.parent.getArguments();
  29.   args.push(KrakenSolverArg('rightSide', 'In', 'Boolean'));
  30.  
  31.   args.push(KrakenSolverArg('ikblend', 'In', 'Scalar'));
  32.   args.push(KrakenSolverArg('softIK', 'In', 'Boolean'));
  33.   args.push(KrakenSolverArg('softRatio', 'In', 'Scalar'));
  34.   args.push(KrakenSolverArg('stretch', 'In', 'Boolean'));
  35.   args.push(KrakenSolverArg('stretchBlend', 'In', 'Scalar'));
  36.   args.push(KrakenSolverArg('slide', 'In', 'Scalar'));
  37.   args.push(KrakenSolverArg('pin', 'In', 'Scalar'));
  38.  
  39.   args.push(KrakenSolverArg('root', 'In', 'Mat44'));
  40.   args.push(KrakenSolverArg('bone0FK', 'In', 'Mat44'));
  41.   args.push(KrakenSolverArg('bone1FK', 'In', 'Mat44'));
  42.   args.push(KrakenSolverArg('ikHandle', 'In', 'Mat44'));
  43.   args.push(KrakenSolverArg('upV', 'In', 'Mat44'));
  44.  
  45.   args.push(KrakenSolverArg('bone0Len', 'In', 'Scalar'));
  46.   args.push(KrakenSolverArg('bone1Len', 'In', 'Scalar'));
  47.   args.push(KrakenSolverArg('bone0Out', 'Out', 'Mat44'));
  48.   args.push(KrakenSolverArg('bone1Out', 'Out', 'Mat44'));
  49.   args.push(KrakenSolverArg('bone2Out', 'Out', 'Mat44'));
  50.   return args;
  51. }
  52.  
  53.  
  54. // Solve
  55. function TwoBoneStretchyIKSolver.solve!
  56. (
  57.   Boolean drawDebug,
  58.   Scalar rigScale,
  59.   Boolean rightSide,
  60.  
  61.   Scalar ikblend,
  62.   Boolean softIK,
  63.   Scalar softRatio,
  64.   Boolean stretch,
  65.   Scalar stretchBlend,
  66.   Scalar slide,
  67.   Scalar pin,
  68.  
  69.   Mat44 root,
  70.   Mat44 bone0FK,
  71.   Mat44 bone1FK,
  72.   Mat44 ikHandle,
  73.   Mat44 upV,
  74.  
  75.   Scalar bone0Len,
  76.   Scalar bone1Len,
  77.   io Mat44 bone0Out,
  78.   io Mat44 bone1Out,
  79.   io Mat44 bone2Out
  80. ){
  81.  
  82.   Xfo bone0FkXfo = Xfo(bone0FK);
  83.   Xfo bone1FkXfo = Xfo(bone1FK);
  84.  
  85.   Xfo bone0Xfo;
  86.   Xfo bone1Xfo;
  87.   Xfo bone2Xfo;
  88.  
  89.   // TODO: Fix FK bone0 translate (could lock this in the component?)
  90.   // TODO: Fix FK/IK blend "translation" blending; instead blend lengths
  91.  
  92.   Scalar outBone0Len = bone0Len;
  93.   Scalar outBone1Len = bone1Len;
  94.  
  95.   // Scale to global rig scale
  96.   Scalar scaledBone0Len = bone0Len * rigScale;
  97.   Scalar scaledBone1Len = bone1Len * rigScale;
  98.  
  99.   // Solve IK
  100.   if(ikblend > 0.0)
  101.   {
  102.  
  103.     Vec3 ikHandlePos = ikHandle.translation();
  104.     Vec3 rootPos = bone0Xfo.tr;
  105.     Scalar distanceToIK = (rootPos - ikHandlePos).length();
  106.  
  107.     // Lock mid to the upVector (pole vector)
  108.     // e.g. could be used to lock an elbow on a table
  109.     if (pin > 0.0)
  110.     {
  111.         Vec3 pinPt = upV.translation();
  112.         scaledBone0Len = Math_linearInterpolate(scaledBone0Len, (pinPt - rootPos).length(), pin);
  113.         scaledBone1Len = Math_linearInterpolate(scaledBone1Len, (pinPt - ikHandlePos).length(), pin);
  114.  
  115.         outBone0Len = scaledBone0Len / rigScale;
  116.         outBone1Len = scaledBone1Len / rigScale;
  117.     }
  118.  
  119.     if (pin != 1.0)
  120.     {
  121.  
  122.       // TODO: Allow scale of zero and the evaluation to finish
  123.       Scalar chainLen = scaledBone0Len + scaledBone1Len;
  124.       if (chainLen == 0) return;
  125.  
  126.       // Slide mid to end (+1) or to start (-1)
  127.       if (slide != 0.0)
  128.       {
  129.         Scalar shift;
  130.         if (slide > 0.0)
  131.           shift = slide * scaledBone1Len;
  132.         else
  133.           shift = slide * scaledBone0Len;
  134.  
  135.         // Update the bone lengths
  136.         scaledBone0Len += shift;
  137.         scaledBone1Len -= shift;
  138.  
  139.         outBone0Len = scaledBone0Len / rigScale;
  140.         outBone1Len = scaledBone1Len / rigScale;
  141.         chainLen = scaledBone0Len + scaledBone1Len;
  142.       }
  143.  
  144.       // Soft IK scale
  145.       Scalar finalRatio = 1.0;
  146.       if (softIK && softRatio > 0.0)
  147.       {
  148.         // For this we drag the IK handle behind after the softDist
  149.         // See: http://www.softimageblog.com/archives/108
  150.         Scalar softLen = softRatio * chainLen;
  151.         Scalar hardLen = chainLen - softLen;
  152.  
  153.         // If we left the hardDistArea we entered the soft area
  154.         if (distanceToIK > hardLen)
  155.         {
  156.           Scalar exponent = -(distanceToIK - hardLen) / softLen;
  157.           Scalar softTargetDistance = softLen * (1 - exp(exponent)) + hardLen;
  158.  
  159.           finalRatio = softTargetDistance / distanceToIK;
  160.  
  161.           if (!stretch || stretchBlend < 1.0)
  162.           {
  163.             // Compute soft IK location for non-stretchy
  164.             Scalar nonStretchyFinalRatio = Math_linearInterpolate(finalRatio, 1.0, stretchBlend);
  165.             Vec3 direction = ikHandlePos - rootPos;
  166.             direction = direction.multiplyScalar(nonStretchyFinalRatio);
  167.             ikHandlePos = rootPos + direction;
  168.             distanceToIK *= nonStretchyFinalRatio;
  169.  
  170.           }
  171.  
  172.           if (stretch && stretchBlend > 0.0)
  173.           {
  174.             // Scale bones by ratio between IK and Soft IK so that we preserve the soft IK
  175.             // motion while hitting the IK handle. See: http://www.softimageblog.com/archives/109
  176.             Scalar stretchyFinalRatio = 1.0 / Math_linearInterpolate(1.0, finalRatio, stretchBlend);
  177.  
  178.             chainLen *= stretchyFinalRatio;
  179.             scaledBone0Len *= stretchyFinalRatio;
  180.             scaledBone1Len *= stretchyFinalRatio;
  181.             outBone0Len *= stretchyFinalRatio;
  182.             outBone1Len *= stretchyFinalRatio;
  183.           }
  184.  
  185.         }
  186.       }
  187.      
  188.       // Stretchy
  189.       if (stretch && stretchBlend > 0.0)
  190.       {
  191.           if (chainLen < distanceToIK)
  192.           {
  193.               Scalar diff = distanceToIK / chainLen;
  194.               diff = Math_linearInterpolate(1.0, diff, stretchBlend);
  195.  
  196.               scaledBone0Len *= diff;
  197.               scaledBone1Len *= diff;
  198.               outBone0Len *= diff;
  199.               outBone1Len *= diff;
  200.           }
  201.  
  202.       }
  203.     }
  204.  
  205.     solve2BoneIK(
  206.       scaledBone0Len,
  207.       scaledBone1Len,
  208.       root.translation(),
  209.       upV.translation(),
  210.       ikHandlePos,
  211.       bone0Xfo,
  212.       bone1Xfo
  213.     );
  214.  
  215.     bone2Xfo = bone1Xfo;
  216.     bone2Xfo.tr = bone1Xfo.transformVector(Vec3(outBone1Len, 0.0, 0.0));
  217.  
  218.     // Set IK  scaling
  219.     bone0Xfo.sc = Vec3(scaledBone0Len / (rigScale * bone0Len), rigScale, rigScale);
  220.     bone1Xfo.sc = Vec3(scaledBone1Len / (rigScale * bone1Len), rigScale, rigScale);
  221.     bone2Xfo.sc = Vec3(rigScale, rigScale, rigScale);
  222.  
  223.   }
  224.  
  225.   // Solve FK
  226.   if (ikblend < 1.0)
  227.   {
  228.     // Project bone2 to the end of bone 1
  229.     Xfo bone2FkXfo = bone1FkXfo;
  230.     bone2FkXfo.tr = bone1FkXfo.transformVector(Vec3(outBone1Len, 0.0, 0.0));
  231.  
  232.     // Set FK scale
  233.     bone0FkXfo.sc = bone0FkXfo.sc.multiplyScalar(rigScale);
  234.     bone1FkXfo.sc = bone1FkXfo.sc.multiplyScalar(rigScale);
  235.     bone2FkXfo.sc = bone2FkXfo.sc.multiplyScalar(rigScale);
  236.  
  237.     // Only FK
  238.     if (ikblend == 0.0)
  239.     {
  240.       bone0Xfo = bone0FkXfo;
  241.       bone1Xfo = bone1FkXfo;
  242.       bone2Xfo = bone2FkXfo;
  243.     }
  244.     // Solve IK/FK blend
  245.     else
  246.     {
  247.       bone0Xfo.ori = bone0FkXfo.ori.sphericalLinearInterpolate(bone0Xfo.ori, ikblend);
  248.       bone0Xfo.sc =  bone0FkXfo.sc.linearInterpolate(bone0Xfo.sc, ikblend);
  249.  
  250.       bone1Xfo.tr =  bone1FkXfo.tr.linearInterpolate(bone1Xfo.tr, ikblend);
  251.       bone1Xfo.ori = bone1FkXfo.ori.sphericalLinearInterpolate(bone1Xfo.ori, ikblend);
  252.       bone1Xfo.sc =  bone1FkXfo.sc.linearInterpolate(bone1Xfo.sc, ikblend);
  253.      
  254.       bone2Xfo.tr =  bone2FkXfo.tr.linearInterpolate(bone2Xfo.tr, ikblend);
  255.       bone2Xfo.ori = bone2FkXfo.ori.sphericalLinearInterpolate(bone2Xfo.ori, ikblend);
  256.       bone2Xfo.sc =  bone2FkXfo.sc.linearInterpolate(bone2Xfo.sc, ikblend);
  257.     }
  258.   }
  259.  
  260.   bone0Out = bone0Xfo.toMat44();
  261.   bone1Out = bone1Xfo.toMat44();
  262.   bone2Out = bone2Xfo.toMat44();
  263.  
  264.   // Set debugging visibility.
  265.   this.setDebug(drawDebug);
  266.   if(this.drawDebug){
  267.  
  268.     Color boneColor(1.0, 1.0, 0);
  269.     etDrawBone(this.handle.rootTransform, 'bone0', bone0Xfo, scaledBone0Len, scaledBone0Len * 0.15, boneColor);
  270.     etDrawBone(this.handle.rootTransform, 'bone1', bone1Xfo, scaledBone1Len, scaledBone1Len * 0.15, boneColor);
  271.   }
  272. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement