Bake Custom Geo at 360 degrees for 3 seconds...
...and you get fully working custom facial geo with no wrap deformers to slow things down. As you might have guessed, the custom facial geo baker is complete. So now you can...
The short of it:
- Import your new beard/gotee whatever
- Position it where you want it in relation to a ZEROED out Morphy face
- Select your custom mesh, then his face mesh
- Source and run script
- Go grab some candy. Preferably dark chocolate.
- Come back and animate.
For those of you interested, here's how I go about tackling things like that. First I figure out what I want the script to do. Here's my original "plan" notes:
- Process to be scripted
- Select $customGeo followed by deformingMesh
- Create wrapDeformer
- Get blendshape channels into array
- For loop
- for each blendshape channel on the deforming mesh (limit by facial region?)
- Get input connector value and put in $driverArray
- Break the connection on the blendshapeChannel
- turn channel value to 1
- duplicate $customGeo to freeze it
- Add new geo name to $bakedCustomGeo string array
- position new geo
- reconnect the connecter value with data from $driverArray
- Put all new blendshape geo in new group
- Name group
- Connect all new geo back into original geo as blendshape node ($customGeoBaseName_bsNode)
Also, thanks to my buddy David Bokser who helped me out with a syntax issue I was getting stuck on last night.
/*
TITLE: jbMorpheusFacialCustomGeoBaker
VERSION: 1.0
AUTHOR:Josh Burton
www.joshburton.com
DATE: August 26, 2010
DESCRIPTION:
Script for baking out custom facial geo for the Morpheus Rig.
DISCLAIMER:
If your computer explodes, I didn't do it.
HOW TO USE:
1. First select the custom geo to bake
2. Then select the head (to wrap it to)
3. Run script
HISTORY:
08.26.10 - BIRTH!
Acknowledgements -
1. Blendshape extraction, size, existance checking from extractBlendShapes - Asi Sudai
asi@asimation.com www.reel.asimation.com
2. David Bokser for helping me fix some of my syntax issues
*/
//sub Procs
// Debuging printing proc - Acknowledgement 1
proc extractBlendShape.debug(string $msg)
{
if (1==1)
print ("\n***Debug: " + $msg +"\n");
}// End
// Get object bounding size - Acknowledgement 1
proc extractBlendShape.getBounding(string $node)
{
float $bounding[]=`xform -q -bb $node`;
float $xSize=(`abs $bounding[0]` +`abs $bounding[3]`);
print $xSize;
}// End
// check the object have blendShapes - Acknowledgement 1
proc string extractBlendShape.getBlendShape(string $node)
{
string $shapes[] = `listRelatives -s $node`;
for ($shape in $shapes){
string $tempArray[]=`listConnections -s 1 -d 0 -type "blendShape" ($shape + ".inMesh")`;
if ($tempArray[0] != "") return $tempArray[0];
}
return "none";
}// End
//Main Proc
global proc jbMorpheusFacialCustomGeoBaker() {
//Declaring our intial variables
string $blendShapeNamesBaked[];
string $blendshapeConnections[];
string $currentConnections[];
string $selected[] = `ls -sl`;
//Josh, do an error check to make sure the selection order is correct
$customGeo = $selected[0];
$deformerGeo = $selected[1];
//create and store name of Wrap deformer
string $wrapDeformer[] = `deformer -type wrap $customGeo`;
select -r $customGeo;
select -tgl $deformerGeo;
AddWrapInfluence;
select -cl;
//reorders deformation order for proper baking of skinned mesh
reorderDeformers "tweak1" "face_skinCluster" $deformerGeo;
// Check if object have blendShape node. - Acknowledgement 1
string $blendShapeNode = `extractBlendShape.getBlendShape $deformerGeo`;
if ($blendShapeNode == "none") { print ("\n"+ $deformerGeo + " don't have blendShape"); return; }
// Get all BlendShapes shapes - Acknowledgement 1
extractBlendShape.debug $blendShapeNode;
string $blendShapeNamesShort[] = `listAttr -m ($blendShapeNode + ".weight")`;
int $n = 0;
//Creates a new name for the geo to be baked
for ($name in $blendShapeNamesShort) {
$blendShapeNamesBaked[$n] = $customGeo + "_" + $blendShapeNamesShort[$n];
$n++;
}
// Start extracting
// Get object size, to better spread the blendShapes - Acknowledgement 1
float $bounding[]=`xform -q -bb $customGeo`;
float $boundingSizeX=(`abs $bounding[0]` +`abs $bounding[3]`);
float $boundingSizeY=(`abs $bounding[1]` +`abs $bounding[4]`);
extractBlendShape.debug ("Bounding size = " + $boundingSizeX);
// Start extracting each shape - Acknowledgement 1, changed to export the custom geo instead of the deforming Geo
int $t=1;
string $bakedCustomGeo[];
for ($i=0; $i<`size($blendShapeNamesShort)`; $i++) { int $row = `floor($i/5)`; if ($t>5) $t=1;
extractBlendShape.debug ("doing blendShape - " + $blendShapeNamesShort[$i]);
//queries the connection that goes into the blendshape node and stores it
string $currentBlendShapeChannel = $blendShapeNode + "." + $blendShapeNamesShort[$i];
$currentConnections = `listConnections -d off -p on -s on $currentBlendShapeChannel`;
$blendshapeConnections[$i] = $currentConnections[0];
//breaks connection on blendshape node
disconnectAttr $blendshapeConnections[$i] ($blendShapeNode + "." + $blendShapeNamesShort[$i] ) ;
//back to Asi's code
setAttr ($blendShapeNode + "." + $blendShapeNamesShort[$i] ) 1;
string $bakedCustomGeo[]=`duplicate -name $blendShapeNamesBaked[$i] $customGeo`;
xform -r -t (($boundingSizeX*($t+1.2))*1.1) (($boundingSizeY*$row)*-1) 0 $bakedCustomGeo[0];
setAttr ($blendShapeNode + "." + $blendShapeNamesShort[$i] ) 0;
// Restores connection
connectAttr $blendshapeConnections[$i] $currentBlendShapeChannel;
$t++;
}
//Restores deformation order of the Deformer Geo
reorderDeformers "face_skinCluster" "tweak1" $deformerGeo;
reorderDeformers "face_skinCluster" "face_bsNode" $deformerGeo;
//Delete wrap and connect baked custom geo as blendshapes to original custom geo
delete $wrapDeformer[0];
$customGeoBlendShapeNode = $customGeo+"_bsNode";
blendShape -n $customGeoBlendShapeNode $blendShapeNamesBaked $customGeo ;
//groups our new baked geo for easy cleanup later on
$bakedCustomGeoGroupName = $customGeo+"_bsGeo_grp";
group -n $bakedCustomGeoGroupName $blendShapeNamesBaked;
setAttr ($bakedCustomGeoGroupName +".v") 0;
parent $bakedCustomGeoGroupName customFacialGeo_bsGeo_grp;
//Connects our custom geo blendshape channels to the original deforming mesh channels
int $b=0;
for ($bshape in $blendShapeNamesBaked) {
connectAttr ($blendShapeNode + "." + $blendShapeNamesShort[$b]) ($customGeoBlendShapeNode +"."+ $blendShapeNamesBaked[$b]);
$b++;
}
//Skin the custom geo
$customGeoSkinName = $customGeo+"_skinCluster";
skinCluster -n $customGeoSkinName -tsb qssFaceSkinJoints $customGeo;
//copy the skin weights from the deformer geo to the custom geo
copySkinWeights -ds $customGeoSkinName -ss "face_skinCluster" -noMirror -surfaceAssociation closestPoint -influenceAssociation name;
//renames our original custom geo properly
$customGeoProperName = $customGeo+"_customGeo";
rename $customGeo $customGeoProperName;
//Report complete
print ($customGeoProperName + " exported properly. I'd move the joysticks around to make sure.") ;
}
- Been doing some polishing on some of the blendshapes for the rig and deformation
- Pushed Nose widener more at a beta tester's request
- Bug fix - eyebrow mover rotation is now properly mirrored
- Moved out the jaw_anim control so it wouldn't get stuck behind beards
- Moved the hair over to using skinning rather than wrap deformers









