• 1/3

MAXScript - Baking Animation Transforms

Posted by Christopher Diggins, 2 October 2012 3:12 pm

A colleague of mine, Amer Yassine, who manages the awesome 3ds Max YouTube learning channel recently asked me how to bake world space transforms to helper objects.

Amer provided me the example of an arm with three bones and three helper objects. Each helper object was parented to the bone and the bones were animated using an IK solution. When he collapsed the transform controllers on the point helpers it would create keyframes for the helpers but with 0 values. So when he unlinked the helper objects they were no longer animated. This makes sense because the position of helpers was in local space relative to the parent object, but what Amer wanted were position/rotation keys for the helpers based on the world-space data.

My first thought was to try and find some scripts on ScriptSpot.com to do what he wanted. However none seemed to work and at first I wasn't quite clear on what the precise problem we needed to solve was. Eventually I found a thread on CGSociety.com where a similar question was framed in a way that explained what Amer and I were looking for except it applied to a camera:

I have been fumbling around trying to find a way to bake out some animation I have on a camera. The camera is animated via three dummies in a hierarchy and I need to 'bake' in the animation at every keyframe in worldspace. Currently every method/script I have found bakes the animation in local space so when the dummies/point helpers have been deleted the camera does not retain any of the animation, yet I have a keyframes at every frame. Is there a way to create keyframes that would take the position/rotation of the camera in worldspace at everyframe and allow me to delete everything but the camera and retain all animation?

http://forums.cgsociety.org/archive/index.php/t-740206.html

Now I was getting somewhere, because I finally understood the problem! The ensuing thread didn't make much sense to either of us, but going back to first principles, I created a basic script that:

  1. Un-parented the helper from the bone.
  2. Created a key-frame for the helper object at each frame based on the bones position/rotation/scale.

The resulting solution is quite elegant using MAXScript:

-- Create keys for the selected objects from the world space transforms taken from the parents (bones). 
-- Also unlink each object from the parent. 
startTime = 0
endTime = 100
nthFrame = 5

-- For all selected objects 
for obj in $ do 
(
  -- Get the current parent (a bone) and unlink the object. 
  bone = obj.parent
  obj.parent = undefined
                
  -- Create animation keys
  for t in startTime to endTime by nthFrame do (
    animate on at time t (
      obj.transform = at time t bone.transform
    )
  )              
)

The magic in this script occurs in the "animate" context expression. Check out the MAXScript documentation on the animate keyword to learn how it works. In short it acts like the "autokey" mode in 3ds Max. Any animatable property you change (such as the transform) is automatically associated with a new key.

I hope the rest of the script is sufficiently clear for you to use and modify for your own work. It did the trick for Amer. :-)

By the way, if you use 3ds Max at all you should check out Amer's tutorial on rigging a character for games that he just recently started posting. It is an amazing tutorial series that will have 40 parts once it is all online!

6 Comments

MrMartinH

Posted 2 October 2012 10:14 pm

Hey Christopher,

Recently I needed a baking option for a project I was working on, on an animated object that had X and Y movements on it. The problem was that the object was animated using a Path Deform, so there was no way to bake the animation keys to the object.

In my search I found this script which helped me out a lot:
http://www.joegunn3d.com/WPblogoo7/archives/926.

I was written by Joe Gunn (if thats his name) and does exactly what your script does. Only Joe's script creates the helper objects automatically and bake the animated key's to the helper.

Just wanted to point it out to you. Thank for the informative post though.

Greets
Martin

Chris Johnson

Posted 3 October 2012 10:22 am

don't use $, I never use that...
use instead the function GetCurrentSelection
for obj in GetCurrentSelection() do ....

oh and btw: Excellent post Chris!

joegunn3d

Posted 3 October 2012 2:46 pm

@MrMartinH

Yes Joe Gunn is my real name

Christopher Diggins

Posted 5 October 2012 12:35 pm

@Martin: Thanks for the compliment and pointing us to a more powerful scripting solution.

@ChrisJ: Thanks for the compliment and the advice. I read up on the $ symbol and I see that it is tricky to use in scripts because it is sometimes a list and sometimes a single value. What are your thoughts about "selection" versus "GetCurrentSelection()"?

sinok

Posted 26 November 2012 5:19 pm

@Christopher Diggins: the difference between "selection" and "GetCurrentSelection()" is that "GetCurrentSelection()" returns an Array (such as: selection as array)

For example: Let's assume that you have a selection with two objects "Box001" and "Box002".
If use mySelection = selection[1]; print mySelection[1].name; it will return "Box001". If you change selection and select "Box003" and "Box004" and you run again print mySelection[1].name it will return "Box003".
On the other hand, if you say mySelection = GetCurrentSelection(); (or mySelection = selection as array) with two objects "Box001" and "Box002" selected the print mySelection[1].name will return "Box01" even if you later on change your selection with "Box03" and "Box04".

the only cases that I personally use selection, is in for loops when I collect data, for example myPositions = for o in selection collect o.pos;

Mark Pigott

Posted 31 January 2013 5:26 pm

I can no longer find that script on Joe Gunn's website.
I need to bake keyframes from Patch Deform motion!

Add Your Comment

You must be logged in to post a comment.

Please only report comments that are spam or abusive.