Stumbling Toward 'Awesomeness'

A Technical Art Blog

Thursday, May 1, 2008

Iterating and Per-frame Functions in MotionBuilder

In any animation package, there are many times technical artists/animators will need to iterate through all the frames of animation and do something. This is a given.

Accessing The Timeline

To access timeline functionality in MBuilder you can either get the current take and then request it’s start/stop or use the following, which grabs the start and stop in the current take/timeline:


However, this only returns a frame number in the range of your FPS, for instance, if your end frame is 1369, it will return the value 19L. To better understand this, enter 1369%30 into your Python Console, it will return 19. More info on modulo operations [here]

So how do we get time from MotionBuilder in a usable format? Here are two examples:

#this retuns the real frame number
#this returns in seconds</span></code>

Iterating Through the Timeline

Now that we can get the range of the frames in the timeline, let’s do stuff! Here is an example you can execute in MB showing how to iterate through time and do something for every frame (print frame number):

from pyfbsdk import *
lScene = lSystem.Scene
playaCtrl = FBPlayerControl()
#this returns the start/stop as integers<code>
fStart = int(playaCtrl.ZoomWindowStart.GetFrame(True))
fStop = int(playaCtrl.ZoomWindowStop.GetFrame(True))
for frame in range(fStart,fStop): print frame

Now, this is not to be confused with doing something on every frame. Above, we are just iterating through the frame numbers themselves. If there are 1000 frames, you are just going from number 1 to 1000 printing the current number.

So now let’s iterate through frames and do something every frame.

from pyfbsdk import *
def posEveryFrame(model):
	lScene = lSystem.Scene
	#we instance the player control to read from it faster
	playaCtrl = FBPlayerControl()
	#set our start and stop (as integers)
	fStart = int(playaCtrl.ZoomWindowStart.GetFrame(True))
	fStop = int(playaCtrl.ZoomWindowStop.GetFrame(True))
	#tell player control to go to the start of the scene
	#now iterate through the frames
	for frame in range(fStart,fStop):
		#evaluate the scene to make sure the data is updated
		#output the models position
		print model.Translation
		#tell the player to go to the next frame
selectedModels = FBModelList()
#run our function on the first model in the selection

So, executing this with a model selected should print the models translation (position) every frame for all frames in your timeslider (transport control).

Now you can start messing around with iterating through frames, and you will immediately notice two things:

1) Iterating through frames in MotionBuilder is slow. Almost slower than my grandmother entering all the values into a calculator (not even one with large numbered buttons)

2) The Python Console that you print to does not have a scroll bar, and does not have selectable text. (complete and utter fail)

posted by Chris at 3:56 AM  

1 Comment »

  1. Firstly, thank you for such an awesome and informative website, I’m very new to python and i have gained so much through some of your examples.

    I have a very similar piece of code as above, but if i run the script the timeline cursor does not update realtime, the script does everything it needs to, but i need to create a “Realtime” scenario, in order to run a live data link to Vicon IQ and print data at certain realtime frames.

    Is it possible to run scripts that iterate through a take on a per-frame basis realtime?

    Any comments will be very welcome
    Thanx once again

    Comment by Richard Tennant — 2009/03/23 @ 4:13 PM

RSS feed for comments on this post. TrackBack URI

Leave a comment

Powered by WordPress