Home Contents Forum Links Tip Jar
Animation Math in Lingo       

Case Study: Mr. Eyes

Related Topics:
Parametric Animation
Object-Oriented Fundamentals
3D Concepts: With Shockwave 3D (coming)

Mr. Eyes - source movie

Breaking It Down
Each of Mr. Eyes' expressions is a collection of linear parametric animations. Taken separately, they are just like those in the linear parametric demos except a sw3D property is being animated rather than a sprite property. No difference algorithm-wise.

The task to accomplish here is setting up numerous parametric animations and scheduling them to run at certain times. These are best accomplished with object-oriented techniques.

There are many ways to structure this program. I'll show how I did it in this demo and why, with its strengths and weaknesses. You'll need to be familiar with the basics of OO Lingo and parametric animation. Handlers are also called methods in this section.

One Animation Unit
Each animation, such as the tilt of an eyebrow or reddening of the eye whites, is a single parametric animation. It is defined by its driver, bias, and animator function. In this demo the driver, bias and animator parts are programmed to work as separate objects:

Once these objects are set up they act as a unit, independent from other code being executed. You can see the code that sets these objects up in the objectChain() method of the "mr. eyes" script.

An advantage of programming each part as a separate object is that they are interchangeable. You can write different types of driver scripts, and as long as they call the bias object's bias() method they can be used as a driver. Same goes for the bias object, which needs to have a bias() method and call the animator object's animate() method. And an animator script just needs an animate() method.

When different scripts (classes) are written to function in a similar way, they are said to implement a common interface in object-oriented terminology.

In this demo there is just one driver script and one bias script, but a variety of animator scripts for the different properties animated.

Driver Object
All the animations are driven by time, so the driver is the familiar eTime from the parametric demos. It is customized as an object as follows:

  • adds itself to the actorlist so it receives a stepframe call every frame
  • waits for the start time of the animation
  • for the duration of the animation, generates a value for p and passes it to the bias object's bias() method
  • when the animation is finished, removes itself from the actorlist

Bias Object
There is one type of bias object, and it provides bias types in, out, both, and none, and a bias magnitude. Whenever its bias() method is called, it biases p and passes it to the animator object's animate() method.

Animator Object
There is a different animator script for each type of property animated in the movie, and they all use a linear animator function (except for the angry vibration which is random). The animator scripts are almost identical, but for the different property they set. All of them have an animate() method so they can be used interchangeably in the object "chain" shown above.

Each animator script accepts as an argument the object whose property it is to animate. For rotation and position this object is the transform object of any 3D node. Other objects are shader.ambient for color and the resource object for animating the start and end angles of the sphere. This is one of those advantages of using objects—whatever object is passed to the animator, it will animate the property of that object. For example, whichever node's transform is passed to the animRot animator, that node in the 3D model will be rotated by the animator.

Setting Up the Objects
Setting these three objects up for an animation requires that each be instantiated and given an object reference for the next object in the chain. The driver needs a reference to the bias object so it can call its bias() method, and the bias object needs a reference to the animator object so it can call its animate() method. A reference is passed as an argument like other types of variables.

In the demo, the code that sets these objects up is in the objectChain() method of the "mr. eyes" script.

Managing the Objects
One facial expression for Mr. Eyes requires many separate animations, each of which has one object "chain" as shown above. After those object chains are created, they function automatically. However, it is useful to keep track of them for various reasons. For example, if you wanted to cut an animation short which would require somehow stopping each of the object chains currently active.

In this demo, the object chains are kept track of so that the mrEyes object can tell if any animations are currently active. If any are, no other facial expressions are allowed to start.

The mrEyes object keeps track of the object chains using a list called driverList. Each time it creates a new animation, it adds the driver object reference to driverList. In addition, it passes a driverList reference to each driver object created. When the driver object is finished with its animation, it removes itself from the driverList with the command driverList.deleteOne(me). When all the active animations are finished, the drivers will have removed themselves from driverList and it will be empty.

A Few Improvements
Manager Object
All the object chains for one facial expression are created when the user clicks on one of the buttons, which takes up memory and computation time while they wait to start.

A separate script can be written to do the managing. To make a new facial expression, the mrEyes object would pass a list defining the expression to the manager object. The manager object would monitor the start times and create each object chain only when it was ready to start. The eTime script would be modified so that it didn't wait for a start time, but started animating immediately.

In addition, the facial expressions could be queued. When the manager object receives the information for a new facial expression, it could add it to a list so that when the current expression is finished the next could be started. As the demo works now, new facial expressions are ignored if another is still happening.

Single Bias Object
The bias functions are generic for all the animations, so that only one bias object is really needed. With just one bias object, the driver would call animator() directly, like this:

objAnim.animate(objBias.bias(#both, p))

objBias would be global so that all drivers use the same one. The type of bias would need to be passed to the driver so it can use it when calling the bias function.

Things To Try
There are various things to try with this demo, depending on how far you want to go. You could:

  • make up new facial expressions using the code already in place.
  • define new object chains for motions not used yet in the demo.
  • write new animator scripts for properties not animated yet.
  • strip out all the code except for the 3D world setup and make your own object architecture.

If you do something new with the demo and wouldn't mind showing it, submit it for the Idea Swap. Feel free to change the design elements or make your own interface if you'd like (can remove the logos).

 
 


Copyright © 2003 JM Harward 
 jmckell~at~jmckell~dot~com
All lingo provided on this site may be used freely for educational purposes. Not for redistribution as uncompiled code. Instructional materials may not be reproduced without permission.