Friday, February 3, 2012

MEL Script -"Unfreezing" Transformations

Someone on CGTalk had 100+ objects in their scene where the transformations had been reset.  He needed their world space positions restored.  Plainly speaking, he needed to unfreeze transformations.  Technically that isn't possible, but there's a way to cheat everything.

There's probably a more efficient way to do this.  If someone reply's to my post on CGTalk with a better version, I'll post their version, credit them, and provide a link to their post.  In any case, here's the "Unfreeze Transformations" script.  I hope it helps someone.


//Get all of the selected items, and the size of the selection
string $selection[] = `ls -sl`;
int $size = size($selection);
int $i;
//for each object in the selection, do the following things:
for ($i = 0; $i < size($selection); $i++){
     //Create two locators.  #1 stays at the origin (0 0 0) while #2 moves to the center of the selected object.
     string $zeroLoc[] = `spaceLocator`;
     string $loc[] = `spaceLocator`;
     string $ptCon[] = `pointConstraint $selection[$i] $loc`;
     string $orCon[] = `orientConstraint $selection[$i] $loc`;
   
     //Get the translation and rotation values of the locator we just moved.  These are the values that we'll give to the object in a few steps.
     float $tran[] = `xform -q -t -ws $loc`;
     float $rot[] = `xform -q -ro -ws $loc`;
   
     //Delete the constraints, we don't need them anymore
     delete $ptCon;
     delete $orCon;
   
     //Move the selected object to the 0 0 0 locator (that's at the origin), then delete the constraints.
     string $ptConZero[] = `pointConstraint $zeroLoc $selection[$i]`;
     string $orConZero[] = `orientConstraint $zeroLoc $selection[$i]`;
     delete $ptConZero;
     delete $orConZero;
     //Freeze Transformations on the object.  Now the objects values are zeroed out and it's at the origin  
     makeIdentity -apply true -t 1 -r 1 $selection[$i];
   
     //Move the object back to it's original position, using the translation/rotation values from the first locator we created and moved.
     setAttr ($selection[$i] + ".translate") $tran[0] $tran[1] $tran[2];
     setAttr ($selection[$i] + ".rotate") $rot[0] $rot[1] $rot[2];
   
     //Delete the two locators we created, we don't need them anymore.
     delete $zeroLoc;
     delete $loc;
}

3 comments:

  1. Nice. I've written one of these myself. Now convert it to python :)

    ReplyDelete
  2. Hey so I took another stab at this script today. I think I've built is about 10 different ways of the years and I continue to lose them. Anyway, I've done it in about 8 lines of code. Enjoy!

    import maya.cmds as cmds

    sel = cmds.ls( sl=True )

    for obj in sel :
    cmds.xform( obj, centerPivots=True )
    pos = cmds.xform( obj, q=True, ws=True, rp=True )
    cmds.move( 0,0,0, obj, rpr=True )
    cmds.makeIdentity( obj, apply=True )
    cmds.xform( obj, ws=True, t=pos )

    ReplyDelete
  3. Thanks Chris! Super helpful to get translation back. As far as I understand, the rotation/scale information can't be recovered since they get swallowed up by the matrix transforms when the object is frozen.
    Can anyone confirm that is true?

    ReplyDelete