# NAME

tabinterp - combine and interpolate multiple data files to create an animation script

# SYNOPSIS

tabinterp >table.final

# DESCRIPTION

tabinterp reads a series of commands from standard input which designate what parts of various data files should be used as input tables for various channels of animation parameters. Commands may extend across multiple lines, and are semi-colon (';') terminated. Each channel is then interpolated using one of a variety of interpolation techniques to provide an output table which has one line for each time step.

The overall notion is based on parameter tables. Each table is arranged so that every row (line) represents the state of some set of parameters at a given time. Each column of the table represents a single parameter, or data channel, with the left-most column always representing time.

The first task in preparing to use tabinterp(1) is to assign specific purposes to each channel in the output table. For example, channels 0, 1, and 2 might be used to represent the X, Y, and Z positions of an object, respectively, while channels 3, 4, and 5 might be used to represent the "aim point" of the virtual camera, while channel 6 might be used to represent the brightness of one of the objects or light sources, and channel 7 might be used to represent the zoom factor (viewsize) of the virtual camera. Once the channel assignment has been decided upon, the source file containing the table of raw values for each channel must be identified. Several output channels may get their raw values from different columns of a single input table (file). Up to 64 columns of input may appear in an input table.

For each file which contains an input table, the file command is given to load the necessary columns of raw values into the output channels. If a channel number in the list is given as a minus ('-'), that input column is skipped.

file filename chan_num(s);

Using the output channel assignments given above as an example, if an input table existed in a file named "table1" which consisted of five columns of values representing (time, brightness, objX, objY, objZ), then these values would be loaded with this command:

file table1 6 0 1 2;

This command indicates that from the file "table1", the current time and four columns of parameters should be read into the raw output table, with the first input column representing the time, the second input column representing the value for output channel 6 (brightness), the third input column representing the value for output channel 0 (objX), etc. Each row of the input file must fit on a single (newline terminated) line of text, with columns separated by one or more spaces and tabs.

After all the file commands have been given, it is necessary to define over what range of time all the values just read into the the raw output table will be sent on to the interpolators, and how many rows of interpolated output should be produced for each second (time unit) in the input file.

times start stop fps;

The fps parameter can be thought of as the ``frames per second'' rate of the interpolation, and is usually set to 24 for film (cine) work, 30 for NTSC video, and 60 for field-at-a-time NTSC video. Any positive integer value is acceptable. (In fact, any time unit can be used, as the time channel is dimensionless. Nothing depends on the units being seconds.) For example, the command:

times 1 7.3 24;

would cause tabinterp to process data values from time 1 second to 7.3 seconds, producing 24 output rows uniformly separated in time for the passage of each second.

After the times command has been given, it is necessary to associate an interpolator procedure or a ``value generator'' command with each output channel. The available interpolator procedures are: step, linear, spline, cspline, and quat. The available value generator commands are: rate, accel, and next. The interpolator procedures are selected by giving commands of this form:

interp type chan_num(s);

For example, the command:

interp linear 3 4 5;

would indicate that output channels 3, 4, and 5 (representing the camera aim point) would be processed using linear interpolation. If only a starting and ending values are given in the input (i.e. the input file had only two rows), then this is an easy way of moving something from one place to another. In this case, if more than two input rows had been provided, there would be a noticeable "jerk" as the camera passed through each of the input parameter values, an effect which is rarely desired. To avoid this, the spline interpolator can be used, which fits an interpolating spline (with open end conditions) through the given data values, resulting in smooth motion. If the starting and ending values are the same, a continuous spline (with closed end conditions) can be used instead by specifying cspline. Both of the spline interpolators require at least three rows to have been provided in the input file.

If the output values are to "jump" from one input value to the next, (i.e. no interpolation at all is desired), then specify step. This can be useful for having lights switch between several intensities (for example, a 3-way bulb with 30, 70, and 100 watt settings), or for having objects "teleport" into position at just the right moment.

The interpolation method indicated on the interp command is assigned to all the output channels listed. One exception to this rule is the quat (Quaternion) interpolator. Quaternions are used to describe an orientation in space, and can be most easily thought of as containing a vector in space, from which they obtain a pointing direction, and a "twist" angle around that vector. To do this, quaternions are processed in blocks of four channels, which must be numbered sequentially (e.g. channels 7, 8, 9, 10). Giving the command

interp quat 7 15;

assigns the quaternion interpolator to two blocks of four channels, the block starting with channel 7 (e.g. channels 7, 8, 9, 10), and the block starting with channel 15.

tabinterp is strictly an interpolator. It will not extrapolate values before the first input value, nor after the last output value. The first or last value is simple repeated.

In addition to interpolation, it is possible to specify rate and acceleration based output channels. In cases where the exact running time of a scene is not known, the rate and accel commands can be quite useful. One command is given for each output channel. The rate command takes these arguments:

rate chan_num init_value incr_per_sec;

For example,

rate 6 1.5 0.5;

says to make channel 6 a rate based channel, with the initial value (at time=0) of 1.5, linearly increasing with an increment of 0.5 for the passing of every additional second (time unit). In this case, the value would be 2.0 at time=1, 2.5 at time=2, and so on. This can be used to establish linear changes where it is the increment and not the final value that is important. For example, the rotation angle of a helicopter rotor could be specified in this way.

The accel command takes these arguments:

accel chan_num init_value mult_per_sec;

For example,

accel 5 10 2;

says to make channel 5 an acceleration based channel, with the initial value at time=0 of 10.0, which is multipled by 2 for every additional second (time unit). In this case, the value would be 20.0 at time=1, and 40.0 at time=2. This can be useful to create constant acceleration, such as a car accelerating smoothly away from it's position at rest in front of a stop sign. If the initial value is zero, all subsequent values will also be zero.

Sometimes it is desirable to create an output channel which looks ahead (or behind) in time. For example, a good way to animate a rocket flying on a complex course would be to simply animate the position of the base of the rocket, and then look ahead in time to see where the rocket is going to go next in order to determine where to aim the nose of the rocket (by rotating it). This kind of lookahead is easily implemented using the next command.

next dest_chan src_chan nsamp;

(See also the fromto directive in tabsub(1) which is used in conjunction with this). The command

next 4 5 +3;

says to fill channel 4 with the values that will be present in channel 5 at 3 output rows later on. Negative values are also permitted. Since the lookahead is defined in terms of output rows rather than time units, this means that the values generated for this column will change as the frames per second (fps) value on the times command is changed. This is almost always the effect which is desired, since as the temporal resolution of the interpolation is increased, the accuracy of the look-ahead will increase as well. However, if the effect desired is one of "have the camera track where the main actor was three seconds ago", then the number of steps given here will have to be changed when the fps value is changed. Be careful of the values generated for the last (or first) nsamp output rows. Looking forward or backward in time beyond the bounds of the interpolation will retrieve the last (or first) output values. So it takes nsamp output rows to ``prime the pumps''.

Whenever a pound sign ('#') is encountered in the command input, all characters from there to the end of the input line are discarded. This is the same commenting convention used in the Bourne shell, sh(1).

When tabinterp encounters an end-of-file on it's standard input, it computes the requested interpolations, and writes the output table on standard output. If no values have been assigned to an output channel, then the value given is a single dot ('.'). This preserves the positional white-space-separated columns nature of the output table. If this column is read as a numeric value by a downstream program, it will be accepted as a valid floating-point zero.

As an aid to debugging, it is possible to dump the raw values of columns of the output table before the interpolation is run:

idump;
idump chan_num(s);

If no output channel numbers are given, all channels are dumped, otherwise only the indicated channels are dumped.

The help command can be given to get a list of all available commands. (Don't forget the semi-colon).

# OPTIONS

-q
  enables quiet mode. This option suppresses the status messages that are normally printed on standard error.

# EXAMPLE

What follows here is a Bourne shell script which will generate two input tables using ``here documents'', and will then produce an interpolated output table of 8 channels.

    #!/bin/sh
    cat << EOF > table.aim
    -1   0 0 0    42 250
    3    1 2 3    28 300
    7    3 4 5    17 350
    EOF
    cat << EOF > table.obj
    0    17 38 44
    2    43 47 3
    4    99 23 18
    EOF
    tabinterp << EOF > table.final
    # Channel allocations:
    #	0,1,2	objX, objY, objZ	main actor position
    #	3,4,5	aimX, aimY, aimZ	camera aim point
    #	6	light brightness
    #	7	viewsize
    #
    # Input table column allocations:  time, aimX, aimY, aimZ, junk, viewsize
    file table.aim 3 4 5 - 7;
    #
    # Input table column allocations:  time, objX, objY, obxZ
    file table.obj 0 1 2;
    # Channel 6 is not read in here, but is rate base.
    #
    # Tstart, Tstop, fps
    times 0 4 30;
    #
    # Assign interpolators to output channels
    rate 6 1000 50;			# 1000 lumen bulb keeps getting brighter...
    interp linear 0 1 2;
    interp spline 3 4 5;
    interp spline 7;
    EOF

Try clipping this example out of the manual page (usually found in /usr/brlcad/man/man1/tabinterp.1) and running it. This example will be continued in the manual page for tabsub(1).

# "POST PROCESSING"

Because both the input and output tables consist of a single line of text for each time step, many of the standard UNIX tools can be brought to bear to assist in creating an animation. To visualize the exact position taken by the aim point in the example (output channels 3, 4, 5), a UNIX-plot file of that trajectory can be created with:

cut -f5,6,7 table.final | xyz-pl > aim.pl
cut -f1,5,6,7 table.final | txyz-pl > aim.pl

Similarly, the position of the main object can be viewed with

cut -f2,3,4 table.final | xyz-pl > obj.pl

tabinterp uses 0-based column numbering, while cut uses 1-based column numbering. Also, the first output column from tabinterp is always the time. The 0-th data column comes second.

The plot file just created can be viewed using pl-fb(1) or pl-sgi(1), or it can be viewed in mged(1) by giving the command

overlay aim.pl

to mged. If the model geometry is brought into view using the mged e command, then the camera aim track (or any other spatial parameter) can be viewed in direct relationship to the three dimensional geometry which is going to be animated.

# "PREPARING INPUT TABLES"

The mged(1) savekey and saveview commands can be very useful for creating the input tables necessary for driving tabinterp. The details of doing this are beyond the scope of this manual page.

The awk(1) command can also be useful for routing through the output files of existing scientific analysis programs, and extracting the few gems of data burried in the heaps of ``printout''.

# "SEE ALSO"

tabsub(1), xyz-pl(1), txyz-pl(1), cut(1), paste(1), rt(1), mged(1)

# BUGS

You can't grep dead trees.

# AUTHOR

Michael John Muuss

# SOURCE

The U. S. Army Research Laboratory
Aberdeen Proving Ground, Maryland 21005

# "BUG REPORTS"

Reports of bugs or problems should be submitted via electronic mail to <devs@brlcad.org>.