|
M3G 1.1 -- Jun 22, 2005 | |||||||||
PREV CLASS NEXT CLASS | FRAMES NO FRAMES | |||||||||
SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD |
java.lang.Object javax.microedition.m3g.Object3D javax.microedition.m3g.KeyframeSequence
Encapsulates animation data as a sequence of time-stamped, vector-valued keyframes. Each keyframe represents the value of an animated quantity at a specific time instant.
A KeyframeSequence can be associated with multiple animation targets, that is, animatable object properties, via multiple AnimationTrack objects. Available animation targets include node and texture transformations, Material parameters, Camera parameters, and so on. When applying an animation to its target, the actual value for the target is derived by interpolating the keyframe values in the associated KeyframeSequence object.
The number of vector components per keyframe is specified in the
constructor and is the same for all keyframes in the sequence. The
interpretation of the keyframes is determined by the animation
target(s) the sequence is attached to. For example, 4-component
keyframes are interpreted as quaternions when applied to the
ORIENTATION
target.
Five different functions are available for interpolating the
keyframe values: LINEAR
and SPLINE
, their
quaternion equivalents SLERP
and SQUAD
; and
the simple STEP
function. Each of these is described in
the Field Summary. There are also two repeat modes, LOOP
and CONSTANT
, that affect the interpolation.
The internal sequence time t of a KeyframeSequence is derived from world time by its associated AnimationController(s). The formula for mapping world times to sequence times is given in the "Timing and speed control" section of the AnimationController class description. The sequence time is then used for interpolating between keyframe values as defined by the chosen interpolation function.
All (valid) keyframes in a KeyframeSequence must fall within a
sequence time range of [0, D], where D is the duration of the keyframe
sequence. The duration can be set with the setDuration
method. For sequences using the LOOP
repeat mode, the
sequence time t is restricted into this range via a modulo operation,
that is, by adding or subtracting a multiple of D such that 0 <= t
< D. For sequences using the CONSTANT
mode, the value
of t is unrestricted.
The first valid keyframe in a CONSTANT
sequence defines
the interpolated value returned before this point in time. That is, with
initial value v0 at time t0, the
interpolated value v = v0 for values of time
t such that t < t0.
The final valid keyframe in a CONSTANT
sequence defines
the interpolated value returned after this point in time. That is, with
final value vN-1 at time tN-1, the interpolated
value v = vN-1 for values of time t such
that t >= tN-1.
A sequence using the LOOP
repeat mode is interpolated
as if the keyframes were replicated backward and forward indefinitely
at a spacing equal to the given duration of the sequence. In this
case, a keyframe which appears at time t will be treated as if it also
appeared at time t + nD where n is any positive or negative integer
and D is the duration of a single loop of the animation, given in
setDuration
. Note that this is not achieved by
just the modulo operation on the sequence time described above.
In a looping sequence with N keyframes numbered [0, N-1], the successor of keyframe N-1 is keyframe 0, and the predecessor to keyframe 0 is keyframe N-1.
The specification allows several keyframes to coexist at the same
position in time. This allows discontinuities in the animation
sequences, which can be useful for example in incorporating cuts to
camera animation. In the case of several keyframes coinciding, the one
with the lowest index is always used for the final value of segments
ending at that position in time; for segments starting at that
position, the keyframe with the highest index is used for the starting
value. For sequences in LOOP
mode, the keyframes from the
next or previous repeat of the sequence may also coincide with the
keyframes of the current repeat if they are at the very end or very
beginning of the sequence. The keyframes in the previous repeat are
then treated as having lower indices, and the keyframes in the next
repeat as having higher indices, than the keyframes in the current
repeat.
Note that although any number of coincident keyframes can be
specified, a maximum of four will ever be used in SPLINE
or SQUAD
interpolation; two in LINEAR
or
SLERP
interpolation; and only the one with the highest
index in STEP
interpolation.
The validity of a keyframe sequence can be fully verified only when
it is applied to an animation target, that is, in the animate
method of Object3D. Any of the following conditions in a KeyframeSequence
will then trigger an IllegalStateException:
Although independent of the keyframe values as such, the interpolation type and the repeat mode of a sequence are set here rather than in the AnimationTrack objects using the sequence. This is so that the implementation can sensibly cache spline tangents or other auxiliary data potentially required at runtime.
AnimationTrack
,
AnimationController
Field Summary | |
static int |
CONSTANT
A parameter to setRepeatMode , specifying that
this sequence is to be played back just once and not repeated. |
static int |
LINEAR
A constructor parameter that specifies linear interpolation between keyframes. |
static int |
LOOP
A parameter to setRepeatMode , specifying that
this sequence is to be repeated indefinitely. |
static int |
SLERP
A constructor parameter that specifies spherical linear interpolation of quaternions. |
static int |
SPLINE
A constructor parameter that specifies spline interpolation between keyframes. |
static int |
SQUAD
A constructor parameter that specifies spline interpolation of quaternions. |
static int |
STEP
A constructor parameter that specifies stepping from one keyframe value to the next. |
Constructor Summary | |
KeyframeSequence(int numKeyframes,
int numComponents,
int interpolation)
Constructs a new keyframe sequence with specified interpolation method, number of components per keyframe, and number of keyframes. |
Method Summary | |
int |
getComponentCount()
Returns the number of components per keyframe in this sequence. |
int |
getDuration()
Gets the duration of this sequence. |
int |
getInterpolationType()
Returns the type of interpolation for this sequence. |
int |
getKeyframe(int index,
float[] value)
Retrieves the time stamp and value of a single keyframe. |
int |
getKeyframeCount()
Returns the total number of keyframes in this sequence. |
int |
getRepeatMode()
Retrieves the current repeat mode of this KeyframeSequence. |
int |
getValidRangeFirst()
Returns the first keyframe of the current valid range for this sequence. |
int |
getValidRangeLast()
Returns the last keyframe of the current valid range for this sequence. |
void |
setDuration(int duration)
Sets the duration of this sequence in sequence time units. |
void |
setKeyframe(int index,
int time,
float[] value)
Sets the time position and value of the specified keyframe. |
void |
setRepeatMode(int mode)
Sets the repeat mode of this KeyframeSequence. |
void |
setValidRange(int first,
int last)
Selects the range of keyframes that are included in the animation. |
Methods inherited from class javax.microedition.m3g.Object3D |
addAnimationTrack, animate, duplicate, find, getAnimationTrack, getAnimationTrackCount, getReferences, getUserID, getUserObject, removeAnimationTrack, setUserID, setUserObject |
Field Detail |
public static final int LINEAR
A constructor parameter that specifies linear interpolation between keyframes.
For a keyframe with value vi at time ti, where the following keyframe has a value vi+1 at time ti+1, the interpolated value v is defined only for values of time t such that ti <= t < ti+1, as follows:
where s is an interpolation factor in [0, 1) computed from the keyframe times:
public static final int SLERP
A constructor parameter that specifies spherical linear interpolation of quaternions.
This type of interpolation will interpolate at constant speed along the shortest "great circle" path between two keyframe values along the surface of the hypersphere of unit quaternions.
Spherical linear interpolation between two keyframe values qi and qi+1 is defined as:
where a is the angle between the two quaternions and s
is the interpolation factor defined for LINEAR
interpolation.
Note that the shortest path between two quaternions is not the same as the shortest path between the corresponding 3D orientations. There are always two quaternions corresponding to a single 3D orientation, each of which denotes a different direction of interpolation along the great circle; thus, quaternions can encode up to 360 degrees of rotation between adjacent keyframes.
It is common practice in some applications to precondition quaternions prior to slerping so that the shorter interpolation path in 3D is always chosen. While this is useful in special cases, it does not yield the same result in general, and is therefore incompatible with more advanced features such as animation blending. Hence, implementations are explicitly disallowed from incorporating this practice, and must implement the general slerp routine instead. Authoring tools, however, are encouraged to present the preconditioning as an option when exporting keyframe data.
Also note that interpolation between diametrically opposed quaternions in successive keyframes is undefined. It is recommended that authoring tools should take steps to warn designers if this case is detected.
More details can be found in "Quaternion Algebra and Calculus" by David Eberly [see Related Literature].
public static final int SPLINE
A constructor parameter that specifies spline interpolation between keyframes. The keyframes will be interpolated with a Catmull-Rom spline adjusted to accommodate non-constant keyframe intervals.
For each curve segment i, we have the values vi at time ti, and vi+1 at time ti+1. We also define tangents at the end points of the segment: Ti at the start point, and Ti+1 at the end point.
Using the interpolation factor s defined for
LINEAR
interpolation, we can then
express the interpolation of the curve as follows:
S = |
| s 3 || s 2 || s || 1 | |
H = |
| 2 -2 1 1 | | -3 3 -2 -1 | | 0 0 1 0 | | 1 0 0 0 | |
C = |
| v i || v i+1 || T 0 i || T 1 i+1 | |
The value vs of the curve at position s can be calculated using the formula:
The only thing left to define is the calculation of the tangent vectors T{0,1}i. A standard Catmull-Rom spline assumes that the keyframe values are evenly spaced in time, and calculates the tangents as centered finite differences of the adjacent keyframes:
We apply additional scaling values to compensate for irregular keyframe timing, and the final tangents are:
where:
CONSTANT
sequence
It is relatively easy to convert to this representation from piecewise Bezier splines (as used by 3ds max, for example) as long as the tangents are set up according to the above scheme. Conversion from other interpolating spline forms may not be exact, although any interpolating spline is guaranteed to pass through the keyframe values.
public static final int SQUAD
A constructor parameter that specifies spline interpolation of quaternions.
This interpolation method is similar to the
SPLINE
method, but using equivalent quaternion
operations. The tangents for each keyframe are computed as
centered finite differences, only this time via quaternion
logarithms:
Note that the operations above are not to be confused with scalar or vector operations. The notation q-1 denotes the inverse of quaternion q; the multiplications are quaternion multiplications; and the logarithm is a quaternion logarithm, which essentially yields a 3-vector as a result.
Keyframe tangents are scaled to compensate for
irregular keyframe timing as specified for SPLINE
interpolation. This yields the "incoming" tangent
T0i and the "outgoing" tangent
T1i. From the scaled tangents,
intermediate quaternion values a and b are
computed for use in interpolating the curve segments starting
and ending at each keyframe:
Finally, the interpolated value q at position s
(as defined in LINEAR
) for a curve segment
between keyframes i and i + 1 is obtained by using
SLERP
interpolation, as follows:
For more information, refer to "Key Frame Interpolation via Splines and Quaternions" by David Eberly [see Related Literature].
public static final int STEP
A constructor parameter that specifies stepping from one keyframe value to the next. The actual value of each keyframe is used, without further interpolation, from the time position of that keyframe until the time of the next keyframe.
For a keyframe with value v at time ti, where the following keyframe is at time ti+1, the value v is valid for all values of time t such that ti <= t < ti+1.
public static final int CONSTANT
A parameter to setRepeatMode
, specifying that
this sequence is to be played back just once and not repeated.
public static final int LOOP
A parameter to setRepeatMode
, specifying that
this sequence is to be repeated indefinitely.
Constructor Detail |
public KeyframeSequence(int numKeyframes, int numComponents, int interpolation)
Constructs a new keyframe sequence with specified
interpolation method, number of components per keyframe, and
number of keyframes. All keyframes are initialized to the zero
vector, with a time stamp of zero. The repeat mode is initially
CONSTANT
(not looping), with an undefined duration
and the valid range spanning all keyframes.
A newly constructed sequence cannot be used in animation
until the duration of the sequence has been set. The valid
range, that is, the range of keyframes that are included in the
animation, can be set with setValidRange
. This may
be desirable if keyframes are generated dynamically or streamed
over the network.
The interpolation method is one of the symbolic constants
defined above. The method must be compatible with the number
of components in the keyframes. STEP
,
LINEAR
and SPLINE
can be specified
for any type of keyframes. On the other hand, SLERP
and SQUAD
can only be specified for 4-component
keyframes, which are then interpreted as quaternions.
numKeyframes
- number of keyframes to allocate for this sequencenumComponents
- number of components in each keyframe vectorinterpolation
- one of the interpolation modes listed above
java.lang.IllegalArgumentException
- if numKeyframes < 1
java.lang.IllegalArgumentException
- if numComponents < 1
java.lang.IllegalArgumentException
- if interpolation
is not
one of LINEAR, SLERP, SPLINE, SQUAD, STEP
java.lang.IllegalArgumentException
- if interpolation
is not a valid interpolation mode for keyframes of size
numComponents
Method Detail |
public int getComponentCount()
public int getKeyframeCount()
setValidRange
public int getInterpolationType()
LINEAR, SLERP, SPLINE, SQUAD, STEP
public void setKeyframe(int index, int time, float[] value)
Sets the time position and value of the specified
keyframe. The keyframe value is copied in from the given
array. The length of the array must be at least equal to the
size of a keyframe (numComponents
). Refer to
AnimationTrack documention for the order in which the keyframe
components should be stored in the array for a particular
target property.
If the interpolation type is SLERP
or
SQUAD
, the keyframes are automatically normalized
to yield unit quaternions for interpolation.
index
- index of the keyframe to settime
- time position of the keyframe, in sequence time unitsvalue
- float array containing the keyframe value vector
java.lang.NullPointerException
- if value
is null
java.lang.IndexOutOfBoundsException
- if (index < 0) ||
(index >= getKeyframeCount)
java.lang.IllegalArgumentException
- if value.length <
getComponentCount
java.lang.IllegalArgumentException
- if time < 0
getKeyframe
public int getKeyframe(int index, float[] value)
Note that if the interpolation type is SLERP or SQUAD, the keyframes are automatically normalized upon setting. The values returned here may therefore be different from the original input values.
index
- index of the keyframe to retrievevalue
- float array to store the keyframe value
vector, or null to only return the time stamp
java.lang.IndexOutOfBoundsException
- if (index < 0)
|| (index >= getKeyframeCount)
java.lang.IllegalArgumentException
- if (value != null)
&& (value.length < getComponentCount)
setKeyframe
public void setValidRange(int first, int last)
Selects the range of keyframes that are included in the
animation. Keyframes outside of that range are ignored by the
animate
method in Object3D.
Setting the valid range shorter than the whole sequence enables the application to use the sequence as a circular buffer when generating new keyframe data on the fly, for example. In a typical case, however, the valid range would span the whole sequence.
The valid keyframe range is always interpreted in the direction
of ascending indices. If first <= last
, the valid
keyframes are those at the indices:
first, first+1, ..., last
If last < first
, the valid range wraps around and
the valid keyframe indices are:
first, first+1, ..., getKeyframeCount()-1, 0, 1, ..., last
The time position of each keyframe in the active range must
be greater than or equal to that of the preceding keyframe; if
this is not the case, Object3D.animate
will throw an exception. The time stamps must be in non-decreasing
order, because otherwise the interpolated values between keyframes
would be undefined. Note that having two or more keyframes with the
same time stamp is specifically allowed.
first
- index of the first valid keyframelast
- index of the last valid keyframe
java.lang.IndexOutOfBoundsException
- if (first < 0) ||
(first >= getKeyframeCount)
java.lang.IndexOutOfBoundsException
- if (last < 0) ||
(last >= getKeyframeCount)
getValidRangeFirst
,
getValidRangeLast
public int getValidRangeFirst()
setValidRange
public int getValidRangeLast()
setValidRange
public void setDuration(int duration)
Sets the duration of this sequence in sequence time units. The duration of a keyframe sequence, as used in animation playback, is determined by the value set here, irrespective of the time stamps of individual keyframes, and irrespective of which keyframes happen to be in the valid range at any given time.
The duration D is also used when interpolating looping keyframe sequences. The time interval from the last valid keyframe to the first valid keyframe of the next cycle is calculated as follows:
where tfirst and tlast are the time
stamps of the first and last keyframe, respectively, in the
valid range (see setValidRange
). Note that they
are not necessarily the first and last keyframe of the whole
sequence.
The duration of the sequence must not be less than the
time stamp of the last valid keyframe (tlast),
as otherwise the above formula would yield a negative time
interval. Since the duration and the valid range can both be
changed at any time, this condition is only enforced by the
animate
method in Object3D.
duration
- duration of the valid range of the sequence
java.lang.IllegalArgumentException
- if duration <= 0
getDuration
public int getDuration()
Gets the duration of this sequence.
setDuration
public void setRepeatMode(int mode)
Sets the repeat mode of this KeyframeSequence. There are two
alternatives, LOOP
and CONSTANT
.
A looping sequence always loops back to the beginning from the end and has an interpolated segment from the last valid keyframe to the first.
A constant sequence maintains the first valid keyframe value from the beginning of the sequence to the actual time of that keyframe, and the last valid keyframe value from that keyframe to the end time of the sequence and beyond.
mode
- the repeat mode to set
java.lang.IllegalArgumentException
- if mode
is not
one of CONSTANT, LOOP
getRepeatMode
public int getRepeatMode()
Retrieves the current repeat mode of this KeyframeSequence.
CONSTANT
or
LOOP
setRepeatMode
|
M3G 1.1 -- Jun 22, 2005 | |||||||||
PREV CLASS NEXT CLASS | FRAMES NO FRAMES | |||||||||
SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD |