Home Technical Talk

Baking Deformations Into A Blendshape - Script

polycounter lvl 12
Offline / Send Message
Pinned
jengy polycounter lvl 12
A wrote a mel script that bakes animations into blendshapes.

What you can do with this:
- Bake skeletal animations into blendshapes
- Bake Ncloth, deformer, and MASH animations into blendshapes
- Combine multiple skin mesh renderers into a single blendshape for Unity and other real-time applications.

I need people to test it so please check it out! We've been using it for effects and optimizing for VR.

There's still some bugs and inefficiencies which is why I need people to test it. 

If you have any questions please feel free to ping me.

How it works:
Select the objects  you want to bake.
Run the script.
It saves a temp file so you don't accidentally overwrite your rig file off in the default projects directory when you run.
A blendshape with the name "blendshape_geo" will be generated which should have a blendshape node attached.

Any feedback would be great!

Here it is:

//Last updated: 3/29/2017
// A script for baking mesh animations into blendshapes.
// Can be used to take skeletal animations and bake them down into in-betweened blendshapes.
// Allows for inbetweens to remain in blendshape for smoother animations.
// Written by J. Gomez and E. Arny

// Renames file to avoid overwriting original file. This saves to the default project in Maya, ovewriting itself as you use it.
file -rename "TEMP_BLENDSHAPE_BAKE.ma"; file -save -type "mayaAscii";

//Checks for and renames old blendshapes
string $attachedBlendshapes[] = `ls -type blendShape`;
int $bsArrayIndex = 0;
string $arraySizeBS = size($attachedBlendshapes);
int $arrayCount = $arraySizeBS;
print $arrayCount;

for ($arrayCount != 1; $arrayCount = 1; $bsArrayIndex++)
    {
        print $attachedBlendshapes[$bsArrayIndex];
        select $attachedBlendshapes[$bsArrayIndex];
        rename blendshape_old_1;
//        $bsArrayIndex++;
        print $bsArrayIndex;
    }

// Setting timeslider to 1
currentTime -edit 1;

// Delcares and sets ints that represent the start and end time slider values, as well as ints I need to reset later. The first couple stay the same; the next two store time values but need to change as frames are generated.                           
int $startFrame = `playbackOptions -q -minTime`;       
int $endFrame = `playbackOptions -q -maxTime`;
int $i = $startFrame;     
int $end = $endFrame;

// Takes the selected object and stores its name in a variable
string $polyName[] = `ls -sl`;                
string $frameName = "frame_1";

// A for loop to repeat the duplicating until the last frame; had to ad one to the arguments to get the last frame to copy. 
for($i; $i < $end + 1 ; $i = $i + 1)          
  {                       
      // Selecting the original object, renaming the currently selected object $frameName, going forward one frame
      select $polyName;                       
      duplicate -rr;
      rename $frameName;                      
      currentTime($i);                        
                  
  };

// Duplicating the first frame for use as the blendshape, and declaring a string that concatanates the name to form the last frame name.
duplicate frame_1;
int $duplicateFrame = $end;                         
$lastFrame = "frame_" + $duplicateFrame;     

// Resetting i to 1 for the first frame of the next for loop, then resetting the time to 1 for the loop.
$i = $startFrame;                                             
currentTime -edit $i;                               

// A for loop for selecting all of the generated frames. 
global proc SelectMeshFrames(int $i, string $frameName, int $end) 
{
  for($i; $i < $end + 1 ; $i = $i + 1)                
  {                         
      $frameName = "frame_" + $i;         
      select -add $frameName;
      currentTime($i);          
    };

}
    
// Setting the $frameName string to be frame_$i, Adds the duplicated first frame mesh to the selection
$frameName = "frame_" + $i;                         
select -add $frameName;                             

// Adding the blendshape node to the duplicated first frame, then clearing selection.
blendShape -tc 0 -ib -n "blendshape_01";                   
select -clear;

// Selecting the duplicated first frame mesh, then renaming the duplicated first frame mesh to a generic name, "blendshape_geo", then clearing selection.
select $frameName;                                
rename $frameName blendshape_geo;                    
select -clear;

// Resetting i to 1 for the first frame of the next for loop,  setting time to 1 for the for loop, then renaming the mesh.
$i = $startFrame;                                             
currentTime -edit $i;                              
$frameName = "frame_" + $i;

// Selecting all generated frames for deletion
SelectMeshFrames($startFrame + 1, "blendshape_geo", $endFrame + 1); 
delete;

//Trying to automatically select blendshape node and create a linear animation curve between $startFrame and $endFrame for easy export. 
//select -add blendshape_geo;

//Getting name together
//string $blendshapeName = "blendshape" + "_" + $endFrame;
//string $blendshapeProperty = "." + "frame" + "_" + $end;
//print $blendshapeName;
//print $blendshapeProperty;
Sign In or Register to comment.