|
BIFS Tutorial - Part IIAnimation |
|
We will now introduce animation to bring some life in the scene. BIFS offers two ways of animating a scene: using value interpolators and events generators as in VRML, or using live modifications by adding, removing or updating nodes in the tree through command or animation frames (encoded in a file, sent by a server).
In order to animate a value with an interpolator, we need 3 nodes: a target node to be animated (here we will use a Transform2D node), a node generating events (TimeSensor), an interpolator node (XXXXXInterpolator) and links between these three nodes (Route).
The Transform2D node is the most commonly used transformation node in 2D scenes.Here is its syntax:
<Transform2D center="0 0" rotationAngle="0.0" scale="1 1" scaleOrientation="0.0" translation="0 0">
<children>... graphical primitives, other nodes ...</children>
</Transform2D>
These node is quite simple and powerfull. It applies an affine transformation to the visual nodes in sub-trees and nodes listed in the children field:
The transformations are applied in the following order: scaling, rotation and translation.
Let's use the previous rectangle example and transform it.
Transformation type |
Example |
|
rect4.xmt, rect4.bt, rect4.mp4 |
|
rect5.xmt, rect5.bt, rect5.mp4 |
|
rect6.xmt, rect6.bt, rect6.mp4 |
|
rect7.xmt, rect7.bt, rect7.mp4 |
Events and routes are the key elements when building interpolator-based animations. Events are usually generated (eventOut) by sensor nodes (click, drag, periodic events, ..) and shall be connected to event listener (eventIn) in order to modify the scene: this connection is called a Route. To fully understand these concepts, let's get back on the notion of field. In the nodes we have seen, we have found several types of fields (order, emissiveColor, translation, size ...) with different types (real, integers, boolean, ...). These types are called fieldType and define what type of numerical value the field is. A field also has a type for the kind of event it accepts or generates, called the eventType. A field can generate events (eventOut), accept event as an input ( eventin), do both ( exposedField) or none (field). Events are passed from emitters (eventOut or exposedField) to recievers (exposedField or eventIn) of a same value type. BIFS defines 22 fieldTypes :
field type |
Semantics |
SFBool |
Boolean (TimeSensor.enabled, IndexedLineSet2D.colorPerVertex) |
SFFloat |
Real (LineProperties.lineWidth, Transform2D.rotationAngle) |
SFTime |
Double number for timing information only (TimeSensor.cycleInterval) |
SFInt32 |
Signed integer (LineProperties.lineStyle) |
SFString |
Character string |
SFVec3f |
3D coordinate for points or vectors (real numbers) |
SFVec2f |
2D coordinate for points or vectors (real numbers) |
SFColor |
RGB values of a color. Each component is a real number in the interval [0, 1] (Material2D.emissiveColor) |
SFRotation |
Rotation givan by a 3D vector (rotation axis, as in SFVec3f) and a rotation angle in radians |
SFImage |
Pixel array, only used for small textures used by PixelTexture node |
SFNode |
Field is of type node and may accept a node as a value (IndexedFaceSet2D.color, Shape.material) |
MFBool |
SFBool Array |
MFFloat |
SFFloat Array |
MFTime |
SFTime Array |
MFInt32 |
SFInt32 Array (IndexedFaceSet2D.colorIndex, OrderedGroup.order) |
MFString |
SFString Array |
MFVec3f |
SFVec3F Array |
MFVec2f |
SFVec2F Array (Coordinate2D.point) |
MFColor |
SFColor Array (Color.color) |
MFRotation |
SFRotation Array |
MFImage |
SFImage Array (never used by native nodes) |
MFNode |
SFNode Array (OrderedGroup.children, Transform2D.children) |
In order to declare a route between 2 fields of 2 nodes, we need a way to identify these nodes so that the player understands how to dispatch (route) events. The mechanism used is the DEF/USE one, which allows to assign a usage name to a node (DEF) and reuse the node (USE) anywhere in the scene. The XMT syntax for the DEF mechanism is simple:
Examples :
<Transform2D scale="1 2" DEF="Y-Scaling">...</Transform2D>
<Shape DEF="ASquare">...</Shape>
<IndexedLineSet2D DEF="Line1" colorPerVertex="false">...</IndexedLineSet2D>The XMT syntax for Route is:
<Route fromNode="Node1" fromField="field1" toNode="Node2" toField="field2"/>
In this syntax, 'Node1' is the same character string as the DEF one of the node owning the emitter field ('field1'), 'Node2' the same character string as the DEF one of the node owning the reciever field ('field2'). Names 'Node1' and 'Node2' are defined by the author, whereas names 'field1' et 'field2' are define by the node syntax (BIFS built-in nodes or prototypes).
The TimeSensor node is used to generate periodic time events. The period is given in seconds by the cycleInterval field. The startTime field specifies when the node shall start the event generation; it is expressed in seconds and relative to the scene simulation time. For now we will use it with its value to default (0), meaning it is active as soon as the scene is loaded. The stopTime field specifies when the node shall stop generating events; it is expressed in seconds and relative to the scene simulation time. We will use it with its value to default (-1), meaning the sensor is always active. The loop field indicates whether generation ends at the end of a cycle of cycleInterval seconds or not. The node can be disbaled (not sending events) by modifiying the enabled field.
The TimeSensor node generates 4 distinct events: cycleTime, isActive, fraction_changed and time. For interpolator-based animation, the most important event is the fraction_changed one. The fraction_changed field is an eventOut of type SFFloat; this real is in the interval [0, 1] and indicates the fraction of the current cycle since the start of the cycle. If the cycle starts at t and the current time is t+dt with a cycleInterval of T then fraction_changed is dt/T.
The XMT syntax is:
<TimeSensor cycleInterval="1"/>
BIFS has many interpolator nodes for many field types: 3D coordinate (CoordinateInterpolator), 3D orientation (OrientationInterpolator), 3D normal (NormalInterpolator), 3D position (PositionInterpolator), 2D coordinate (CoordinateInterpolator2D), 2D position (PositionInterpolator2D), scalar (ScalarInterpolator)and color (ColorInterpolator). All interpolators have 4 common fields: 2 exposedfields called key (MFFloat type), and keyValue (type depending on the interpolator type), an eventIn called set_fraction (SFFloat type) and an eventOut called value_changed (type depending on the interpolator type). Interpolators used in 2D are as follows:
Interpolator Node |
keyValue type |
value_changed type |
|
PositionInterpolator2D |
MFVec2F |
SFVec2F |
|
CoordinateInterpolator2D |
MFVec2f |
MFVec2f |
|
ScalarInterpolator |
MFFloat |
SFFloat |
|
ColorInterpolator |
MFColor |
SFColor |
Interpolators perform a piecewise-linear interpolation on the interval (-infinity, +infinity). The interpolation function is defined by the N values of the key field, called interpolation keys, and the N values of the keyValue field. Keys must be listed in increasing order but are not restricted to any interval. The interpolator uses the input fraction t recieved in set_fraction to evaluate the interpolation f(t) and give the result in the output value_changed field . If there are n keys (t0, t1, t2, ..., tn-1) in the key field, the interpolation is done on the intervals ]-infinity, t0[, [t0, t1[, [t1, t2[, ... , [tn-1, +infinity[. Let v0, .., vn-1 be the values of the keyValue field, then f(t) is:
f(t) = v0, if t <= t0,
f(t) = vn-1, if t >= tn-1,
f(t) = linear interpolation between (ti, vi) and (ti+1, vi+1) for ti<=t <= ti+12 following keys may be identical, hence allowing for discontinuities in f(t).
The XMT syntax is:
<PositionInterpolator2D key="0 1" keyValue="0 0 40 40"/>
This interpolator will output the event SFVec2f(30,30) in value_changed field if it gets the value 0.75 in its set_fraction field.
Now that we have all elements to build a simple animation, let's make our rectangle move from position (0,0) to position (40,40) in 10 seconds : anim1.xmt, anim1.bt, anim1.mp4.
<OrderedGroup>
<children>
<Transform2D DEF="MoveRec">
<children><Shape><geometry><Rectangle size="50 40"/></geometry></Shape></children>
</Transform2D>
<TimeSensor DEF="Timer" cycleInterval="10"/>
<PositionInterpolator2D DEF="Interp" key="0 1" keyValue="0 0 40 40"/>
</children>
</OrderedGroup>
<Route fromNode="Timer" fromField="fraction_changed" toNode="Interp" toField="set_fraction"/>
<Route fromNode="Interp" fromField="value_changed" toNode="MoveRec" toField="translation"/>
One of the fundamentals of BIFS scenes is that the scene may be modified at will through commands. These commands are grouped in a timed entity called Access Unit in MPEG-4 Systems, which can be compared to a video frame.
A video is a sequence of images or frames where each frame is given a presentation time (the time at which the frame has to be displayed on the terminal). This indication is called the CompositionTimeStamp in MPEG-4 terminology. The sequence of timed video frames is called a video stream.
Similary, a BIFS scene is made of a sequence of BIFS-Commands access units (set of commands and presentation time), hence resulting in a BIFS stream. Playing a BIFS stream consists in applying modification described in the BIFS commands to the scene and displaying the result to the user. As in video, some BIFS commands may describe the entire scene (hence may be decoded without knowledge of previous BIFS commands) much like an I-frame in video coding, while others modify the existing scene much like a P-frame in video coding. In all cases the BIFS commands are called BIFS updates. There are two kinds of BIFS updates: the first one, called BIFS Command frames, consists in modifying node fields or adding or suppressing parts of the scene graph. The second type, called BIFS Animation frames, consists in modifying a pre-defined set of node fields with high compression techniques, and is designed for continuous animation. The BIFS animation frames can be re-written in BIFS command frames with higher bitrate, while the opposite is not true. This tutorial will not talk about BIFS animation frames.
In order to add BIFS updates in an XMT document, we need to have a deeper look at the XMT structure of the vide.xmt document.
An XMT document begins with the XML XMT-A element. This element is made of the header element and the body element. We will come back on the header element later on. until now, the body element had the following syntax:
<body>
<Replace>
<Scene>
<OrderedGroup> The BIFS scene </OrderedGroup>
... eventually a list of ROUTEs ...
</Scene>
</Replace>
</body>The body element indicates the begining of the BIFS stream. The CompositionTimeStamp for this element matches time T = 0. The Replace element indicates that the BIFS command used is a replacement command. Its sub-element Scene indicates that the whole scene (previously empty) is being replaced by the Scene element (eg, the top node and the list of Routes). This implicitly defines a BIFS stream with only one frame at time 0 containing one command.
Adding a frame to the BIFS stream in an XMT documant is done by appending the par element to the Replace sub-element of the body element:
<par begin="1.5"> .... </par>
The begin attribute indicates the presentation time of the frame in seconds. The content of the par element is a sequence of BIFS commands that will be applied in order to the scene at time begin.
There are three types of BIFS commands: a replacement command (Replace), an insertion command (Insert) and a deletion command(Delete).
As seen above, the Replace command can be used to replace the whole scene by a new one if its content is the Scene element. It can also be used to replace a defined node, a defined route or a field of a defined node.
Command Meaning |
Syntax |
|
<Replace atNode="Identifier"> ... the new node to replace with ... </Replace> |
|
<Replace atRoute="Identifier"> ... the new route to replace with ... </Replace> |
|
<Replace atNode="identifier" atField="Fieldname" value="NewValue"/> |
|
<Replace atNode="identifier" atField="FieldName"> ... the new node to replace the field with... </Replace> |
|
<Replace atNode="identifier" atField="FieldName" position="FIRST|END|n"> ... remplacement node... </Replace> |
|
<Replace atNode="identifier" atField="FieldName" position="FIRST|END|n"
value="NewValue"/> |
Let's take our first example (rect.xmt) and replace after 2 seconds the rectangle by the rectangle used in our second example (rect2.xmt).
The resulting scene is : update1.xmt, update1.bt, update1.mp4.
NOTE : Although we have replaced a Shape node by a new one, the new Shape node doesn't have any identifier.
The Insert command is used to ... insert a node, a route or an SF value at a given position in an MF field.
Command Meaning |
Syntax |
|
<Replace atNode="identifier" atField="Fieldname" position="FIRST|END|n"> ... new node ... </Replace> |
|
<Replace atNode="identifier" atField="FieldName" position="FIRST|END|n" value="ValueToInsert"/> |
|
<Insert> ... route to insert ... </Insert> |
|
<Insert atRoute="identifier"> ... route to insert ... </Insert> |
Let's take the previous example (update1.xmt) and insert a circle (radius 10 pixels) centered at (20, 0) at time t=5 s. The resulting scene is : update2.xmt, update2.bt, update2.mp4 .
The delete Delete is used to delete a node, a route or an SF value at a given position in an MF field.
Command Meaning |
Syntax |
|
|
|
<Delete atNode="identifier" atField="FieldName" position="FIRST|END|n"/> |
|
<Delete atRoute="Identifier" /> |
Let's take the previous example and delete the rectangle at time t = 7 s. The resulting scene is update3.xmt, update3.bt, update3.mp4.
Exercise 6 : Create a scene with a 50-pixel radius circle centered at (0,0), a rectangle (100x200 pixels), centered at (20,20) and a square (60x60 pixels) rotated 45° centered at (-20, 20).
Exercise 7 : take one of the examples and add identifiers to all nodes.
Exercise 8 :
1. Change the TimeSensor cycle duration and modify the interpolator keys to get a smoother and faster animation.
2. Animate the rotation of a rectangle around its center.
3. Animate the fill color of the rectangle.
Exercise 9 : Replace at time t=4s the line color of the rectangle (you will have to introduce identifiers).
Exercise 10 : Take the IndexedLineSet2D example and add points and colors at time t=3s.
Exercise 11 : Take the interpolator-based example and delete a route while animating. Note what's happening.
In this part we have seen how to transform graphical objects and animate the transformations through routes and interpolators, and through BIFS commands. With these simple tools and some practice and patience, you should be able to write a cartoon entirely in BIFS.
[ Home ] [ Very Simple Scenes ] [ Animation ] [ Including Media ] |