Jacob's Blog Buttons (custom HTML)

portfolio
animation
character
digital art

Friday, August 23, 2013

Joint Skeleton-mover Script

You can temporarily download it here until I get it on Creative Crash.
Or click Read More to show the full script at the bottom of the post.

This is a script I started late last year, and I've recently come back and cleaned it up.  It allows you to grab the root joint of a joint chain to rotate and move it relative to the origin.  It creates a locator on your joint, bakes the animation onto that, and then allows you to interact with a shape on the origin to play with your joint chain.  After deleting, it bakes it all back onto the root joint.  Though it's fairly simple, and not entirely original, it has been one of my most-used scripts for exported joint chains (and also mocap cleanup).


It's pretty straightforward; you run the JHH_skeletonMover script to create or delete the skeleton mover.  It will intelligently put it on the object selected, then delete it off when you're done.  There's also a JHH_skeletonMover_originOffset procedure which will center the joint onto the origin; good for zeroing out your animation.  I'll be making a video pretty soon, but feel free to ask if you have questions.

I'll probably rewrite this in Python at some point, just to get some practice in.





// JHH_skeletonMover
//   written by Jacob Hemphill, December 2012
//  version 1.2.01
//
// JHH_skeletonMover will create a cube at the origin that can be used to adjust the position and rotation of a joint chain.
// Select an object and source the script; it can be run by JHH_skeletonMover() to both create and delete the script.

// ==========================================================================================
// === JHH_skeletonMover
// Directs the script by creating or deleting the skeletonMover, if it has already been created
// Checks selected object for keys, if not, tries to default to Root or Hips, before erroring out.
// ------------------------------------------------------------------------------------------
// Parameters: none
// Returns: none
// ==========================================================================================
global proc JHH_skeletonMover ()
{
 if(!objExists ("skeletonMover_OriginControl")){
  // doesn't exist, try to create the object (handle the input based on selection)
  string $selected_obj_array[] = `ls -selection`;
  if(size($selected_obj_array) >= 1 && `keyframe -q -kc`){
   print ("from JHH_skeletonMover: Building mover on "+$selected_obj_array[0]+" object.\n");
   JHH_skeletonMover_build($selected_obj_array[0]);
  }
  else if (size($selected_obj_array) >= 1 && !`keyframe -q -kc`){
   error ("from JHH_skeletonMover: Selected object (" + $selected_obj_array[0] + ") has no keys!");
  }
  else {
   error "from JHH_skeletonMover: No object selected.\n";
  }
 }
 else {
  string $constraint_parent[] = `listRelatives -p skeletonMover_pointConstraint`;
  JHH_skeletonMover_delete($constraint_parent[0]);
  print ("from JHH_skeletonMover: Deleting mover found on "+$constraint_parent[0]+" object.\n");
 }
}



// ==========================================================================================
// === JHH_skeletonMover_build
// Is the thing that builds the objects and connects it to the skeleton
// ------------------------------------------------------------------------------------------
// Parameters:
//  $root_joints:  The name of the root joint
// Returns: none
// ==========================================================================================
global proc JHH_skeletonMover_build (string $root_joint)
{ 
  // Save current frame number
  $current_time = `currentTime -q`;

  // Do clean-up, just in case.
  if(objExists ("skeletonMover_pointConstraint")) delete skeletonMover_pointConstraint;
  if(objExists ("skeletonMover_orientConstraint")) delete skeletonMover_orientConstraint;
  if(objExists ("skeletonMover_JointLoc")) delete skeletonMover_JointLoc;
  
  // Create the nurbsCube at the origin and lock the scale controls
  //sphere -p 0 0 0 -ax 0 1 0 -ssw 0 -esw 360 -r 10 -d 3 -ut 0 -tol 0.01 -s 8 -nsp 4 -ch 1 -n skeletonMover_OriginControl;
  polyCube -w 12 -h 12 -d 12 -sx 1 -sy 1 -sz 1 -ax 0 1 0 -cuv 4 -ch 1 -n skeletonMover_OriginControl;
  setAttr -lock 1 "skeletonMover_OriginControl.sx";
  setAttr -lock 1 "skeletonMover_OriginControl.sy";
  setAttr -lock 1 "skeletonMover_OriginControl.sz";

  // Create a locator and set it to a resonable visible size
  spaceLocator -p 0 0 0 -n skeletonMover_JointLoc;
  setAttr "skeletonMover_JointLoc.localScaleZ" 10;
  setAttr "skeletonMover_JointLoc.localScaleX" 10;
  setAttr "skeletonMover_JointLoc.localScaleY" 10;

  // Parent the locator to the origin control
  select -r skeletonMover_JointLoc skeletonMover_OriginControl ;
  parent;
  
  // Point and orient constrain the locator to the hips so you can bake animation
  pointConstraint -weight 1 -n skeletonMover_pointConstraint_temp $root_joint skeletonMover_JointLoc ;
  orientConstraint -weight 1 -n skeletonMover_orientConstraint_temp $root_joint skeletonMover_JointLoc ;

  // Bake animation onto the locator (do from channel box to only get translates and rotates
  int $time_range_start = `findKeyframe -which first $root_joint`;
  int $time_range_end = `findKeyframe -which last $root_joint`;
  $time_range = $time_range_start+":"+$time_range_end;

  currentTime 1 ;
  bakeResults -simulation true -t $time_range -sampleBy 1 -disableImplicitControl true -preserveOutsideKeys true -sparseAnimCurveBake false -removeBakedAttributeFromLayer false -bakeOnOverrideLayer false -minimizeRotation true -at "tx" -at "ty" -at "tz" -at "rx" -at "ry" -at "rz" skeletonMover_JointLoc;
  
  // Delete keys off of the hips (since it's now on the locator)
  cutKey -clear -time $time_range -hierarchy none -controlPoints 0 -shape 1 {$root_joint};
  
  // Delete the constraints off of the locator and constrain it in the other direction
  delete skeletonMover_pointConstraint_temp;
  delete skeletonMover_orientConstraint_temp;
  pointConstraint -weight 1 -n skeletonMover_pointConstraint skeletonMover_JointLoc $root_joint ;
  orientConstraint -weight 1 -n skeletonMover_orientConstraint skeletonMover_JointLoc $root_joint;
  
  // Select the origin control
  select -r skeletonMover_OriginControl;
  
  // Go back to saved time
  currentTime $current_time;
}


// ==========================================================================================
// === JHH_skeletonMover_delete
// Will re-bake the keys onto the hips and then remove all of the objects created by the script.
// ------------------------------------------------------------------------------------------
// Parameters:
//  $root_joints:  The name of the root joint
// Returns: none
// ==========================================================================================
global proc JHH_skeletonMover_delete (string $root_joint)
{
 // Save current frame number
  $current_time = `currentTime -q`;
  
 // Bake simulation from the locator onto the hips
 int $time_range_start = `findKeyframe -which first skeletonMover_JointLoc`;
 int $time_range_end = `findKeyframe -which last skeletonMover_JointLoc`;
 $time_range = $time_range_start+":"+$time_range_end;
 
 currentTime 1 ;
 bakeResults -simulation true -t $time_range -sampleBy 1 -disableImplicitControl true -preserveOutsideKeys true -sparseAnimCurveBake false -removeBakedAttributeFromLayer false -bakeOnOverrideLayer false -minimizeRotation true -at "tx" -at "ty" -at "tz" -at "rx" -at "ry" -at "rz" $root_joint ;
 
 // Delete the sphere, locator, and constraints 
 delete skeletonMover_pointConstraint;
 delete skeletonMover_orientConstraint;
 delete skeletonMover_JointLoc;
 delete skeletonMover_OriginControl;
 
 select -cl;
 
 // Go back to saved time
  currentTime $current_time;
}


// ==========================================================================================
// === JHH_skeletonMover_zero
// Looks at the hips locator and adjusts the origin-control to offset and put the hips at tx 0 and tz 0
// Best done on a fresh build, as it may not work as intended with an already-rotated origin.
// ------------------------------------------------------------------------------------------
// Parameters: none
// Returns: none
// ==========================================================================================
global proc JHH_skeletonMover_originOffset ()
{
    if(objExists ("skeletonMover_JointLoc")){
  setAttr "skeletonMover_OriginControl.tx" (-(`getAttr ("skeletonMover_JointLoc.tx")`)); 
  setAttr "skeletonMover_OriginControl.tz" (-(`getAttr ("skeletonMover_JointLoc.tz")`));
 }
 else{
  error "No skeletonMover detected";
 }
}

No comments:

Post a Comment