JSR-184 Public Review Draft - Apr. 30, 2003.

javax.microedition.m3d
Class AnimationController

java.lang.Object
  |
  +--javax.microedition.m3d.Object3D
        |
        +--javax.microedition.m3d.AnimationController

public class AnimationController
extends Object3D

A set of methods for controlling multiple AnimationTracks as one.

In anything other than the simplest scenes, an animation sequence will require control of more than one property of more than one object. For example, a jointed figure performing a single gesture is usually thought of as a single animation, yet it involves the coordinated control of the position and orientation of many different objects.

Each animation sequence consists of a single AnimationController object, which is used to coordinate the operation of one or more AnimationTrack objects. Each AnimationTrack object contains all the data required to control a single animatable property on one object.

The AnimationController class enables the animation as a whole to be paused, stopped, and restarted in both immediate and retained mode. The speed of playback can also be adjusted.

The detailed behaviour of how the data flows through the animation system as a whole is documented in the AnimationTrack class.

Animation application

In both immediate and retained mode, animations are explicitly applied to target objects by calling the animate method on the target object itself. This re-evaluates the values of all object properties that have one or more animations attached. Animations are also applied to the children of the target object, so the application is free to choose between calling myWorld.animate to animate everything in myWorld at once, or applying animations to more fine-grained groups of objects individually.

Animation controllers have an active interval, specified by minimum and maximum world time values, during which the animation controller is active. Animations controlled by inactive animation controllers have no effect on their target objects and are simply ignored during animation application.

Weighted animations

Each animation controller has a weight associated with it. The contributions of all active animations targeting the same property at the same time are blended together by their respective weights. Formally, the value of a scalar property P as a function of weights w[i] and contributions P[i] is:

P = Sum(P[i]w[i]) / Sum(w[i])

Note that Sum(w[i]) can not be zero if there are active animations.

For vector-valued properties, the above formula is applied for each vector component separately. For most types of animation, the simple weighted sum as shown above is sufficient, but rotation values must be treated specially. Each interpolated quaternion is converted to "log space" by taking its logarithm prior to blending. These values are then blended linearly as above, and the final blended result is converted back into a unit quaternion by taking its exponent.

Timing and speed control

The animation controller specifies the relationship between world time, passed in to Object3D.animate, and the effective sequence time used in sampling the associated keyframe data.

We assume that synchronization of animation with other media types is only based on the world time passed from the controlling application. No synchronization events or other mechanisms are provided for this purpose. In the case of synchronizing animation to music, for example, the current elapsed time is often available directly from the music player library.

The sequence time is calculated directly from the world time at each update to avoid unexpected and undesirable results due to rounding errors. Furthermore, a reference point is introduced to enable more flexible speed and timing control. The formula for calculating the current animation sequence time ts from a given world time tw for an animation proceeding at speed s is:

ts = tsref + s * (tw - twref)

where twref is the reference world time, and tsref the reference sequence time. Sequence time can be visualized, in a coordinate system where world time is on the horizontal and sequence time on the vertical axis, as a line having slope s and passing through the point (twref, tsref).

As an example of the relationship between world time and sequence time, imagine a world where the current time is 5000 milliseconds since start. An animation was started (from 0 ms sequence time) at 3000 ms, running at half speed. The animation was started 2000 ms ago, but because the speed is 0.5, the actual required sequence time is 1000 ms. Here, we would have tw = 5000 ms, twref = 3000 ms, tsref = 0 ms, and s = 0.5 in the formula above.

Example usage

As an example of using animation, consider a case where we want a light source to pulsate between red and green, moving along a curved path. In both immediate and retained mode, this involves creating keyframe sequences and associating them with the light node, as illustrated in Example 1 below.

To apply the animation to the light object in our rendering loop, we must call the animate method, as shown in Example 2.

See Also:
Binary format
Examples:
(1) Creating an animation.
 Light light = new Light();	// Create a light node

// Load a motion path from a stream, assuming it's the first object there

Object3D[] objects = Loader.load("http://www.example.com/myfile.m3d");
KeyframeSequence motion = (KeyframeSequence) objects[0];

// Create a color keyframe sequence, with keyframes at 0 ms and 50 ms,
// and a total length of 100 ms. The setValidRange method must always
// be called after setting new keyframes with setKeyFrame, so that the
// validity of the sequence can be enforced. The animate method will
// throw an exception if it encounters an invalid KeyframeSequence.
// Note that the Loader automatically validates any sequences that
// are loaded from a file.

KeyframeSequence blinking = new KeyframeSequence(2, 3, KeyframeSequence.LINEAR);
blinking.setKeyframe(0,  0, new float[] { 1.0f, 0.0f, 0.0f });
blinking.setKeyframe(1, 50, new float[] { 0.0f, 1.0f, 0.0f });
blinking.setDuration(100);
blinking.setValidRange(0, 1);

AnimationTrack blink = new AnimationTrack(blinking, AnimationTrack.COLOR);
AnimationTrack move = new AnimationTrack(blinking, AnimationTrack.TRANSLATION);
light.addAnimationTrack(blink);
light.addAnimationTrack(move);

// Create an AnimationController and make it control both the blinking
// and the movement of our light

AnimationController lightAnim = new AnimationController();
blink.setController(lightAnim);
move.setController(lightAnim);

// Start the animation when world time reaches 2 seconds, stop at 5 s.
// There is only one reference point for this animation: sequence time
// must be zero at world time 2000 ms. The animation will be running
// at normal speed (1.0, the default).

lightAnim.setActiveInterval(2000, 5000);
lightAnim.setPosition(0, 2000);
(2) Applying the animation during rendering.
 appTime += 100;		// advance time by 100 ms each frame
light.animate(appTime);

// Assume 'myGraphics3D' is the Graphics3D object we draw into.
// In immediate mode, node transforms are ignored, so we get
// our animated transformation into a local Transform object

Transform modelview = new Transform();

light.getTransform(modelview);
myGraphics3D.setLight(0, light, modelview);

Field Summary
 
Fields inherited from class javax.microedition.m3d.Object3D
userObject
 
Constructor Summary
AnimationController()
          Creates a new AnimationController object.
 
Method Summary
 int getActiveIntervalEnd()
          Retrieves the ending time of the current active interval of this animation controller, in world time units.
 int getActiveIntervalStart()
          Retrieves the starting time of the current active interval of this animation controller, in world time units.
 int getPosition(int worldTime)
          Retrieves the current sequence time of this animation controller at specified world time.
 float getSpeed()
          Retrieves the currently set playback speed of this animation controller.
 int getWeight()
          Retrieves the currently set blending weight for this animation controller.
 void setActiveInterval(int start, int end)
          Sets the world time interval during which this animation controller is active.
 void setPosition(int time, int worldTime)
          Sets a new playback position, relative to world time, for this animation controller.
 void setSpeed(float factor, int worldTime)
          Sets a new playback speed for this animation, effective after the given world time.
 void setWeight(int weight)
          Sets the blending weight for this animation controller.
 
Methods inherited from class javax.microedition.m3d.Object3D
addAnimationTrack, animate, clone, find, getAnimationTrack, getAnimationTrackCount, getReferences, getUserID, removeAnimationTrack, setUserID
 
Methods inherited from class java.lang.Object
equals, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Constructor Detail

AnimationController

public AnimationController()

Creates a new AnimationController object. The default values for the new object are:

Method Detail

setActiveInterval

public void setActiveInterval(int start,
                              int end)

Sets the world time interval during which this animation controller is active.

This animation controller will subsequently be active when the world time t is such that start <= t < end, and inactive outside of that range. As a special case, if both are set to the same value, this animation controller is always active.

Note that changing the active interval has no effect on the mapping from world time to sequence time.

Parameters:
start - the starting time of the active interval, in world time units (inclusive)
end - the ending time of the active interval, in world time units (exclusive)
Throws:
java.lang.IllegalArgumentException - if start > end
See Also:
getActiveIntervalStart, getActiveIntervalEnd

getActiveIntervalStart

public int getActiveIntervalStart()

Retrieves the starting time of the current active interval of this animation controller, in world time units. The value returned is the same that was last set with setActiveInterval, or if it has not been called yet, the default value set at construction.

Returns:
the starting time of the active interval
See Also:
setActiveInterval

getActiveIntervalEnd

public int getActiveIntervalEnd()

Retrieves the ending time of the current active interval of this animation controller, in world time units. The value returned is the same that was last set with setActiveInterval, or if it has not been called yet, the default value set at construction.

Returns:
the ending time of the active interval
See Also:
setActiveInterval

setSpeed

public void setSpeed(float factor,
                     int worldTime)

Sets a new playback speed for this animation, effective after the given world time. The speed is set as a factor of the nominal speed of the animation: 1.0 is normal playback speed (as specified by the keyframe times in the associated animation tracks), 2.0 is double speed, and -1.0 is reverse playback at normal speed. A speed of 0.0 stops the animation. Setting the speed also modifies the internal reference point so that playback continues from the same position after the speed change.

The speed setting effectively specifies how much to advance the internal playback position of this animation for a given increment in the global world time.

Parameters:
factor - new playback speed
worldTime - reference world time; the value of sequence time at this point will remain constant during the speed change
See Also:
getSpeed

getSpeed

public float getSpeed()

Retrieves the currently set playback speed of this animation controller.

Returns:
the current playback speed
See Also:
setSpeed

setPosition

public void setPosition(int time,
                        int worldTime)

Sets a new playback position, relative to world time, for this animation controller. This essentially sets the internal reference point to (time, worldTime) to shift the animation to the new position.

Parameters:
time - the desired playback position in sequence time units
worldTime - reference world time; after the call, the sequence time will equal time at this point in world time
See Also:
getPosition

getPosition

public int getPosition(int worldTime)

Retrieves the current sequence time of this animation controller at specified world time.

Parameters:
worldTime - world time to get the corresponding animation time for
Returns:
animation sequence position in number of time units elapsed since the beginning of this animation, until worldTime
See Also:
setPosition

setWeight

public void setWeight(int weight)

Sets the blending weight for this animation controller. The blending weight must be positive or zero. Setting the weight to zero disables this animation controller; that is, the controller is subsequently not active even within its active range. If the weight is non-zero, the animations controlled by this controller contribute to their target properties as described in the class description.

Parameters:
weight - the new blending weight
Throws:
java.lang.IllegalArgumentException - if weight < 0
See Also:
getWeight

getWeight

public int getWeight()

Retrieves the currently set blending weight for this animation controller.

Returns:
the current blending weight
See Also:
setWeight

JSR-184 Public Review Draft - Apr. 30, 2003.

Copyright © 2003 Nokia Corporation. See the Copyright Notice for details.