Interpolators are operators on a set of nodes of the same types that dynamically produce a blended description of these nodes. Any type of node can be blended by an interpolator, and the number of nodes is not restricted. Variables (scalar, table, or matrices) can also be interpolated.
We first define binary, random, and n-ary interpolation, and then we examine in turn leaf node interpolation, non-terminal node interpolation, and variable interpolation. The second case is the most elaborate because interpolation is percolated in parallel to all the children of the transformation node. On the contrary, leaf node and variable interpolation are non recursive and do not involve propagation by percolation.
The notion of binary interpolation is based on linear combination of values or affine combination of points. Let x1 and x2 be two values. The linear interpolation of these two values is obtained by varying a parameter α between 0 and 1:
Equation 2-1 can be straightforwardly extended to points by computing the affine combination of two points:Binary interpolation can be generalized to the interpolation of two points I1 and I2 defined as affine combinations of the two interpolated points:
In the following example, the first scheduler controls the interpolation from the first node to the second one, and the second scheduler controls the next edge that connects the second node back to the first one.
<node id="interpolator_quads"> <interpolator id="classe.1.1.2.1" type="node" size="2"> <schedule begin="0" dur="{#duree_interpolation}" repeatCount="1" mode="sinus-periodic" fill="freeze" ini="1" end="2"/> <schedule begin="{#duree_interpolation}" dur="{#duree_interpolation}" repeatCount="1" mode="sinus-periodic" fill="freeze" ini="2" end="3"/> <tabweights size="3"> <weights dim="2" index="1"> 1.0 0.0 </weights> <weights dim="2" index="2"> 0.0 1.0 </weights> <weights dim="2" index="3"> 1.0 0.0 </weights> </tabweights> <node id="quad_opaque_classe.1.1.2.1"> <quad id="quad_opaque_classe.1.1.2.1" x1="-1" y1="1" z1="-1" x2="1" y2="1" z2="-1" x3="1" y3="-1" z3="-1" x4="-1" y4="-1" z4="-1"> </quad> </node> <node id="quad_clear_classe.1.1.2.1"> <quad id="quad_clear_classe.1.1.2.1" x1="-1" y1="1" z1="-1" x2="1" y2="1" z2="-1" x3="1" y3="-1" z3="-1" x4="-1" y4="-1" z4="-1"> </quad> </node> </interpolator> </node>
Random interpolation is a special case of binary interpolation. A random interpolation is defined by a point P0 and a vector V (a small variation between two points). It begins at P0 and iteratively computes each new position as a random interpolation in the hypercube centered at the current position Mi-1 and whose corner is Mi-1+V. The random interpolation is obtained by selecting at each step as many parameters α between -1 and 1 as the number of dimensions of V. In the following formula, Vk represent the k values of the k parameters that define V.
Figure 2-3 represents the first two steps of a stepwise random interpolator. It starts at P0 and steps through M2 and M3. Each MiMi+1 vector has coordinates whose absolute values are lower than or equal to the absolute value of V coordinates.
In the following example, the interpolation starts from a null translation. At each step, the interpolator adds a random translation in the z direction, its value is a random number between -0.02 and 0.02.
<node id="blocs_de_magma"> <interpolator id="blocs_de_magma" type="transformation" size="2" interpolator_type="stepwise-interpolation"> <schedule begin="0" dur="100000" repeatCount="10000000" mode="linear" fill="remove"/> <transformation id="camera_translation_1" geometry="translation" x="0" y="0" z="0"/> <transformation id="camera_translation_1" geometry="translation" x="0" y="0" z="0.02"/> </interpolator> </node>
Both Equation 2-1 and Equation 2-2 can be generalized to an n-ary interpolation. It consists in traveling from the first vertex of a polygon to the last one along the edges. Each vertex of the polygon is a key position calculated as an affine combination of the n interpolated points. Generally, the vertices of the polygon are the n interpolated points, and the weights of the affine combinations are (1,0,...,0), (0,1,...,0),... (0,0,...,1): the n×n identity matrix.
Figure 2-4 represents a general n-ary interpolation of n points P1, P2,... Pn and its associated n×p weight matrix M. The p key positions of the interpolation polygon I1, I2,... Ip are computed by multiplying M by the column vector [Pi]. For instance, I1=1/3(P1+P2+P3). For n-ary affine interpolation, Equation 2-2 becomes:
In the following example, the interpolation has three key position. The first one is the first node, the second one is a weighted combination of the first and second nodes (close to the second node), and the third key position is the third node.
<node id="interpolator_big_square"> <interpolator id="interpolator_big_square" type="node" size="3"> <schedule begin="1" dur="100" repeatCount="1" mode="polynomial" param_sinus_polynom="2" fill="freeze" ini="2" end="3"/> <tabweights size="3"> <weights dim="3" index="1"> 1.00000 0.00000 0.00000 </weights> <weights dim="3" index="2"> 0.10000 0.90000 0.00000 </weights> <weights dim="3" index="3"> 0.00000 0.00000 1.00000 </weights> </tabweights> <use xlink:href="bib/PM/flat_square2.xml:#node body #1" /> <use xlink:href="bib/PM/folded_square.xml:#node body #1" /> <use xlink:href="bib/PM/flat_square2.xml:#node body #1" /> </interpolator> </node>
In an animation, the temporal evolution of an interpolation is controlled by a scheduler. The scheduler is defined by a begin time begin, a duration dur or an end time end=begin+dur, a repetition count count, and an animation function. The scheduler is active from begin to begin+count×dur. Before begin, the animated element is either hidden or in its initial state depending on the value of before. After termination of the schedule, the animated element is either hidden, or in its final state, or in its initial state, depending on the value of fill.
The animation function defines the values of the interpolation coefficient α in [0..1] as a function of time t. The following functions are implemented:
linear: linear time function from 0 at begin time to 1 at end time:
α(t)=(t-begin)/dur
sinusoidal: cosine time function from 0 at begin time to 1 at end time:
α(t)=0.5(cos(((t-begin)×Π/dur) - Π) + 1)
The slope of the sinusoidal function can be modified by providing an integer n (n=2 or n=3) that transforms the preceding α value by composing the time function with itself once or twice.
sinusoidal periodic: the same as above but starting from 0 and returning to 0:
α(t)=0.5(cos(((t-begin)×2Π/dur) - Π) + 1)
As with the preceding function, an integer n can also be provided here.
polynomial: polynomial time function from 0 at begin time to 1 at end time:
α(t)=((t-begin)/dur)n
In case of n-ary interpolation, several schedulers can be defined. Each scheduler controls a subpart of the interpolation: a connected subset of the edges of the interpolation polygon shown in Figure 2-4. The first active scheduler is chosen to compute the result of the interpolation if several of these schedulers are active simultaneously. It is however preferable to avoid such conflicts, and to design that are active one after another.
In the following example, the first scheduler controls the interpolation from the first node to the second one, and the second scheduler controls the next edge that connects the second node to the third one.
<node id="tc"> <interpolator id="interpolator_tc" type="node" size="3"> <schedule begin="4" before="hide" dur=".75" repeatCount="1" mode="sinus" fill="freeze" ini="1" end="2"/> <schedule begin="4.75" dur="9.25" repeatCount="1" mode="linear" fill="hide" ini="2" end="3"/> <use xlink:href="train1.xml:#node wing #1" /> <use xlink:href="commuter1.xml:#node body #1" /> <use xlink:href="commuter2.xml:#node body #2" /> </interpolator> </node>
Transformations can only be interpolated if they have the same type. If so the numerical and geometrical components of the transformations are interpolated in order to compute the object motion. For instance, the interpolation of two rotations is obtained by interpolating their angles and directions. The following example illustrates the interpolation of two translations:
<node id="vertical_translation"> <interpolator id="vertical_translation" type="transformation" size="2"> <schedule begin="(30+rand(0,5))" dur="(4+rand(0,3))" repeatCount="100" mode="linear" fill="remove"/> <transformation id="Transl1.1" geometry="translation" x="0.0" y="-80.0" z="0.0" /> <transformation id="Transl1.1" geometry="translation" x="0.0" y="80.0" z="0.0" /> </interpolator> </node>
When applied to leaf nodes that contain objects of the same type, interpolators separately compute the interpolation of all the components of these objects. For instance, when blending two spheres, an interpolator computes the interpolation of their radii and material properties. Parametric curves and surfaces with control points are blended by interpolating their corresponding control points and material properties. For instance, the blending of two ruled surfaces defined by two Bezier curves results from the blending of the control points of the curves. (Both curves must have the same number of control points.)
Interpolations concern any type of objects on leaf nodes (except crowds, graphs, and viewpoints): media objects or lights. The following extract of a VC scene is the interpolation of two spheres, material properties are not reported for the sake of clarity:
<node id="interpolator_sphere"> <interpolator id="interpolator_sphere" type="node" size="2"> <schedule begin="35" dur="0.1" repeatCount="1" mode="linear" fill="freeze"/> <node id="nightsky"> <sphere id="sphere_nightsky" radius="50.0"> </sphere> </node> <node id="deepsea"> <sphere id="sphere_deepsea" radius="5.0"> </sphere> </node> </interpolator> </node>
Non-terminal nodes can only be interpolated if they dominate two subgraphs that are isomorphic: They must have the same structure, their corresponding non-terminal nodes must be transformations of the same type, and their corresponding leaf nodes must carry the same type of media objects. If this condition is verified, the interpolation of the non-terminal nodes is percolated in parallel in their daughter nodes. Figure 2-5 illustrates a binary interpolation on two non-terminal nodes T1 and T'1 and its percolation into their two subgraphs.
The following example illustrates the interpolation of two nodes with embedded subgraphs. The transformations carried by the non-terminal nodes are omitted for simplification purposes. After interpolation percolation, the following pairs of nodes will be interpolated: (commutercylinder1, commutercylinder2), (individualcylinder1, individualcylinder2), (individual1, individual2), (body1, body2), and (cylinderfinite1, cylinderfinite2). Assuming that the external links refer to leaf nodes, the first three pairs will result in transformation interpolations, while the last two are object interpolations. Such parallel interpolations are useful for designing key scenes with identical structures without going into the details of interpolation at the node level.
<?xml version="1.0" encoding="utf-8"?> <node id="mainNode"> <interpolator id="individual_interpolator" type="node" size="2"> <schedule begin="5" dur="22.5" repeatCount="1000" mode="sinus-periodic" fill="freeze"/> <!-- 1st interpolated node --> <node id="commutercylinder1"> <node id="individualcylinder1"> <node id="individual1"> <use xlink:href="bib/commuter1.xml:#body1" /> <node id="cylinderfinite1"> <cylinder id="metrocylinder1"> </cylinder> </node> </node> </node> </node> <!-- 2nd interpolated node --> <node id="commutercylinder2"> <node id="individualcylinder2"> <node id="individual2"> <use xlink:href="bib/commuter2.xml:#body2" /> <node id="cylinderfinite2"> <cylinder id="metrocylinder2"> </cylinder> </node> </node> </node> </node> </interpolator> </node>
The current version of the browser does not accept embedded interpolations: interpolations cannot be percolated into subgraphs that already contain interpolated nodes.
Interpolator can also be defined on variables (scalar, table, or matrices). When applied to scalars interpolators compute the interpolation of the scalar values. In the case of composite variables that contain arrays of scalars (table, or matrix elements), interpolators separately compute the interpolation of all the scalars of these objects. In this case, both tables or matrices must have the same number of scalars.
Interpolations concern only numerical scalars (floats or integers). The following example is the interpolation of two float variables. An updateScript associated with the scheduler is used to modify the width of a wall according to the current value of the interpolated scalar.
<scalar id="interp_scal" type="float" > <interpolator id="interp_scal" type="scalar" size="2"> <schedule begin="0" dur="(2*{#unitaryDuration})" repeatCount="1" mode="linear" fill="freeze" > <updateScript> <command> <action> <set_node_attribute_value operator="="> <wall width="({$root:interp_scal}/2.0)" /> </set_node_attribute_value> <target type="multiple_nodes" value="#wall 1 *" /> </action> </command> </updateScript> </schedule> <scalar id="interp_scal_src" type="float" value="0.0"/> <scalar id="interp_scal_cible" type="float" value="1.0"/> </interpolator> </scalar>
The following example is the interpolation of two float 3-dimensional tables. An updateScript associated with the scheduler is used to modify the diffuse color of a media-object according to the three current values of the interpolated table.
<table id="interp_table" type="float" size="3" > <interpolator id="interp_table" type="table" size="2"> <schedule begin="0" dur="(2*{#unitaryDuration})" repeatCount="1" mode="linear" fill="freeze" > <updateScript> <command> <action> <set_material_attribute_value operator="="> <diffuse r="({$root:interp_table[1]})" g="({$root:interp_table[2]})" b="({$root:interp_table[3]})" /> </set_material_attribute_value> <target type="multiple_nodes" value="#wall 1 *" /> </action> </command> </updateScript> </schedule> <table id="interp_table_src" type="float" size="3" value="(0.0 , 0.0 , 0.0)"/> <table id="interp_table_cible" type="float" size="3" value="(1.0 , 1.0 , 1.0)"/> </interpolator> </table>