|
JSR-184 Public Review Draft - Apr. 30, 2003. | ||||||||||
PREV CLASS NEXT CLASS | FRAMES NO FRAMES | ||||||||||
SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD |
java.lang.Object | +--javax.microedition.m3d.Object3D | +--javax.microedition.m3d.AnimationController
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.
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.
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.
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.
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.
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);
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 |
public AnimationController()
Creates a new AnimationController object. The default values for the new object are:
Method Detail |
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.
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)
java.lang.IllegalArgumentException
- if start > end
getActiveIntervalStart
,
getActiveIntervalEnd
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.
setActiveInterval
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.
setActiveInterval
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.
factor
- new playback speedworldTime
- reference world time; the value of sequence
time at this point will remain constant during the speed changegetSpeed
public float getSpeed()
Retrieves the currently set playback speed of this animation controller.
setSpeed
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.
time
- the desired playback position in sequence time
unitsworldTime
- reference world time; after the call, the
sequence time will equal time
at this point in
world timegetPosition
public int getPosition(int worldTime)
Retrieves the current sequence time of this animation controller at specified world time.
worldTime
- world time to get the corresponding animation time for
worldTime
setPosition
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.
weight
- the new blending weight
java.lang.IllegalArgumentException
- if weight < 0
getWeight
public int getWeight()
Retrieves the currently set blending weight for this animation controller.
setWeight
|
JSR-184 Public Review Draft - Apr. 30, 2003. | ||||||||||
PREV CLASS NEXT CLASS | FRAMES NO FRAMES | ||||||||||
SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD |