Images Objects 3D Programming Home

Creating Motion Files

In LightWave, you can create a motion file by opening the Motion Graph for an item and hitting the Save Motion button (in versions prior to 6.0), or through the File menu (using the default menu configuration). The file LightWave writes contains the position, rotation and scale of the item at each keyframe, written in the same format used in scene files. You can later reload the file to apply this keyframe data to any item in the scene.

Motion files are text files that can be examined and modified in any text editor. Programs to create or modify motion files are useful when you have motion information obtained outside LightWave that you'd like to apply to an item in a scene. The motion data can come from motion capture equipment, sensors, or physical simulations. (I've used, for example, the positions of the Earth, Moon and Sun to visualize a solar eclipse.)

The motion file format described here is for versions of LightWave prior to 6.0. More recent versions can still load these, but they're saved in a new format, with a version number of 3. (You can find out what's in a version 3 motion file by reading the relevant sections of the scene file format documentation in the SDK.)

The File Format

Original format motion files contain

  • a 4-line header
  • one or more keyframe records, each 2 lines long

The first three lines of the header are always the same. They identify the file as a LightWave motion file, version 1, with keyframe records containing nine values. The fourth line gives the number of keyframes in the file.

A keyframe record is a list of coordinates followed by a frame number and some spline parameters. The coordinates are the x, y and z position values, the heading, pitch and bank rotation values, and scale values (sx, sy, sz) along each axis, a total of nine motion values, or channels, separated by spaces on the first line of the record. The spline parameters are the tension, continuity and bias for the keyframe, along with a linear toggle (the same values you set in LightWave's graph editor).

Let's examine the simplest possible motion file. Items in red are parts of the file that never change, and those in green are notations that don't appear in the file.

   LWMO                 LightWave Motion file
   1                    version 1
   9                    9 channels
   1                    1 keyframe
   0 0 0 0 0 0 1 1 1    x y z h p b sx sy sz
   0 0 0 0 0            frame, linear flag, T C B

This is what you get when you save the motion of an item that hasn't been keyframed yet.

All of the channel values are floating-point, with positions expressed in meters and rotations in degrees. Rotations can fall outside the principal interval (0 to 360 degrees) since they represent rotational motion and not just orientation. The linear flag, which determines whether linear or spline interpolation is used between keyframes, can be 0 (linear off) or 1 (linear on). A little later I'll expand on the tension, continuity and bias parameters, but in files generated outside LightWave these will typically be (0, 0, 0).

LightWave's coordinate system is left-handed. With X increasing to the right, +Y points up and +Z points away. Rotations are Eulerian. Heading is rotation around Y, increasing clockwise when looking down (toward -Y). Pitch is rotation around X and increases clockwise when looking toward -X. Bank is rotation around Z, clockwise when looking toward -Z.

A BASIC Program for Orbital Motion

A program that creates LightWave motion files typically reads motion data from some other source, converts it into LightWave's coordinate system, and writes the data in the motion file format. This example creates and converts its input data by calling a procedure that calculates a motion path for an elliptical orbit. qbasic keywords appear in red, comments in green.

   ' orbit.bas
   ' Ernie Wright  8 Dec 97

qbasic allows you to implicitly declare variable types according to the first letter of every variable's name. This is an idea borrowed from FORTRAN, and we'll use it to reduce the size of the program a bit by telling qbasic to assume all variables are single-precision floating-point numbers unless we say otherwise.

   DEFSNG A-Z

Forward declaration of subroutines makes it easier for the interpreter to perform type checking on the arguments when we call the routines. This subroutine calculates points on an elliptical orbit, given an orbit time between 0 and 1 and the dimensions of the ellipse. The exclamation marks in the arguments are type suffixes, qbasic shorthand identifying them as single-precision floats.

   DECLARE SUB kepler (t!, a!, b!, x!, z!)

   p = 60               'period (number of frames per orbit)
   a = 2                'semimajor axis
   b = 1.75             'semiminor axis

Layout does a funny thing with motion files. If you don't explicitly write a keyframe record for frame 0, Layout will shift the first keyframe record to frame 0. An acceptable way of handling this is to write a default keyframe 0 immediately after the four-line header and begin the real data at frame 1. It happens that in this example there's a natural way to incorporate the writing of a frame 0 record into the loop that creates all the keyframe data.

   OPEN "orbit.mot" FOR OUTPUT AS 1
   PRINT #1, "LWMO"
   PRINT #1, "1"
   PRINT #1, "9"
   PRINT #1, p + 1

The for loop gets x and z values from the kepler routine. Values for the other channels, as well as the spline control parameters, are left at their defaults.

   FOR f = 0 TO p
      CALL kepler(f / p, a, b, x, z)
      PRINT #1, x; "0 "; z; "0 0 0 1 1 1"
      PRINT #1, f; "0 0 0 0"
   NEXT

   CLOSE 1

Motion Curves

This is a brief technical description of the way Layout calculates motion values between keyframes for TCB curves (the only motion curve type supported prior to LightWave 6.0). Ordinarily it isn't necessary to understand any of this to write motion files, but you may want this information for more advanced motion projects, or simply to satisfy your curiosity.

TCB (or Kochanek-Bartels) curves are C1- and G1-continuous cubic curves based on Hermite curves. The TCB form introduces three parameters called tension, continuity and bias (whence "TCB"). Rather than changing the Hermite tangents directly, the user changes these three values to adjust the shape of the curve. The tangents are calculated from the TCB parameters in a way that ensures C1 continuity (Hermite curves are inherently only C0). The LightWave documentation gives details on the qualitative effect of each parameter.

To find a point Q(t) on the curve between the keyframes at P1 and P2, we find the tangent vectors R1 and R2 using

R1  =  s1 (1 - a1)(1 + b1)(1 + c1)(P1 - P0) + (1 - a1)(1 - b1)(1 - c1)(P2 - P1)

R2  =  (1 - a2)(1 + b2)(1 - c2)(P2 - P1) + s2 (1 - a2)(1 - b2)(1 + c2)(P3 - P2)

where ai is the tension setting, bi is the bias, and ci is the continuity at Pi. The si are scale factors that relate the time intervals of the neighboring spans to the time interval between P1 and P2. Using big T for the times at each keyframe,

s1  =  (T2 - T1) / (T2 - T0)

s2  =  (T2 - T1) / (T3 - T1)

If P1 is the first keyframe, then P0 doesn't exist, and the entire left half of the expression for R1 is taken to be 0. Similarly, when P2 is the last keyframe, P3 doesn't exist, and the right half of the expression for R2 is set to 0.

Once we have the tangents, the calculation is identical to that for Hermite curves. We find the four Hermite coefficients h0, ..., h3 for time t,

h0  =  2t3 - 3t2 + 1

h1  =  -2t3 + 3t2

h2  = t3 - 2t2 + t

h3  =  t3 - t2

The expression for Q(t) is then

Q(t)  = h0P1 + h1P2 + h2R1 + h3R2

C source code that implements Layout's keyframe interpolation is included in the envelope sample in the LightWave SDK.


© Ernie Wright