S.B.C.C. ->
Computer Science -> Courses
-> COMSC 111 -> Class
Notes
These notes explain how to do a simple VRML animation. We want to move a box from side to side along the X-axis. If we were going place the box in three different places not using animation we could use the following VRML.
Transform { children [ Shape { geometry Box {} } ] translation 0 0 0 } Transform { children [ Shape { geometry Box {} } ] translation 0 0 0 } Transform { children [ Shape { geometry Box {} } ] translation 0 0 0 }
This looks like the following:
To animate the scene with on block we will want the one block to go from the center position to the right position, back to the center position, to the left position, and returning to the center position before starting over again.
We can do this in VRML using a technique called keyframe animation. In traditional keyframe animation we specify several frames where we want the object to be located. Once those are specified, the computer generates frames that smoothly interpolate between those end positions to give us the animation. In VRML, there are no "frames" to speak of so we move the Box by changing the translation field in the enclosing Transform node.
Since we don't have any frames to speak of in VRML let's take a look at the VRML that does keyframe animation.
#VRML V2.0 utf8 DEF myBox Transform { children [ Shape { geometry Box {} } ] translation 0 0 0 } DEF box_pos PositionInterpolator { key [ 0.0 0.25 0.50 0.75 1.00 ] keyValue [ 0 0 0, 4 0 0, 0 0 0, -4 0 0, 0 0 0] } DEF clk TimeSensor { cycleInterval 2 loop TRUE }
ROUTE clk.fraction_changed TO box_pos.set_fraction
ROUTE box_pos.value_changed TO myBox.translation
Let's take a look at the first line:
#VRML V2.0 utf8
This is the usual VRML comment indicating that it is version 2.0. Following this comment is:
DEF myBox Transform { children [ Shape { geometry Box {} } ] translation 0 0 0 }
This is where the Box that we're going to animated is defined. We use a DEF node to define the box, called myBox, so that it can be referred to by name later. The Box node must be enclosed in a Transform node so that we may alter the values of the translation field through time to move the Box.
The next block of VRML shows the PositionInterpolator node. This node is the node that generates the different translation field values to do the animation. This is where the keyframe part of the animation is actually done. The PositionInterpolator has two visible fields, key and keyValue. The key refers to a sequence of floating-point numbers ranging from 0.0 to 1.0. Each one of these numbers shows where the Box will be at that time. Corresponding to each key is a keyValue. The keyValue is an X Y and Z coordinate corresponding to the position of the Box. Each key must have an X Y Z triplet associated with it.
The illustration above shows how this works. At Time 0.0 the box is located at coordinate (0,0,0). When time goes to 0.25 the box moves to (4,0,0). It returns to (0,0,0) when the time goes to 0.50 and then moves to the left when the time goes to 0.75. Finally, it returns back to (0,0,0) when the time goes to 1.0.
DEF box_pos PositionInterpolator {
key [ 0.0 0.25 0.50 0.75 1.00 ]
keyValue [ 0 0 0, 4 0 0, 0 0 0, -4 0 0, 0 0 0]
}
If the interpolator gets a key that is not specified then it creates a keyValue by interpolating between keys and keyValues. For instance if the node gets a key of 0.125 then the corresponding keyValue that will be generated is (2,0,0). This is because 0.125 is half way between the keys 0.0 and 0.25, and half way between the keyValues (0,0,0) and (4,0,0) is (2,0,0).
So what gives the PositionInterpolator its keys? The TimeSensor node. This is shown below:
DEF clk TimeSensor { cycleInterval 2 loop TRUE }
The TimeSensor node simply generates a stream of numbers between 0.0 and 1.0. The cycleInterval refers to how long it takes to get from 0.0 to 1.0. We have specified that it takes 2 seconds to go from 0.0 to 1.0. The loop field specifies that once we get to 1.0 we start again at 0.0. Note that the TimeSensor node is DEF'd with clk to allow it to be accessed by name.
As of right now we have a Box to be moved, an interpolator to feed the Box the proper coordinates, and a TimeSensor to feed the interpolator the keys. How do we connect them together? We use the ROUTE command. ROUTE is specified by saying
You don't have to capitialize ROUTE or TO but it makes them easier to read. Let's look at our ROUTEs:
ROUTE clk.fraction_changed TO box_pos.set_fraction ROUTE box_pos.value_changed TO myBox.translation
The first route connects the clk to the box_pos. What are fraction_changed and set_fraction? These are extra fields on the node used to receive and send events (this is why you have to look at the Specification). The field fraction_changed is a field the spits out events in a TimeSensor node. The field set_fraction is a field that is made to receive events in an Interpolator node. We need the names attached to the objects by the DEF statement so that we can refer to the ROUTEs by name.
The second ROUTE routes the interpolator's value (value_changed) to the translation field of our Box's Transform node (translation). Fields like translation can be used for both sending and receiving events.
So, to recap. The TimeSensor continuously generates a stream of numbers between 0.0 and 1.0 every 2.0 seconds. This stream of numbers comes out of the fraction_changed field and is ROUTEd to the PositionInterpolator by means of the set_fraction field. Once the numbers are received then they are used to generate new keyValues based upon the number's value. These new keyValues are the coordinates of where the Box should be located. The keyValues are ROUTEd to the translation field of the Transform node that encloses the Box. This change in translation field values moves the box.
The effect is shown in the VRML below.
Last Updated: March 13, 1998