CS184 Lecture 10 summary

Animation: Keyframes and Interpolation

Last time we introduced VRML's event model built on sensors and routes. Sensors generate events which can be routed to transform or other nodes to cause changes in the scene.

This time we cover animation of objects with specified motions. Animation of objects in VRML is accomplished with a TimeSensor node which generates events at regular time intervals, and various Interpolator nodes. The Interpolator nodes contain keyframes and interpolate between them in response to time signals from a TimeSensor.

Keyframing is the standard technique for computer animation. The position, orientation and/or shape of an object are specified at particular instants of time, called keyframes. The positions, orientations and shapes of the object in between keyframes are given by interpolating functions. In VRML, the builtin interpolators use linear interpolation. e.g. If an interpolator has position 0 0 0 at time t = 0 and position 1 0 0 at time t = 1, the position at time t = 0.3 would be 0.3 0 0.

In general, an interpolator can have more than two key times, and the same number of key positions/ orientations/ shapes. If the time is t, we find the two key times t1, t2 such that t1 £ t £  t2. Then we find the keyframes corresponding to those times and interpolate between them according to the fraction (t - t1)/(t2- t1).

For example, here is a position interpolator whose z-position approximates an upside-down parabola as a function of time, corresponding to an object bouncing.

Here is another example. This example has both a PositionInterpolator and an OrientationInterpolator. Note that the cycle interval is an arbitrary time (3 seconds) while the key values always range from 0 to 1.

You can also use a PositionInterpolator to control the shape of an object using a transform's scale exposedField.

You can also animate color using a ColorInterpolator.

Shape Animation

Most of the user-defined shapes, like IndexedLineSet, IndexedFaceSet and Extrusion  have exposedFields or eventIns that allow you to animate their shape. The basic type that is used to define their shape is MFVec3f, which is a multi-field value of 3D floating-point vectors. i.e. an arbitrary-sized array of 3D vectors.

In the PositionInterpolator, there is a 3D vector keyValue for every key fraction. For an OrientationInterpolator, there is a 4D rotation vector for each key fraction.

To animate a shape, we use a CoordinateInterpolator. For every key fraction, the CoordinateInterpolator has an arbitrary-length array of 3D vectors in its definition statement. It outputs an array of that length for each input fraction. If there are N keys, there should be NM 3D vectors specified in the keyValue field of the CoordinateInterpolator. For each set_fraction eventIn, the CoordinateInterpolator outputs M 3D vectors.

In this example from the textbook, a CoordinateInterpolator is used to animate the spine of an extrusion. The spine of the model has 19 points. The CoordinateInterpolator has 5 times, and for each time, there are 19 points in the interpolator. At each time step, the interpolator outputs 19 points which are used to update the spine.

Using Scripts

Scripts provide linkage between VRML and general programming language. A script node is like any other node that can send and receive events. Although this is an unfamiliar way to program, it makes a lot of sense in a 3D modeling context. In fact it is probably more natural and modular than controlling the scene with a single program.

In this example, there is a self-contained script which remembers an internal boolean variable called state, and toggles it whenever there is a click eventIn. The script code is here, using Javascript:

DEF toggle Script {
   url "javascript:
              function click(bval, eventTime) {
                  if ( bval == true ) { state = ! state; 
                                                    run = state; }
              }"
   field SFBool state FALSE
   eventIn SFBool click 
   eventOut SFBool run 
}

You can see that the eventIn click becomes a function defined in the script. The function accepts the passed event value as its first argument, and then the time of the event.

The eventOut is just a variable in the script. Setting it causes the eventOut to happen with the new value.

Scripts are particularly useful for building complex interpolators. Here is a script to generate the snake spine using a sine wave shifted by the time fraction:

DEF SnakeWiggle Script {
    url "javascript:
              function set_fraction (frac, eventTime) {
                   for ( i = 0; i < 19; i++) {
                        value_changed[i][0] = 0.47 * i - 4.47;
                        value_changed[i][1] = 0.0;
                        value_changed[i][2] = Math.sin((i/4.5 - frac*2) * 3.14);
                        }
                  value_changed[0][0] = -4.1;  // Fix the snake's head
                  value_changed[0][2] = value_changed[1][2];
             }"
    eventIn SFFloat set_fraction
    eventOut MFVec3f value_changed
}

You can see from the animation that this is much smoother than the original.

Doubling the number of spine points gives a more convincing snake.

Here's the same snake world again, but this time using a Java bytecode interpolator script.

The script source code is here.