Friday, February 7, 2014

Quick Script for making an ikSpline rig along selected curves

So  a friend of mine posted a question/request about needing a script to make joint chains on hair curves and then applying some sort of joint ikSpline rig to those curves, and then binding that to the respective geo.

 I was bored. Saw his post and said, sure,  why not.  I write this kind of stuff all the time, so why not expand a little and share.



So here is what I wrote, with over commenting.  

 maybe it will help someone, or they can get a laugh out of it as it is written in mel.

The use of this is based on a selection of curves, and those curves have matching geo with the suffix "GEO"
  It creates a joint chain of 10 joints and scales them to match the length of the selected curves, and then uses that curve as an ikSpline handle, and then does a simple bind of the joints to the geo.

The idea being that your geo is just named the same as the curve, plus GEO.
ie: "curve178' has  a corresponding geo named "curve178GEO"  To be fair, its not often we have this scenario where curves and geo match each other, but that's what cometRename is for.. and I do this a lot,  I know I don't want that geo named anything like that, but I'll temporarily name it that way to make the script slightly easier, and then after the fact I'll just name them back to something better. ( if it matters)

also, I didn't do any nice naming of anything in this script, its all whatever Maya wants to name it.. Generally I don't do that either. I give everything matching names that make sense and make it easy to find relationships later. ( visually / mentally ) . Naming nodes is really just to help us humans.    Cause really , it doesn't matter what anything is named , you can always follow the connections.( but clashing names are always bad, for humans and computers) .

//--------------------------------------------------
global proc curveJointRig ()
{
string $crvs[] = `ls -sl`;
select -cl;
// create GOD group
string $grp = `group -em -n "GOD"`;
select -cl;
for ($crv in $crvs)
    {
    // arclen creates a node called curveInfo and connects it to the given curve.   
    // the main use here is to get the length of the curve to figure out how long the joints 
    // should be, and to then use that to drive their stretch  
    //  for more info   `help -doc arclen`;
    string $cInfo = `arclen -ch -1 $crv`;
    float $dis = `getAttr ($cInfo + ".arcLength")`;
 
    float $jlen = ($dis / 10);
    string $jnts[];
    clear $jnts;
    int $i = 0;
    while ($i <= 10)
        {
        // the joint command makes joint.. in this case I'm just putting them at 0 1 2 3 
        // as I don't know yet what length i want them to be.   for more info `help -doc joint`;
        string $jnt = `joint -p $i 0 0 `;
        $jnts[`size$jnts`] = $jnt;
        int $n = `size$jnts`;
        print ($jnt + "  " + $jnts[$n -1] + " /n");
        // I used catch here as I don't really care if it works or not, 
        //when making joints if the joint stays  selected while you create the next joint, 
       // it will automatically parent correctly also, I'm not doing any rotation axis settings here,, 
        // for more info `help -doc catch`;
        catch (`parent $jnt $jnts[$n -2]`);
        $i++;
        setAttr ($jnt + ".tx") $jlen;
        }
    // make ikSpline handle    for more info `help -doc ikHandle`;
    ikHandle -sol ikSplineSolver -sj $jnts[0] -ee $jnts[(`size $jnts` -1)] -ccv false -pcv false -curve $crv;  
 
    // do some stretch rigging   yadda yadda yadda  joints on chain, scale with curve as it gets
    // longer and shorter based on the arclength dividing the original length of the curve and the     //current length, which is then plugged into the scaleX of the joints
    //( did not do any twist rigging here) this is a pretty standard practice. 
    // operation sets how the mult div works, 1 =mult, 2 = divide, 3= pow
    string $multA = `createNode multiplyDivide`;
    setAttr ($multA + ".operation") 2;
    connectAttr ($cInfo +".arcLength") ($multA + ".input1X");
    setAttr ($multA + ".input2X") $dis;
    string $multB = `createNode multiplyDivide`;
    setAttr ($multB + ".operation") 2;
    connectAttr ($multA + ".outputX") ($multB + ".input1X");
        for ($jnt in $jnts)
        {
        connectAttr ($multB + ".outputX") ($jnt + ".sx");
        }
     
     // some clean up  This is just grouping, and plugging the scaleX of the main group
     //  into the secondary mult that will keep things from exploding.
     // that only works if you parent the joints under the group as well.
    // this curve has no rig on it, so I put that in there as well, but normally I want put joints
    // on it, or clusters and those would go in the group, and not the curve
     parent $jnts[0] $grp;
     parent $crv  $grp ;
     connectAttr ($grp + ".sx") ($multB + ".input2X" );
      select -cl;


     // bind?  ( I really did the least amount of scripting possible here.. but it should give 
    // a base to start with     for more info use `help -doc skinCluster`;
     skinCluster -dr 7.5 -tsb $jnts ($crv + "GEO");


     select -cl;
     print ("finished " + $crv + " \n");
    }
     
}

//-----------------------------------------------------


here is just the node graph of the curveInfo to the multDiv to the joints .




well, anyway, I hope that helps someone.. or gives them a laugh. .

 -=s





No comments:

Post a Comment