Game Development Reference
In-Depth Information
Keyframing morph targets
Now that we can blend our morph targets, the next stage is to store the
result of the blending so that we can interpolate the result. The
interpolation will use TCB curves, so any new keyframe must store the
current levels for all the morph targets along with a time or frame value for
the position. The flow of a TCB curve is adjusted by altering the tension,
bias and continuity parameters, which are stored for each keyframe. Full
details of TCB curves are given in Chapter 8. Because TCB curves
attempt to smooth the flow of the curve around each key value, this can
sometimes result in movement where no movement is intended. The
linear flag informs the code that the movement between two key positions
should be linear rather than smoothed. The main benefit of this flag is to
ensure that static sections are static.
typedef struct stMORPHKEY{
int frame;
float time;
float level[MAX_MORPH_TARGETS];
int linear;
float tn, bs, ct;//tension, bias and continuity
}MORPHKEY;
When creating a key value we need to take the current morph levels
and a supplied frame or time value and amend, insert or add a keyframe.
We amend a keyframe if there is already a key defined for this frame
value. The development software Toon3D uses a combination of an
integer value 'frame' and an integer value 'fps' to define the time value.
Time is defined as frame/fps. Why not simply use time in seconds? The
reason is that comparing floating-point values is not nearly as reliable as
comparing integer values. It is easy in practice to end up creating a key at
1.04 seconds and another at 1.0401 seconds when the intention was to
amend the key at 1.04 seconds. If the frames per second (fps) is 25 and
the current frame is 26, then the time value is 1.04. If the intention is to
amend the values at frame 26, then comparing 26 with a keyframe with
the frame value set to 26 will ensure a one-to-one comparison. In the
supplied code, a loop is used to check the current frame value against the
current keyframes; if the current frame is less than a current keyframe
then we need to insert the key before this existing keyframe. Since we are
inserting a key we must allocate memory for the existing keyframes and
one extra. Before inserting the key, the previous keys are copied to the
new keyframe array. Then the keyframe is added and any keyframes that