Thursday, June 12, 2014

Tool idea to reuse blendshapes after few topology changes II


Here's the current version of the script i wrote in MEL.  Its still a work in progress so I would suggest testing it on a test scene before any attempt at using it in production.  Also there is no gui for the tool.

What is it for?

Say weve got lots of blendshapes in Maya made already and then we made some topology changes from the "old topology mesh" creating a "new topology mesh", this tool is one way to try to get all those blendshapes recreated using the new topology mesh.

To use it,
--source the MEL script,

--have a copy of the "old topology default mesh" This is the default mesh used to create the already made blendshapes.

--have a copy of the "new topology mesh" in its default pose.

Now select all the already made blendshape polygon meshes,
then type in MEL script editor:

facerigMakeSelSectionIntoFullBlendshape("PUT NAME new topology mesh", " PUT NAME old topology default mesh" )

(remove any unnessary base nodes tool made  .. select "*Base" or something like that should be able to quickly remove them)

Now should have copies of all the old blendshapes but using the new topology.  Notice may have some weird looking shapes especially for areas with major topology differences that would need to be corrected.
(ex: on the left is the tool created blendshape , on the right is the old blendshape )

Here it is:
Modify at your own risk.
// updated 03-11-2014 nate ----- making wrap mechanism more robust, added multiple shape support
// updated 05-27-2012 nate ----- initial commit

//requires sections selected on scene, input is full shape, and the overlapping section shape. assumes section does not have blendshapes. if shape look off change wrap options max dist to 0.01
global proc facerigMakeSelSectionIntoFullBlendshape(string $full, string $section )
    string $full, $section;
    string $sectionShapesArray[] = {};
    string $sectionShapes = "";
    //$section =  "polySurface217";
    //$full =  "polySurface216";
    //$sectionShapes = {"lt_browLowerer","lt_innerBrowRaiser","lt_outerBrowRaiser"};
    $sectionShapesArray = `ls -sl`;

    if(size($sectionShapesArray) == 0){error("First Select half sculpted blendshape(s) !!!.  \nDefault section should NOT be deformed !!! \n");}
    string $wrapName = "";
    for( $sectionShapes in $sectionShapesArray ){     
        //section should move full face
        select -cl;
        select -r $full;
        select -add $section;
        string $fullShapeArray[] = {};
        $fullShapeArray = `pickWalk -direction down $full`;
        select -cl;
        string $fullShape = $fullShapeArray[0];//would bug out if multiple child shapes
        string $wrapNameArray[] = {};
        $wrapNameArray = stringArrayRemoveDuplicates( `listConnections -source true -type wrap ($fullShape)` );
        if(size($wrapNameArray) != 1){error("Error Wrapping Geometry !!!:"+$sectionShapes);}
        string $wrapName = $wrapNameArray[0];
        //deformer -type wrap $full; //there is some maya bug using this
        //so we're not affecting mirrored side
        setAttr ($wrapName+"."+"maxDistance") 0.01; //make smaller so section moves smaller area of full head
        //setAttr ($wrapName+"."+"inflType") 2; //make points since verts should overlap ... i think need api to do this
        //make shapes moving section
        select -r $sectionShapes;
        select -add $section;
        //$blendName = "tmp_bnd";
        string $blendNameAr[] = `blendShape`; //make sure blendnode not on scene
        $blendName = $blendNameAr[0];
        //---make section moving full face, section needs to be at default
        setAttr ($blendName+"."+$sectionShapes) 0;
        //select -r polySurface216 ; 
        //select -add polySurface217 ;
        //deformer -type wrap polySurface216;
        //--get our full faces
        string $resultShapeName = $sectionShapes+"_full";
        setAttr ($blendName+"."+$sectionShapes) 0;//first reset all shapes
        setAttr ($blendName+"."+$sectionShapes) 1.0;
        duplicate -n $resultShapeName -rr $full;

        setAttr ($blendName+"."+$sectionShapes) 0;//put back to default
        delete -ch $full;//clean history
        delete -ch $section;//clean history
        delete(`pointConstraint -offset 0 0 0 -weight 1 $sectionShapes $resultShapeName`); //clean position of created shape 
    }//end looping over all selected shapes

Hope this is helpful,