Keyframe Animator - animate geometry objects using frame interpolation

Name

	Keyframe Animator - animate geometry objects using frame interpolation

Summary

	Name	Keyframe Animator (V2.40)
	Type	mapper
	Inputs	integer (optional) -- animate pulse in
		struct upstream_transform (invisible) -- mouse information in
		struct upstream_geom (invisible) -- pick information in
	Outpts	geom -- object transformations
		integer (invisible) -- animate pulse out
	Parms	Name		Type		Description
		>>>		string		value of current attribute
		obj attributes	choice		object attribute selector
		new obj		oneshot		add a new object to the list
		del obj		oneshot		delete current object from list
		pick obj	boolean		turn on/off object picking
		next obj	oneshot		animate next object in the list
		XROTon		boolean		X rot interpolation is active
		YROTon		boolean		Y rot interpolation is active
		ZROTon		boolean		Z rot interpolation is active
		XTRNon		boolean		X trans interpolation is active
		YTRNon		boolean		Y trans interpolation is active
		ZTRNon		boolean		Z trans interpolation is active
		SCLEon		boolean		scale interpolation is active
		ALLon		oneshot		turn on all "XXXXon" buttons
		ALLoff		oneshot		turn off all "XXXXon" buttons
		init dials	oneshot		resets active dials to def vals
		update frame	boolean		current frame update on/off
		animation frame	integer		changes the current frame
		<--		oneshot		move back a frame
		-->		oneshot		move forward a frame
		prev key	oneshot		jump backward to prev keyframe
		next key	oneshot		jump forward to next keyframe
		anim speed	integer		sets skip value for playback
		anim start	integer		sets the start of anim window
		anim end	integer		sets the end of anim window
		save keyframe	oneshot		saves position as keyframe
		ease in		boolean		create interpolation ease-in
		ease out	boolean		create interpolation ease-out
		create interp	oneshot		interpolates animation window
		create sp intrp	oneshot		spline interpolates window
		create hold	oneshot		copies a frame to entire window
		trace obj path	boolean		traces translations in window
		clear keyframe	oneshot		unmark a frame as keyframe
		clear all keys	oneshot		unmark all frames as keyframes
		clear frme info	oneshot		clear info from anim window
		anim filename	string		filename for save and load 
		load anim	oneshot		load an animation file
		save anim	oneshot		save an animation file
		sync wth driver	boolean		disables transformation dials
		wait for sync	boolean		wait for a specified anim pulse
		sync frme	integer		the sync pulse to wait for
		rot x		real		X rotation transformation dial
		rot y		real		Y rotation transformation dial
		rot z		real		Z rotation transformation dial
		trans x		real		X translation transform dial
		trans y		real		Y translation transform dial
		trans z		real		Z translation transform dial
		scale		real		proportional scale transf dial
		curr frame	integer		current frame dial

Description

	The Keyframe Animator module is used to animate objects which are
	displayed through Render Geometry and the Geometry Viewer subsystem.
	It works by supplying a transformation matrix to the Render Geometry
	module for any object which has been loaded into the Geometry Viewer
	or supplied to the Render Geometry module's geom input.  Generally,
	the Keyframe Animator's geometry output (the transformation matrix)
	is supplied to the geometry input of Render Geometry.  The Keyframe
	Animator does not know whether or not the specified object actually
	exists, so it is up to the user to make sure that the geometry has
	been supplied to the Geometry Viewer.  This can be verified by going
	into the Geometry Viewer (under the Data Viewer's pulldown menu of
	the Network Editor), and clicking on the small square in the current
	object selector (the bar above the small object window) to get a list
	of the objects for the currently chosen window.  To see the list of
	objects for a different window, click in that window.  These object
	names should be preceeded by a percent symbol (%) in the Keyframe
	Animator.  For example, to control an object called "dodec.14", you
	would use "%dodec.14" as the object name in the Keyframe Animator.
	(Make sure that the "object attribute" selector is on "name" and then
	type the object name in the text input marked with ">>>").  Cameras
	and lights can also be animated by using the name "%camera" or
	"%light" followed by the camera or light number.  For example,
	"%camera1" will animate the first camera and "%light3" will animate
	the third light.  The "%top" object is special since it will affect
	ALL of the objects in the window (including the "trace path" object,
	discussed below).  Usually, the "%top" object will be disabled so that
	it cannot be animated.  Instead of typing in the name of the object,
	you can use the mouse to pick the object you want to animate.  Turn
	on the "pick obj" button and use the left mouse button to click on
	the object in the display window.  You will then be asked if you want
	to add the object, replace the current object, or abort.  Press
	"REPLACE OBJ" to animate the new object.  See below for more details
	on the other options.  Clicking in the background of the display
	window with the left mouse button will allow you to animate the
	camera for that window.  You should always use "del obj" to remove
	the object or camera from the Keyframe Animator's control before you
	throw away the Keyframe Animator module (by dragging it onto the
	hammer in the Network Editor).
	The Transformation Dials:
	The object can then be rotated, translated, and scaled interactively
	with the Keyframe Animator's "transformation dials" ("rot x",
	"trans x", "scale", etc.).  When you first drag the "Keyframe
	Animator" icon into the work area of the Network Editor, a menu named
	"Transform Dials" will automatically be created along with the
	Keyframe Animator's menu.  This menu will contain the Dialbox
	Manager, with the "transformation dials" added to it.  If you don't
	have a dialbox connected to your computer, it may be necessary to
	drag the "transformation dials" out of the Dialbox Manager (using the
	"Layout Editor" menu of the Network Editor), so that they are no
	longer controlled by a real dialbox.  The object can also be
	transformed using the mouse in the display window.  Use the middle
	mouse button to rotate the object and the right mouse button to
	translate the object.  Holding either SHIFT key while pressing the
	right mouse button will translate the object in the Z direction.
	Holding the SHIFT key while pressing the middle mouse button will
	scale the object.  The left mouse button should ONLY be used to
	change the object you wish to animate (see above).  Moving the
	object with the mouse will change the appropriate transformation
	dial.  The "initialize dials" button will reset the transformation
	dials to their default values.  If you change the object's name to
	change which object is being animated, the old object will remain
	frozen in whatever position you left it.  You might want to press the
	"initialize dials" button to move the object back to its original
	position before changing the object you are animating or deleting an
	object (with "del obj").  There is a special transformation dial
	called "curr frame" which is only useful if you have a hardware
	dialbox.  This dial allows you to control the "animation frame" slider
	(see below) using the dialbox instead of the mouse.
	Keyframe Animation Interpolation:
	Keyframe animation is done by saving certain key object positions
	called "keyframes" and allowing the Keyframe Animator to interpolate
	the in-between timesteps or "frames."  This is done by moving the
	object to the desired key position, moving the "animation frame"
	slider to the timestep at which you want that object at that position,
	and pressing the "save keyframe" button.  Then, choose another keyframe
	position in the same manner, by moving the object to the chosen
	position, moving the animation frame to the desired timestep, and
	pressing the "save keyframe" button.  Any number of keyframes can be
	set at various timesteps.  Pressing the "create linear interpolation"
	button will fill in the empty frames based on straight lines between
	the keyframe positions, thus creating an animation.  Pressing "create
	spline interpolation" will instead fill in the empty frames based on
	a smooth curve which goes through all keyframes.  The "ease in" and
	"ease out" buttons are used to make an object gradually speed up and
	slow down near the beginning or end of it's path.  If "ease in" is
	lit when doing a linear or spline interpolation, the object will
	gradually speed up between the first frame and the first keyframe set.
	Similarly, if "ease out" is lit, the object will slow down between
	the last keyframe set and the last frame of the animation.  The
	"create hold" button will copy the object's currently saved position
	(the position which has been saved for the object at the current
	frame) to all the other frames in the animation.  This can be used
	as an alternative to "create linear interpolation" or "create spline
	interpolation" for objects which remain in one place during the
	animation.
	The "Trace Object Path" Button:
	After interpolating, turning on the "trace object path" button will
	trace the path that the object will take through the animation and
	show you the path as a curved line.  Turning the button off will
	remove the trace from the screen.  To recalculate the trace after
	changing an animation, you must turn the button off, then turn it
	back on.  Keep in mind that the trace is itself an object (named
	"ANIM-Trace"), so it is possible to try to animate it with strange
	results.  Also, animating the "%top" object will have similar results,
	as will attempting to trace the path of the camera ("%camera1").
	Therefore, if you want to use the "trace object path" button, it is
	recommended that the object you are animating NOT be the "%top"
	object, the "ANIM-Trace" object, or a camera.
	The "Update Frame" Button:
	To see the saved position of an object at any frame, move the
	"animation frame" slider to the desired frame and make sure that the
	"update frame" button is lit.  When this button is lit, the object
	will move to the saved values from the interpolation or the keyframe
	values saved with the "save keyframe" button.  The "update frame"
	button automatically lights up during certain operations such as
	"create linear interpolation", "create spline interpolation", and 
	"create hold" and automatically unlights when a	transformation dial
	is moved, so that you will see the object move with the dial rather
	than stay at the saved position.
	Moving Around Your Animation:
	The "-->" and "<--" buttons can be used to step through frames of
	the animation by increasing or decreasing the current animation frame
	number.  The "prev key" and "next key" buttons can be used to jump
	to the previous or next	keyframe.  The "animation speed" slider can
	be used to make the arrow buttons increase (or decrease) by more than
	one frame.  Negative values will cause the animation to run backwards
	(it will in effect switch the meanings of the two arrow buttons).
	If the current frame goes beyond the "anim end" value (the largest
	value which can be displayed by the "animation frame" slider), it
	will "wrap around" and the current frame will be the "anim start"
	value.  Similarly, the frames will wrap around the other direction
	if you are stepping through the animation backwards.
	Clearing Keyframes and Frame Information:
	It may be desirable to unmark certain frames so that they are no
	longer thought of as keyframes for interpolation.  Use the "clear
	keyframe" button to mark the current frame as not being a keyframe,
	and use the "clear all keyframes" to clear all keyframes.  The
	"clear frame information" button is used to wipe out all of the
	saved transformations in the animation (set them to their default
	values), including the keyframes, although it does not change whether
	or not a frame is a keyframe.  They keyframes themselves will still
	exist, but the information saved for the keyframes will be cleared as
	well as the information	stored for all the in-between frames.
	Use the "clear frame information" button with caution!
	Loading and Saving Your Animation:
	To save an animation, type in the name of the animation in the
	"anim filename" text input, and press the "save anim" button.  If the
	file already exists, you will be asked if you wish to replace it.
	To load the animation back in, make sure that the correct filename has
	been typed in the "anim filename" text input, and click the "load anim"
	button.  You will be given several choices at this point.  You can
	replace whatever animation might currently be in memory by pressing
	the "LOAD" button (this is usually what you will want to do).  The
	"MERGE" and "APPEND" buttons are discussed in the ADVANCED TOPICS
	below.  The "update frame" button will automatically light after the
	load so that you can immediately see the new animation.
	ADVANCED TOPICS:
	More About the "Update Frame" Button:
	The "update frame" button, when lit, forces the transformation dials
	to reflect the saved position, which in turn moves the object to that
	position.  When it is turned off, the transformation dials will remain
	set to the saved values until you move them.  This can be used to move
	an object relative to a saved position by turning "update frame" on
	and off (actually, since the button automatically turns off when a
	dial is moved, it isn't necessary to turn it off by hand), moving the
	object relative to its current position, changing the "animation
	frame" number, and saving the new position as a keyframe.
	The "Animation Window":
	More frames can be added to an animation by increasing the "anim end"
	value.  The "anim end" and "anim start" inputs also change the
	frames which are selectable with the "animation frame" slider.  The
	frames within the "anim start" and "anim end" values comprise the
	current "animation window."  No frames outside the window can be
	selected with the "animation frame" slider without changing the "anim
	start" or "anim end" values.  Certain operations such as "clear frame
	information", "create linear interpolation", "create spline
	interpolation", "create hold", and "trace object path" will affect
	only the frames within the current animation window for the current
	object (see Handling Multiple Objects below).  The current "start
	frame" and "end frame" are automatically defined as keyframes before
	interpolation.  When you press "save anim" to save your animation,
	if the current "animation window" is smaller than the number of
	frames that have been defined for the animation, you will be asked
	if you want to save ONLY the animation window, or if you want to save
	the entire animation.
	"Active" Transformation Dials:
	Note that when a transformation dial is moved, it's corresponding
	"active button" ("XROTon", "YTRNon", "SCLEon", etc.) is automatically
	lighted.  The reason for this is that when you create an interpolation
	by pressing "create linear interpolation", "create spline
	interpolation, or "create hold" (and also "clear frame information")
	only those transformations which are lighted will be interpolated.
	The others will remain unchanged.  Therefore, it is possible to control
	exactly which transformations will be interpolated by manually turning
	on and off individual "active buttons," or turn them all on with the
	"ALLon" button, or turn them all off with the "ALLoff" button.
	Furthermore, many of the other operations which	affect the
	transformations will affect only those which are currently active.
	For example, "initialize dials" will only initialize those
	transformation dials which are active, and the "save keyframe" button
	will save only the transformation values which are active.
	Handling Multiple Objects:
	More than one object may be animated at a time.  Use "new obj" to
	create an "EMPTY" object.  You should then change its name by typing
	in a new name in the text area marked ">>>".  Note that the Keyframe
	Animator will automatically ignore objects which begin with "EMPTY"
	in all caps, so the Geometry Viewer will not complain that it doesn't
	know of	an object called "EMPTY-2".  Use "del obj" to change the 
	current object to an "EMPTY" object.  Use "next obj" to make another
	object the current object.  When dealing with more than one object,
	the transformations only affect the current object, and the positions
	of all non-active objects are always updated whether or not "update
	frame" is on.  After pressing "next obj" to make a new object the
	current object, the "update frame" button will automatically light to
	show you the saved position of the new object.  When you press
	"save anim" to save your animation, if any of the objects begin with
	"EMPTY" you will be asked if you want to save ONLY objects which are
	NOT "empty," or if you want to save ALL the objects (including ones
	whose names begin with "EMPTY").  This allows you to, in effect,
	delete objects by simply naming them "EMPTY" so they won't be saved
	with the rest of the objects if you don't want them to be.  If all of
	the objects currently defined begin with "EMPTY" they will always be
	saved, and you will not be given the choice.  Most operations such as
	creating interpolations, "trace object path", and "clear frame
	information" affect only the current object.
	Picking:
	Instead of using the "new obj" and "next obj" buttons, you can use
	the mouse to make a particular object current, add a new object, or
	change the name of the current object.  To pick an object, turn on
	the "pick obj" button, then use the left mouse button to choose the
	object in the display window.  You can also click either the middle
	or right buttons on the mouse (without dragging the mouse in the
	display window) to turn on and off the "pick obj" button.  Then, by
	clicking on the object in question with the left mouse button in the
	display window, you can make that object the current object.  Clicking
	in the background of a window will make the camera associated with
	that window the current object.  If the object doesn't currently exist
	as one of the objects you are animating, you will be asked if you want
	to add it or replace the current object.  Press "ADD OBJ" to add the
	object to the other objects you are animating.  Press "REPLACE OBJ" to
	change the name of the current object to the new object.  Press
	"ABORT" to do nothing.  When the "pick obj" button is off, you will
	not be able to choose objects you are animating with the left mouse
	button.  However, you CAN move objects that are not currently under
	control of the Keyframe Animator.  When you delete an object with the
	"del obj" button, or change the name of the current object to another
	object, the old object will be restored to its normal picking
	status (you will be able to pick and move it reguardless of the
	"pick obj" button since it will no longer be controlled by the
	Keyframe Animator).  However, if you throw away the Keyframe Animator
	module by dragging it onto the hammer in the Network Editor,
	objects that were under the control of the Keyframe Animator will
	be stuck in strange picking and transformation modes.  It is therefore
	recommended that you delete all objects before throwing away the
	Keyframe Animator module.
	Object Attributes:
	The "object attributes" selector allows you to choose which of the
	four object attributes you wish to view or change.  The current
	value of the attribute you select will be displayed in the text
	input marked with ">>>".  To change the value of the attribute,
	simply type in a new value.  The "name" attribute allows you to
	see or change the object that the current transformations will affect.
	The "parent" attribute allows you to see or change the object's
	parent (see below).  The "rotation" selector allows you to change
	the type of rotation from quaternion to matrix rotation (see below).
	Any value beginning with an "m" or an "M" will change the rotation
	type to "matrix".  Anything else changes it to quaternion rotation
	which is the default.  The "colortype" attribute is not currently
	used, but will be used to change the color system when animating
	object's colors (to be implimented in a future release).  Anything
	beginning with an "h" or "H" will change the color type to the HSV
	(Hue-Saturation-Value) color system.  Input any other value for the
	RGB (Red-Green-Blue) color system (the default).
	About Parenting:
	Parenting is a powerful way of creating complex moves.  An object will
	always move in relation to it's parent's transformations, so if object
	"%dodec.1" has a parent "%harmonic.2", moving object "%harmonic.2"
	will affect both objects while moving object "%dodec.1" will affect
	only "%dodec.1".  In other words, a "parent" will affect it's
	"children" which will in turn affect their "children" and so on
	(thus a parent will affect all of it's "offspring").  When you press
	the "trace object path" button, the "ANIM-Trace" object is
	automatically parented to the current parent, so that the trace will
	reflect the current object's true path.  Unpredictable results can
	occur if you create a "parenting loop" (by assigning an object's
	"offsprings" as a parent of that object).  Parenting an object to
	itself is not advised.  Assigning the "ANIM-Trace" object as a parent
	is also not advised.  Objects that have been parented to other objects
	will remain parented to those objects even if you change the "name"
	attribute to control a different object.  You should probably change
	an object's parent back to "%top" before assigning a new value for the
	"name" attribute.  Note that the "%top" object is always at the top
	of the "family tree."
	About Quaternion Rotation:
	There are two types of rotation which can be used to interpolate
	the position of objects:  regular rotation and quaternion rotation.
	Regular rotation uses the traditional X, Y, and Z transformation
	dials which are accumulated before combining them in a transformation
	matrix.  This has two unfortunate side effects.  One, using absolute
	rotation values can create a problem sometimes known as "gimbal lock,"
	the loss of a degree of rotational freedom when trying to rotate an
	object to certain positions.  The other unfortunate side effect is that
	interpolation will not choose the shortest rotation path between
	two positions, but will rather linearly interpolate the X rotations,
	the Y rotations, and the Z rotations separately, then concatenate
	the three matrices to create the final rotation transformation.
	Quaternion rotation solves both of these problems.  One, objects
	can be rotated intuitively (an X rotation always rotates around
	the horizontal, a Y rotation around the vertical, and a Z rotation
	perpendicular to the screen).  Also, quaternion interpolation chooses
	the shortest path between two positions.  The only drawback to using
	quaternion rotation is that the object must be rotated less than 360
	degrees or the shortest path will then be in the opposite direction.
	The work around to this is to save intermediate keyframes so that the
	rotations between keyframes are	always less than 360 degrees.  The
	"rotation" attribute is provided to allow either type of rotation.
	The type of rotation used is saved for each object, so it is possible
	to use regular rotation for one object, and quaternion rotation for
	another.  When the "rotation" attribute is changed, the	"XROTon",
	"YROTon", and "ZROTon" buttons always unlight.  In addition, the
	object will reflect the currently saved	rotation for the type of
	rotation specified.  Note also that when you are using quaternion
	rotation, the "XROTon", "YROTon", and "ZROTon" activity buttons all
	act as a single "rotation" button since it makes no sense to
	interpolate each separately.  When you press any of them, the others
	will also change state.  Spline quaternion rotation is not yet
	implimented, so if "create spline interpolation" is pressed while
	using quaternion rotation, the rotation will be linearly interpolated
	while the other transformations will be correctly spline interpolated.
	More on the "Load Anim" Operation:
	During a "load anim" operation, three options are presented aside from
	replacing the animation currently in memory.  The "MERGE" button will
	allow you to merge the file with the animation currently in memory,
	thus adding to the objects in memory rather than overwriting them.
	"APPEND" will add the frames stored in the file to the end of the
	frames currently in memory, but will ignore the object names in the
	saved file, appending the frames for the first object in the file to
	the frames of the first object in memory, and so on.  Use "ABORT" to
	abort the loading process and return to the Keyframe Animator.
	If the file you are loading was created with an older version of
	the Keyframe Animator, a warning will be given when the file is
	loaded.  You can then abort the load, or attempt to load the file
	anyway.  There is no guarantee that files created by different
	versions of the Keyframe Animator will be the same (but chances are
	they will).  You can examine the file and compare it against the 
	format described below in the ANIMATION FILE FORMAT section at the
	end of this documentation.
	Attaching a Driver Coroutine to the Keyframe Animator:
	It is possible to view an animation without having to repeatedly
	press the "-->" key or manually move the "animation frame" slider.
	The "animation pulse" inputs allows an integer to be supplied by
	a "driver" coroutine module (such as "animated integer"), causing the
	current animation frame to be increased or decrease by the "animation
	speed" value every time the pulse is received.  See INPUTS and EXAMPLES
	below.	The "sync with driver" button, "wait for sync" button,
	and "sync frme" text input are only useful if the Keyframe Animator's
	"animation pulse" input is connected to a driver module or to a
	downstream record module.  When lit, the "wait for sync" will cause
	the Keyframe Animator to wait for a specific integer at its
	"animation pulse" input before it will begin incrementing the
	"animation frame".  The integer which the Keyframe Animator will wait
	for is specified with the "sync frme" text input.  When this integer
	is received, the "wait for sync" button will automatically unlight,
	the current animation frame will be incremented, and subsequent
	integers (reguardless of their values) will be taken as pulses and
	will cause the current animation frame to be incremented.  While
	running an animation using a driver coroutine, you might want to
	disable the transformation dials so that they are not accidentally
	changed while the animation is in progress because if they are
	changed, the "update frame" button will turn off causing the
	animation to stop.  It is especially crucial while recording an
	animation to video that the transformations not be changed
	accidentally.  For this reason, the "sync with driver" button,
	when lit, will disable the dials from turning off the "update frame"
	button.  The "update frame" button will automatically be turned on
	when "sync with driver" is turned on, allowing you to view or record
	the stored animation using a driver coroutine.

Inputs

	Animation pulse in (integer).
	The "animation pulse" input is an integer, usually supplied by a
	coroutine module which repeatedly sends integers in order to drive the
	Keyframe Animator.  Each time the Keyframe Animator receives an
	integer into the "animation pulse" input, the current frame is
	incremented (or	decremented) by the "animation speed" value (this is
	identical to manually pressing the "-->" button).  This will have the
	effect of playing back a saved animation without having to press the
	"-->" button repeatedly, or manually slide the "animation frame"
	slider.  Note that the "update frame" button must be lit in order to
	view the animation.  The "animated integer" module supplied with AVS3
	serves nicely as an animation driver by simply connecting its output
	to the "animation pulse" input of the Keyframe Animator, by pressing
	the "animated integer" module's "Continuous" button, and by turning its
	"sleep" button off.  Turning "sleep" on again will allow the user to
	regain manual control of the Keyframe Animator.  See the EXAMPLE
	networks below.  When recording your animation to an external device
	such as a Lyon-Lamb Minivas videotape controller or a Sony Laser
	Videodisc recorder, the "animation pulse" input can be used to
	synchronize the recording process.  Presumably, a module used to
	record an animation and control the external devices will take
	as input a pixmap from "render geometry" so that it can tell when the
	image has changed, and will produce an integer pulse output when the
	frame has been recorded to videotape or videodisc.  This output would
	then be fed upstream to the Keyframe Animator to complete the loop,
	causing it to produce the next frame of the animation.  See the EXAMPLE
	networks below.
	Upstream trans in (struct upstream_transform) -- invisible.
	This is the input used to receive mouse movements from the "render
	geometry" module in order to transform an object with the mouse.
	This invisible input will automatically be connected to the "render
	geometry" invisible "upstream_transform" output when the "Keyframe
	Animator" module is connected to the "geometry" input, of "render
	geometry" so the user does not have to connect it by hand.
	Upstream geom in (struct upstream_geom) -- invisible.
	This is the input used to receive pick information from the "render
	geometry" module.  This invisible input will automatically be
	connected to the "render geometry" invisible "upstream_geom" output
	when the "Keyframe Animator" module is connected to the "geometry"
	input, of "render geometry" so the user does not have to connect it
	by hand.

Outputs

	Transformation matrices (geom).
	Every time the Keyframe Animator module fires, it produces a
	transformation matrix for each object as geometry which is then fed
	to a module which accepts geometry such as "render geometry".
	Animation pulse out (integer) -- invisible.
	This output can be used as input to other modules which might need
	to receive a pulse at each frame of an animation.  The integer sent
	is the current "animation frame" value, so it can also be used to
	let user-defined modules know what frame the Keyframe Animator is on.
	This output is invisible since it is sledom used.

Examples

	Simple animation network:
	The "animated integer" module is used as the driver for the animation.
	Objects are loaded in via the "Geometry Viewer" subsystem's "Read
	Object" button (the "Objects" button must be lit in the
	"Menu Selection" section before the "Read Object" button is visible).
	Once loaded, the objects can be animated using the Keyframe Animator,
	and the animation can be played back by choosing "Continuous" playback
	and turning off "sleep" for the "animated integer" module:
	
			       animated integer
			              |
			              |
			      Keyframe Animator
			              |
			              |
			       render geometry
			              |
			              |
			       display pixmap
	Network to record an animation to an external device:
	The Keyframe Animator waits for the "Record Animation" module to
	send it a pulse after the current frame has been stored to the
	videotape or videodisc.  The "Record Animation" module waits for
	"render	geometry" to complete the rendering process and send the pixmap
	downstream before it fires and records the frame:
	              ,---------------------------------------.
	              |                                       |
	              V                                       |
	      Keyframe Animator                               |
	              |                      (upstream pulse) |
	              |                                       |
	       render geometry                                |
	              |                                       |
	              |------------------.                    |
	              |                  |                    |
	       display pixmap     Record Animation            |
	                         (to record to tape or disc)  |
	                                 |                    |
	                                 `--------------------'
BUGS
	Due to bugs in AVS3, slider widgets don't always work properly in
	immediate mode.  Since the "animation frame" slider is immediate,
	the bug will show up with the Keyframe Animator.  If you SLIDE the
	slider button to a value, then CLICK to another value, the second
	value isn't registered, even though the slider button moves to that
	value.	If you press "-->", for example, the slider value will jump
	to the frame following the first value.
	Another bug associated with immediate sliders affects only those
	sliders which contain negative values.  In this light, the
	"animation speed" slider is affected.  Even though the slider is
	actually defined to go from -50 to 50, it goes from -49 to 50.
	Also, there are two positions which display as zero, but only one
	of them actually puts out a zero value (the second zero registers a
	value of -1).  All other negative values are off by one.  For example,
	if the slider shows -2, it is actually putting out a value of -1.
	Furthermore, the slider will not move all the way to the last
	negative value, so you can only choose up to -48 (which will then
	actually register -49).  It is impossible to get the slider to
	put out the lowest negative value it has been programmed to (-50 in
	this case).
	If you try to animate an object which doesn't exist in the Geometry
	Viewer, the Geometry Viewer will barrage you with lots of dialog
	boxes telling you of the problem.  At present, there is no way for a
	module to query the Geometry Viewer to make sure that the object
	exists.
	Because of the way AVS handles picking and transformations of objects,
	objects can get stuck in undesirable selection and transformation
	modes when the Keyframe Animator module is thrown away.  You can
	use "del obj" to delete each of the objects before throwing the
	module away to avoid this problem.  However, the "%top" object will
	always remain unpickable and untransformable after you throw away the
	module.  This is a limitation in AVS and there is no fix to this
	problem.
	It would be more convenient to not have a "picking mode" (the
	"pick object" button) to do picking, but instead simply pick the
	desired object with the left mouse button.  However, AVS makes
	it very difficult to track the mouse in order to override AVS's
	default mouse transformations of the objects, so as a result things
	don't always work as you would like them to.  Because of the fact
	that there is no way to detect such things as mouse button presses
	or keyboard presses in AVS without making Xwindows calls, things
	don't always work as you would expect.  In short, the picking
	and object manipulation with the mouse works well, but is a hack
	to overcome some shortcomings in AVS.
	Occasionally, after you pick an object, AVS will not allow you to
	transform the object with the mouse until you click the left mouse
	button in the display window again.
FUTURE ENHANCEMENTS
	The Keyframe Animator will be able to do spline quaternion
	interpolation.
	Objects can be loaded in through the Keyframe Animator instead of
	having to load them in via the Geometry Viewer subsystem.
	Improved rotation, translation, and scaling of objects with
	the mouse (also see BUGS above).  At the moment, I am using a
	fairly naive algorithm to achieve trackball rotation, so it is
	difficult to do a Z rotation with the mouse.  The algorithms
	for doing transformations with the mouse are not exactly the same
	as the ones used by AVS, so the object will not transform exactly
	as expected with the Keyframe Animator.

Related modules

	animated integer, render geometry, display pixmap
		see AVS3 documentation for more information.
	animate-driver, written by Brian Kaplan
		works similarly to "animated integer" but accepts an optional
		integer pulse input, allowing a full animation network to be
		set up that will allow both automated viewing of the animation
		and recording to an external device with a record module such
		as Record Animation.
	Record Animation, written by Brian Kaplan
		allows recording to Lyon-Lamb Minivas and Sony Laser
		Videodisc devices.
	created by Brian Kaplan
		kaplan@cica.cica.indiana.edu
		Center for Innovative Computer Applications (CICA)
		Indiana University
ANIMATION FILE FORMAT
	The Keyframe Animator stores its files in a simple ASCII format.
	The file contains a version number of the Keyframe Animator module
	that produced it (VERSION).  On the following line are the number of
	frames in the animation (NFRMS) and the number of objects (NO).
	The following  lines consists of the object list, one object
	per line.  On each line are the object number (OBJ##), name of the
	object (%NAME), parent of the object (%PARENT), the rotation type
	used by the object , and color system used by that object
	(COLORSYS).  Following the object list is the animation frame list.
	Each of the  frames in the the frame list contains the frame
	number (FRAME#####) and whether or not that frame is a keyframe (KEY)
	on a line, followed by transformations for each object in the
	animation.  The transformations consist of four lines each.  The first
	contains the object number (OBJ##) and scale for that object (SCLE).
	The second line contains the matrix rotation values for that object
	(XROT, YROT, ZROT).  The third line contains the quaternion rotation
	values for the object (QTRC, QTRX, QTRY, QTRZ).  The last line of
	each transformation section contains the translation values for the
	object (XTRN, YTRN, ZTRN).
	The file looks like this:
	VERSION
	NFRMS NO
	obj01: %NAME %PARENT ROTTYPE COLORSYS
          :
          :
        objNO: %NAME %PARENT ROTTYPE COLORSYS
	frame00001: KEY
	     obj01: SCLE
	            XROT YROT ZROT
	            QTRC QTRX QTRY QTRZ
	            XTRN YTRN ZTRN
                :
                :
	     objNO: SCLE
	            XROT YROT ZROT
	            QTRC QTRX QTRY QTRZ
	            XTRN YTRN ZTRN
	   :
	   :
	frameNFRMS: KEY
	     obj01: SCLE
	            XROT YROT ZROT
	            QTRC QTRX QTRY QTRZ
	            XTRN YTRN ZTRN
                      :
                      :
	     objNO: SCLE
	            XROT YROT ZROT
	            QTRC QTRX QTRY QTRZ
	            XTRN YTRN ZTRN
	
	Here is a portion of an actual animation file:
	V2.30
	150 4
	obj01: %camera3 %top quaternion RGB
	obj02: %harmonic.7 %top quaternion RGB
	obj03: %math123 %top quaternion RGB
	obj04: %camera2 %top quaternion RGB
	frame00001: 1
	     obj01: 1.000000
	            0.000000 0.000000 0.000000
	            1.000000 0.000000 0.000000 0.000000
	            0.000000 0.000000 0.000000
	     obj02: 1.000000
	            0.000000 0.000000 0.000000
	            0.760406 -0.649448 0.000000 0.000000
	            -345.000000 270.000000 0.000000
	     obj03: 1.000000
	            0.000000 0.000000 0.000000
	            0.833886 0.551937 0.000000 0.000000
	            -78.000000 -300.000000 0.000000
	     obj04: 1.000000
	            0.000000 0.000000 0.000000
	            0.990268 -0.139173 0.000000 0.000000
	            6.000005 0.000000 0.000000
	frame00002: 0
	     obj01: 1.000000
	            0.000000 0.000000 0.000000
	            1.000000 0.000000 0.000000 0.000000
	            0.000000 0.000000 0.000000
	     obj02: 1.000000
	            0.000000 0.000000 0.000000
	            0.760406 -0.649448 0.000000 0.000000
	            -338.814117 264.796448 0.000000
	     obj03: 1.000000
	            0.000000 0.000000 0.000000
	            0.813753 0.581210 0.000000 0.000000
	            -78.100441 -296.024628 1.197711
	     obj04: 1.000000
	            0.000000 0.000000 0.000000
	            0.990268 -0.139173 0.000000 0.000000
	            8.329805 0.000000 0.000000
	frame00003: 0
           :
           :
	frame00150: 1
	     obj01: 1.000000
	            0.000000 0.000000 0.000000
	            1.000000 0.000000 0.000000 0.000000
	            0.000000 0.000000 0.000000
	     obj02: 1.000000
	            0.000000 0.000000 0.000000
	            0.760406 -0.649448 0.000000 0.000000
	            -26.000031 313.000000 0.000000
	     obj03: 1.000000
	            0.000000 0.000000 0.000000
	            0.050079 0.520093 0.081722 0.848715
	            -250.000000 -262.000000 94.000000
	     obj04: 1.000000
	            0.000000 0.000000 0.000000
	            0.990268 -0.139173 0.000000 0.000000
	            227.000000 0.000000 0.000000