Thursday, September 25, 2008

IK/FK Switch

This first script is incredibly helpful in animation. It's a script that will allow for IK/FK switching on a character rig with a single skeleton. This switch works without popping, or any other wonky, unwanted movement. It also keeps your rig clean without having to set up 3 skeletons that drive each other and make for a very confusing rig.
I based this script off of one I found online written by Lionel Gallant, but I modified it pretty heavily to work on my own, procedurally generated rig. I'm only including the arms to save some space, but it does work for legs as well, or anything else the animator would need it for with a little bit of tweaking.



// ==============================================================
// Turn arm IK on or off while preserving the arm orientation.
// ==============================================================
// This script will switch between IK and FK states on the arms
// and legs without any popping in the animation.
// Based on a script originally written by Lionel Gallat.

global proc IkFk_switch( string $side, string $limb )
{
string $rigName = getSelectedRigName();
string $rigSideName = ($rigName + ":" + $side);

string $currentSelection[] = `ls -sl`;

// Check to see if anything is keyed in the arm, and if so, set the flag.
int $keyWhenSwitching = 0;

// Declaring arm variables.
float $keysOnShoulder[] = `keyframe -q ($rigSideName + "Shoulder")`;
float $keysOnShoulderControl[] = `keyframe -q ($rigSideName + "ShoulderControl")`;
float $keysOnElbow[] = `keyframe -q ($rigSideName + "Elbow")`;
float $keysOnElbowControl[] = `keyframe -q ($rigSideName + "ElbowControl")`;
float $keysOnArmIk[] = `keyframe -q ($rigSideName + "ArmIKControl")`;
float $keysOnArmPole[] = `keyframe -q ($rigSideName + "armPV")`;
float $keysOnShoulderConstraint[] = `keyframe -q ($rigSideName + "Shoulder_orientConstraint1")`;
float $keysOnElbowConstraint[] = `keyframe -q ($rigSideName + "Elbow_orientConstraint1")`;


if ( `size $keysOnShoulder` != 0 ||
`size $keysOnElbow` != 0 ||
`size $keysOnArmIk` != 0 ||
`size $keysOnArmPole` != 0 ||
`size $keysOnShoulderControl` != 0 ||
`size $keysOnElbowControl` != 0 ||
`size $keysOnShoulderConstraint` != 0 ||
`size $keysOnElbowConstraint` != 0 )

{
$keyWhenSwitching = 1;
}
// ----------------
// Turn arm IK off.
// ----------------

if ( $limb == "arm" )
{
if ( `getAttr ( $rigSideName + "ArmIKControl.enableIk")` == 1 )
{
// Get current arm joints rotation info.
vector $shoulderRot = `xform -q -r -ro ($rigSideName + "Shoulder")`;
vector $elbowRot = `xform -q -r -ro ($rigSideName + "Elbow")`;
vector $shoulderLoc = `xform -q -r -ro ($rigSideName + "ShoulderLoc")`;
vector $elbowLoc = `xform -q -r -ro ($rigSideName + "ElbowLoc")`;

// Disable the IK solver (if there are keys on the joints, the arm will pop back to those).
setAttr ($rigSideName + "ArmIKControl.enableIk") 0;

// Match the joints rotations.
setAttr ($rigSideName + "Shoulder.rx") ($shoulderRot.x);
setAttr ($rigSideName + "Shoulder.ry") ($shoulderRot.y);
setAttr ($rigSideName + "Shoulder.rz") ($shoulderRot.z);
setAttr ($rigSideName + "Elbow.ry") ($elbowRot.y);
setAttr ($rigSideName + "ShoulderControl.rx") ($shoulderLoc.x);
setAttr ($rigSideName + "ShoulderControl.ry") ($shoulderLoc.y);
setAttr ($rigSideName + "ShoulderControl.rz") ($shoulderLoc.z);
setAttr ($rigSideName + "ElbowControl.ry") ($elbowLoc.y);

// Make the controls visible again, and enable the constraints.
setAttr ($rigSideName + "ShoulderControl.visibility") 1;
setAttr ($rigSideName + "ElbowControl.visibility") 1;
setAttr ($rigSideName + "Shoulder_orientConstraint1." + $side + "ShoulderControlW0" ) 1;
setAttr ($rigSideName + "Elbow_orientConstraint1." + $side + "ElbowControlW0" ) 1;

// If there are keys anywhere on the arm, then key the shoulder and elbow, and then delete the constraint.
if ( $keyWhenSwitching )
{
setKeyframe -breakdown 0 -hierarchy none -controlPoints 0 -shape 1 ($rigSideName + "ShoulderControl");
setKeyframe -breakdown 0 -hierarchy none -controlPoints 0 -shape 1 ($rigSideName + "Shoulder");
setKeyframe -breakdown 0 -hierarchy none -controlPoints 0 -shape 1 ($rigSideName + "ElbowControl");
setKeyframe -breakdown 0 -hierarchy none -controlPoints 0 -shape 1 ($rigSideName + "Elbow");
setKeyframe -breakdown 0 -hierarchy none -controlPoints 0 -shape 1 ($rigSideName + "ArmIKControl");
setKeyframe -breakdown 0 -hierarchy none -controlPoints 0 -shape 1 ($rigSideName + "armPV");
setKeyframe -breakdown 0 -hierarchy none -controlPoints 0 -shape 1 ($rigSideName + "Shoulder_orientConstraint1");
setKeyframe -breakdown 0 -hierarchy none -controlPoints 0 -shape 1 ($rigSideName + "Elbow_orientConstraint1");
}
}

// ---------------
// Turn arm IK on.
// ---------------
else
{
// Move the IK control to the current position of the wrist.
pointConstraint -w 1 -o 0 0 0 ($rigSideName + "Wrist") ($rigSideName + "ArmIKControl");

// If there are keys anywhere on the arm, then key the armIk and delete the constraint.
if ( $keyWhenSwitching )
{
setKeyframe -breakdown 0 -hierarchy none -controlPoints 0 -shape 1 ($rigSideName + "ArmIKControl");
}
delete ($rigSideName + "ArmIKControl_pointConstraint1");

// Move the pole vector where it should be to match the arm angle.
pointConstraint -w 1 -o 0 0 0 ($rigSideName + "armLoc") ($rigSideName + "armPV");

// If there are keys anywhere on the arm, then key the armPole and delete the constraint.
if ( $keyWhenSwitching )
{
setKeyframe -breakdown 0 -hierarchy none -controlPoints 0 -shape 1 ($rigSideName + "armPV");
}
delete ($rigSideName + "armPV_pointConstraint1");

// Bring the IKHandle to the control point.
pointConstraint -w 1 -o 0 0 0 ($rigSideName + "ArmIKControl") ($rigSideName + "armIKHandle");
delete ($rigSideName + "armIKHandle_pointConstraint1");

// Set the constraint weights to zero.
setAttr ($rigSideName + "Shoulder_orientConstraint1." + $side + "ShoulderControlW0" ) 0;
setAttr ($rigSideName + "Elbow_orientConstraint1." + $side + "ElbowControlW0" ) 0;


// Turn the Visibility of the FK controls off.
setAttr ($rigSideName + "ShoulderControl.visibility") 0;
setAttr ($rigSideName + "ElbowControl.visibility") 0;

// Enable the IK solver.
setAttr ($rigSideName + "ArmIKControl.enableIk") 1;

// If there are keys anywhere on the arm, then key the shoulder and elbow, and then delete the constraint.
if ( $keyWhenSwitching )
{
setKeyframe -breakdown 0 -hierarchy none -controlPoints 0 -shape 1 ($rigSideName + "ShoulderControl");
setKeyframe -breakdown 0 -hierarchy none -controlPoints 0 -shape 1 ($rigSideName + "Shoulder");
setKeyframe -breakdown 0 -hierarchy none -controlPoints 0 -shape 1 ($rigSideName + "ElbowControl");
setKeyframe -breakdown 0 -hierarchy none -controlPoints 0 -shape 1 ($rigSideName + "Elbow");
setKeyframe -breakdown 0 -hierarchy none -controlPoints 0 -shape 1 ($rigSideName + "ArmIKControl");
setKeyframe -breakdown 0 -hierarchy none -controlPoints 0 -shape 1 ($rigSideName + "armPV");
setKeyframe -breakdown 0 -hierarchy none -controlPoints 0 -shape 1 ($rigSideName + "Shoulder_orientConstraint1");
setKeyframe -breakdown 0 -hierarchy none -controlPoints 0 -shape 1 ($rigSideName + "Elbow_orientConstraint1");
}
}
}
}

0 Comments:

Post a Comment

Subscribe to Post Comments [Atom]



<< Home