/***************************************************************************\
 *                                                                         * 
 *         Electronic Documentation for NeonJax3D World Compiler           * 
 *                                                                         * 
 *                               Version 1.0                               * 
 *                                                                         * 
 *                             July 9th, 2002                              * 
 *                                                                         * 
 *                 Copyright (c) 2002 by Richard Goedeken                  * 
 *                                                                         * 
 *                                                                         * 
 *                  A product of Fascination Software Co.                  * 
 *                                                                         * 
\***************************************************************************/
-----------------------------------------------------------------------------
Legal Stuff:

This software (NeonJax3D SDK Version 1.0) is copyrighted software.  I give
you (the LICENSEE) permission to freely copy and distribute this software in
any manner to anyone (the RECIPIENTS) as long as the following two conditions
are met:

A) The LICENSEE may not charge the RECIPIENTS more than us$1 over and above
   the media and duplication costs for copies of this software.
B) Any copies made by the LICENSEE must retain all of the original files and
   the original file structure from the ZIP file distributed by Fascination
   Software. (NeonJax3D-SDK.zip)

Fascination Software, and Richard Goedeken, are not in any way liable for any
damages incurred by the use of this software.  The user assumes full
responsibility for the use of this software.
-----------------------------------------------------------------------------

 *************************************************************************** 
 **                              J3DComp.txt                              ** 
 *************************************************************************** 

This file contains information regarding the usage of the NeonJax3D World
Compiler.

The NeonJax3D World Compiler (J3DComp.exe) is a Win32 console program which
translates special text files (J3D Scene Source Files) into binary .J3D files
which may be displayed with the NeonJax3D Screen Saver.  J3DComp.exe takes
only two command line parameters: the filename of the input (source text)
file, and the name of the output (binary .J3D) file.  Look at the batch files
in the 'Worlds\' directory for examples of usage.  The Table of Contents for
this file is given below:

1. Basic Overview
2. Data Types
3. 'World' Object
4. 'Palette' Object
5. 'Path' Object
6. 'Scene' Object
7. CmdStream Commands
8. NeonJax3D Engine Overview
9. Specifications & Limitations
10. Contact Information

-----------------------------------------------------------------------------
 ++-----------------------------------------------------------------------++
 ||                         1. Basic Overview                             ||
 ++-----------------------------------------------------------------------++

The NeonJax3D Screen Saver has 3 classes of visual displays:

  1. Background - The NeonJax3D background is a lavalamp-like plasma display.
                  It is not user-configureable.
  2. 3D Objects - NeonJax3D is capable of displaying arbitrary triangle-based
                  objects, with user-designed palettes.
  3. 1000 Points of Light - this is a special object which consists of 1,000
                            separate white dots.  It has morphing capability
                            and can display 12 different user-configureable
                            effects.  Only one 1000 Points of Light object
                            may be in a Scene.

The NeonJax3D Scene File format is a simple object-oriented C-like language
for creating 3D demo scenes.  The NeonJax3D World Compiler is case-sensitive
and ignores whitespace.  There are four main object types: World, Palette,
Path, and Scene.  There must be exactly one World object and one Scene
object, but there may be between 0 and 32 Paths, and between 0 and 32
Palettes.  The Scene object must be defined *AFTER* all of the other objects;
it should be the last object.  The objects are defined like this:

  ObjectType {
  // ...
  // Object properties and data
  // ...
  } ObjectNameIfPathOrPalette;

World and Scene objects may *NOT* have names, but Path and Palette objects
are *REQUIRED* to have names.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
The object hierarchy is shown below for reference:

      World          <Palette>      <Path>              Scene
      | | |              |             |                || ||
      | | |           <Color>      <Segment>            || ||
      | | |                                    +--------+| |+--------+
  +---+ | +-------+                            |      +--+ +--+      |
  |     |         |                            |      |       |   Version
 Name  Version <Object>                     <Item>  Light    Name
                |   |                        |  |
          +-----+   |                +-------+  |
          |         |                |          |
      <Vertex>   <Poly>           Palette   <CmdStream>

<> = more than one instance of this type of object is allowed in parent
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

World objects contain 'Name' and 'Version' properties, and Object objects.  I
apologize for the confusing nomenclature.  The World object contains the
templates for the 3D objects.  They are like blueprints - a representation
of the object but not the object itself.  The Scene object contains the
actual 3D Items that are displayed in the demo.  These Items are created
from the blueprints (Objects) which are in the World object.  Thus the user
may have only one cube Object (in the World) but 3 cubes in the demo (in
the Scene).

Each Palette object is collection of 513 colors (numbered -256 to 256) which
may be used to color an Item (in the Scene) or a Poly (in an Object).   Each
polygon displayed by NeonJax3D is painted with the color in the palette index
proportional to the angle between the polygon surface normal and the light
vector.  If they are facing each other, the polygon will be colored with
Color 256; if they are facing the same direction (the back of the poly is
lit) then Color -256 will be used.  If the polygon surface normal is exactly
perpendicular to the light vector, then it will be painted with Color 0.

The Path object contains Segments which describe curves in a line drawing.
A Path may be used in one of the special effects for the 1000 Points of Light
object.   This effect is called Marquee and causes the army of points to
march along the path like lights around a movie marquee.

The Scene is the final object; it uses the data declared in the other objects
and puts everything together to define all of the Items in the demo and their
movements through time.  The Scene contains 'Name', 'Version', and 'Light'
properties, and Item objects.  The Items represent the actual 3D objects
which will be in the demo.  Each Item has an associated Palette and one or
more CmdStreams.  The CmdStream (Command Stream) defines the movement (and
morphing for the 1000 Points of Light) for each object.  There are 3 types of
CmdStreams: Translation, Rotation, and Morph.  Only the special Points object
may have a Morph CmdStream.

If this is all very confusing, then just look at the example files and it
will make sense.

-----------------------------------------------------------------------------
 ++-----------------------------------------------------------------------++
 ||                           2. Data Types                               ||
 ++-----------------------------------------------------------------------++

The NeonJax3D World Compiler uses seven data types, listed below:

Data Type  |  Used For                             |  Examples
-----------------------------------------------------------------------------
Name       |  Various object names                 |  Bob  Poly42  _Blue
Text       |  World and Scene 'Name' property      |  "Cool Scene 42"
Int        |  Version property, command operands   |  12  -37  8192 0xffe3
Float      |  Command operands                     |  42.0  99.99  0.001
Duplet     |  Path segment starting X,Y            |  (42, 73)  (-1,440)
Triplet    |  Vertex coordinates, command operands |  (-60,60,15)  (12, 0, 0)
TriName    |  Polygon definitions                  |  (Va,Vb,Vc)  (AB,_,b42)

There are 36 reserved words that the NeonJax3D World Compiler recognizes.
These may *NOT* be used as names.  Names may be up to 32 characters and must
start with an alphabetic character or underscore.   Names may include
digits, but not the first character may not be a digit.   The reserved words
are categorized below:

Top-level directives:
  - World, Palette, Path, Scene

Lower-level directives:
  - Name, Version, Object, Vertex, Poly, Color, Segment, Light, Item,
    CmdStream

CmdStream types:
  - Translation, Rotation, Morph

Translation and Rotation Commands:
  - Move, Stay, Spline, Orbit, Spin, MoveSpin

Morph Commands:
  - EmptyCube, FilledCube, Sphere, Corkscrew, GridCurve, RandomCloud,
    SnowField, GaseousSphere, BouncingCubes, Vortex, Marquee, SaturnRings

Reserved Names:
  - Points

-----------------------------------------------------------------------------
 ++-----------------------------------------------------------------------++
 ||                         3. 'World' Object                             ||
 ++-----------------------------------------------------------------------++

Each NeonJax3D demo must have exactly one World object.  The reference
definition for a generic World follows:

World {
  Name "My World Name";
  Version 1;
  Object {
    // vertices and polygons
    } Object1Name;
  Object {
    // vertices and polygons
    } Object2Name;
  // ...
  };

The Objects which are defined in the World are templates for the actual Items
which will be displayed in the Scene.  These Objects are by default
'unpainted' in their definition in the World.  A palette is associated with
each Item in the Scene, and this palette is used by default for display.  An
example Object definition is:

Object {
    Vertex A (0,-40,0);     Vertex B (-20,40,20);
    Vertex C (-20,40,-20);  Vertex D (20,40,-20);
    Vertex E (20,40,20);
    Poly(A,B,C);            Poly(A,C,D);
    Poly(A,D,E);            Poly(A,E,B);
    Poly(B,E,D);            Poly(B,D,C);
  } Pyramid;

Each Vertex directive is followed by a Name and a Triplet, with a semicolon
at the end.  The Triplet (see 2. Data Types) specifies the X,Y,Z coordinates
of the Vertex.  Each Poly has a single operand, which is a TriName (see 2.
Data Types).  This specifies the names of the three vertices in this
triangle.  Since NeonJax3D uses a right-hand coordinate system (see 8.
NeonJax3D Engine Overview), the three vertices in a triangle must be defined
in a counter-clockwise order when viewing the front of the polygon.  This
will assure that the surface normal is computed correctly and that the
lighting is correct.

Each Poly may be assigned a palette in the Object definition if desired.
This allows Objects to be painted with more than one palette.   To use this
feature, put a palette Name after the TriName in a Poly definition, as
demonstrated below.  This palette will override the default (Item) palette:

Poly (Vert1, Vert32, Vert73) White;

There is no practical restriction on the number of Polys, Vertex's, or
Objects in a NeonJax3D Scene file.  The only limitation is file/memory size.
However there are limitations for the total number of vertices, polygons, and
Items in a Scene.  (See 9. Specifications & Limitations)

-----------------------------------------------------------------------------
 ++-----------------------------------------------------------------------++
 ||                        4. 'Palette' Object                            ||
 ++-----------------------------------------------------------------------++

Palettes are used to paint all of the 3D polygons that NeonJax3D renders.
Each palette has 513 colors, which are numbered from -256 to 256.  The color
which will be painted on a given polygon is determined by the angle between
the polygon's surface normal and the Light vector (See 8. NeonJax3D Engine
Overview).  The equation relating these quantities is:

  PaletteColorIndex = -256 * DotProduct(PolySurfNormal, LightVector)

If the front of the polygon is directly facing the light vector, the polygon
will be colored with Color 256; If the polygon's surface normal is pointing
in the exact same direction as the Light Vector (the back of the poly is lit)
then Color -256 will be used.  If the polygon's surface normal is exactly
perpendicular to the light vector, then it will be painted with Color 0.

Each Palette must have at least one Color object.  Every Color directive is
followed by a palette index (-256 to 256) and an RGB Triplet.  Each color
component (red, green, and blue) in the RGB triplet must be between 0 and
255.  The NeonJax3D World Compiler will interpolate between Color indices
which are defined.  Thus it is not necessary to define all 513 Colors; just
define the 'key' colors and the NeonJax3D World Compiler will do a piecewise-
linear interpolation between them.  An example Palette definition follows:

Palette {
  Color 0   (0,0,0);        // -256 through 0 are black
  Color 85  (255,0,0);      //  +85 is pure red
  Color 170 (255,128,0);    // +170 is orange
  Color 256 (255,255,0);    // +255 is pure yellow
  } Fire;

Each palette must have a name ('Fire' in the example above).  The NeonJax3D
compiler enforces a maximum of 32 Palettes in each J3D Scene Source file.

-----------------------------------------------------------------------------
 ++-----------------------------------------------------------------------++
 ||                         5. 'Path' Object                              ||
 ++-----------------------------------------------------------------------++

The Path object defines a series of steps along a path, which can be split
into multiple segments.  This path is used for the Marquee effect for the
1000 Points of Light object.  Paths are composed of one or more Segments.
Each Segment has two operands; the first one is a Duplet (see 2. Data Types)
which specifies the starting X,Y coordinates of the Segment.  The second
operand is a Text block which specifies the steps to be taken on the path.

Each step along the Path can go one of four directions: -y, +y, +x, or -x.
This is like North, South, East, and West.  The text operand in the Segment
object must contain only the letters n,N,s,S,e,E,w, or W, and white space.
The example Path below demonstrates an 11-pixel square Path centered at 0,0:

Path {
  Segment (-5,-5)      "EEEEEEEEEESSSSSSSSSSWWWWWWWWWWNNNNNNNNNN";
  } Square11;

The 'PathFind\' directory contains a DOS utility program (PathFind.exe) which
can read 8-bit BMP images, trace their contours, and output the NeonJax3D
World Compiler compatible Path source code.  This can be cut and pasted into
your demos!  Read the 'PathFind\PathFind.txt' file for more information.

-----------------------------------------------------------------------------
 ++-----------------------------------------------------------------------++
 ||                         6. 'Scene' Object                             ||
 ++-----------------------------------------------------------------------++

The Scene object must be the last top-level object in the demo.  The Scene
defines the Items which are present in the demo, and gives them palettes and
streams of commands to guide their movements through time.

The Scene object has 'Name', 'Version', and 'Light' properties, and Item
objects.  The reference definition for a generic Scene follows:

Scene {
  Name "My Generic Scene";
  Version 0x0;
  Light (0,0,10);

  Item Pyramid {
    Palette Fire;
    CmdStream Translation {
      // translation commands
      };
    CmdStream Rotation {
      // rotation commands
      };
    } PyrObj;    // end of Pyramid
    
  Item Points {
    CmdStream Translation {
      // translation commands
      };
    CmdStream Rotation {
      // rotation commands
      };
    CmdStream Morph {
      // morph commands
      };
    } PointsObj;    // end of Points object definition
  };  // end of scene description

The Name directive is followed by a single text string.  The Version
directive has a single operand of type Int.  The Light directive takes a
Triplet operand.  Triplets are made of integers (the decimal point is not
allowed in a Triplet).  The magnitude of the Light vector does not matter,
however, because the vector is normalized before it is used.  The NeonJax3D
engine does not use a point light source; the light comes from everywhere at
the same angle.  The direction of the incoming light is given by the Light
vector.  In the example above, the light is going in the +z direction (into
the monitor).

The Item objects define the actual 3D shapes which will be in the demo.
Each Item has an associated Palette (except the Points object) and one or
more CmdStreams.  All unpainted polygons in the specified Object will be
colored with the Palette specified in the Item.  The CmdStream objects define
the movement of the Items through time.

There are 3 types of CmdStreams: Translation, Rotation, and Morph.  Only the
special 1000 Points of Light object may have a Morph CmdStream.  As the demo
is displayed, each Item sequentially executes the commands given in each of
its streams.  When an Item reaches the end of one of its command streams,
that stream immediately starts over from the beginning.  Control flow is
linear - there are currently no commands for branching or looping.  The
definitions of the commands which may be used in the CmdStreams are in the
section below titled '7. CmdStream Commands'.

The Scene may contain up to a maximum of 256 Items.  The total number of
polygons in a Scene must be no more than 32,768.  The total number of
vertices in a Scene must be no more than 16,384.

-----------------------------------------------------------------------------
 ++-----------------------------------------------------------------------++
 ||                       7. CmdStream Commands                           ||
 ++-----------------------------------------------------------------------++

The Translation CmdStream type controls the 3D position of the Item, has 4
different commands, and one command (Orbit) which has two forms.  The first
parameter after each command directive is the number of frames for which the
command will execute.  The parameters which follow vary with the command.  An
example Translation CmdStream is presented below:

CmdStream Translation {
  Stay   100;
  Move   60  (0, -256, 512);
  Orbit  240 (25, -200, 400) 0.0 2.2;  // Pc, Alpha(z), V(theta)
                                       //    [degrees]  [degrees/frame]
  Orbit  120 Star1 0.0 2.2;  // Object Name, Alpha(z),  V(theta)
                             //              [degrees]  [degrees/frame]
  Spline 120 (128, 0, 512) (0, 256, 400) 60 60;
          //      P1             P2      F1 F2
  };

The Stay command causes the Item's position to stay stationary for the number
of frames given by the first parameter.  The Stay command has no extra
parameters.

The Move command causes the Item to move with a constant velocity to the
specified point.  The Move command has one extra parameter, which is the
destination point (a Triplet).

The Orbit command has two forms: the first causes the Item to orbit around
a specified point, and the second causes the Item to orbit around another
Item.  The second parameter for the Orbit command is either the specified
point to orbit (in a Triplet), or the name of the Item to orbit.  The third
parameter is an angle called Alpha(z) which determines angle of the path
along which the Item will orbit.  The range of the Alpha(z) parameter is:
(-360,360).  The fourth and final parameter for the Orbit command is the
speed at which the item will Orbit, called V(theta), in degrees per frame.
If an Orbit command goes for 120 frames and orbits at a speed of 3.0 degrees
per frame, then it will end at the point at which it started.

The Spline command does a two-stage spline movement using two specified
points and two Int frame counts.  Parameters 2 and 3 are 3D points
(Triplets), called P1 and P2.  Parameters 4 and 5 are Int frame counts,
called F1 and F2.  The Spline movement progresses through stage 1 starting
at its current position and velocity, and ending at point P1 with its
acceleration equal to zero (constant velocity).  Stage 2 begins at point P1
with a calculated velocity and no acceleration, and ends at point P2.  Stage
1 lasts for F1 frames, and stage 2 is F2 frames long.  F1 plus F2 should
equal the first parameter (the total frame count).

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

The Rotation CmdStream type controls the 3D angular position of the Item.
This CmdStream type has 4 different commands.  The first parameter after each
command directive is the number of frames for which the command will execute.
The parameters which follow vary with the command.  An example Rotation
CmdStream is presented below:

CmdStream Rotation {
  Stay     60;
  Spin     60  -6.0;            // [degrees/frame]
  Move     120 0.0 -90.0 45.0;  // Phi(x)    Phi(y)    Theta(z)
                                // [degrees] [degrees] [degrees]
  MoveSpin 120 4.5 90.0 0.0;    // V(Theta(z))      Phi(x)     Phi(y)
                                // [degrees/frame]  [degrees]  [degrees]
  };

The angular position of each Item in the Scene is stored in three parameters.
The first two, called Phi(x) and Phi(y), are like spherical coordinates.
They specify an axis of rotation.  The third angular parameter, called
Theta(z), specifies the amount of rotation to apply to the Item around the
current axis of rotation.  For more information on this, see 8. NeonJax3D
Engine Overview.

The Stay command causes the Item's angular position to stay stationary for
the number of frames given by the first parameter.  The Stay command has no
extra parameters.

The Spin command has a single extra parameter, called V(theta).  This
parameter specifies the angular speed (in degrees per frame) at which the
Item will rotate around its axis of rotation.  The Item's axis of rotation
will remain stationary during this time.  If a Spin command lasts 50 frames
and spins at 7.2 degrees per frame, the Item will end up in the same
orientation in which it began.

The Move command causes the item to move with a constant angular velocity to
the given angular position.  The three extra parameters for the Move command
are Phi(x), Phi(y), and Theta(z). These are Floats and are interpreted to be
in degrees.

The MoveSpin command causes the axis of rotation to move to a given angular
position, and moves the Theta(z) position parameter at a constant rate.  The
first extra parameter for the MoveSpin command is called V(Theta(z)).  This
specifies the rotational speed of the Item to be applied to the Theta(z)
position during the command, in degrees per frame.  The last two parameters
in the MoveSpin command are Phi(x) and Phi(y) and specify the angular
position to which the Item's axis of rotation will move with a constant
velocity.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

The Morph CmdStream type controls the special effect to be applied to the
1000 Points of Light object.  Each Morph command has two stages.  During the
first stage, the points morph between the old effect and the new effect.  The
second part of each Morph command executes the desired special effect.  The
morphing between effects is accomplished via a spline interpolation.  The
initial position and velocity are given by the final frame of the old effect,
and the final position and velocity for each point are calculated from the
initial state of the new effect.  In this way the transitions between effects
are as smooth as possible.

This Morph CmdStream type has 12 different commands. The first *TWO*
parameters after each command directive are frame counts.  The first
parameter is the number of frames for which the Points will morph as
described above from the previous effect to the new effect.  The second
parameter is the number of frames for which the new effect will execute.
The parameters which follow these two vary with the command.  An example
Morph CmdStream is presented below:

CmdStream Morph {
  EmptyCube     60 1500 20;     // Point Spacing              [pixels]
  FilledCube    60 120 20;      // Point Spacing              [pixels]
  Sphere        60 120 100      // Minimum Radius             [pixels]
                       120      // Maximum Radius             [pixels]
                       15.0     // Velocity Theta(R)          [degrees/frame]
                       8        // Radial Points              [count]
                       125;     // Axial Points               [count]
  Corkscrew     60 120 100      // Minimum Radius             [pixels]
                       200      // Height                     [pixels]
                       1.5      // Minimum Velocity (Theta)   [degrees/frame]
                       0.5;     // Minimum Velocity (Z)       [pixels/frame]
  GridCurve     60 120 400      // Side Length                [pixels]
                       1000     // Radius                     [pixels]
                       20       // Stationary Frames          [count]
                       40;      // Moving Frames              [count]
  RandomCloud   60 120 100      // X Size                     [pixels]
                       100      // Y Size                     [pixels]
                       100;     // Z Size                     [pixels]
  SnowField     60 120 448      // Initial Field Size         [pixels]
                       0.285    // Scale Factor               [degrees/pixel]
                       0.375    // Maximum Sin Acceleration [degrees/frame^2]
                       0.25     // Positive Threshold         [coefficient]
                       -0.25    // Negative Threshold         [coefficient]
                       0.625    // Maximum Force             [pixels/frame^2]
                       0.00976; // Friction Coefficient       [coefficient]
  GaseousSphere 60 600 150      // Radius                     [pixels]
                       20       // Points                     [count]
                       0.5      // Minimum Velocity           [pixels/frame]
                       7.5      // Maximum Velocity           [pixels/frame]
                       0;       // Minimum Radius             [pixels]
  BouncingCubes 60 120 800      // Arena Size                 [pixels]
                       70       // Cube Size                  [pixels]
                       8        // Inter Points               [count]
                       0.2539   // Gravity Strength           [coefficient]
                       0.39868  // Outer Spring Coefficient   [coefficient]
                       0.07629  // Outer Damper Coefficient   [coefficient]
                       0.58313  // Inner Spring Coefficient   [coefficient]
                       0.07019; // Inner Damper Coefficient   [coefficient]
  Vortex        60 120 120      // Minimum Radius at top      [pixels]
                       30       // Maximum Velocity (Theta)   [degrees/frame]
                       2.0      // Minimum Velocity (Final Z) [pixels/frame]
                       10.0;    // Maximum Velocity (Final Z) [pixels/frame]
                                // vortex height is always 256
  Marquee       60 120 NukePath // Path Name
                       1.0      // Velocity                   [steps/frame]
                       200;     // Number of Points           [count]
  SaturnRings   60 120 20       // Ring Height                [pixels]
                       100      // Minimum Ring Radius        [pixels]
                       200      // Maximum Ring Radius        [pixels]
                       80       // Planet Radius              [pixels]
                       1.0      // Planet Rotation Velocity   [degrees/frame]
                       0.25;    // Minimum Ring Velocity      [degrees/frame]
  };

The EmptyCube effect causes the points to stay stationary in a cubic
arrangement.  The points will be on a grid surrounding the surface of a cube.
The distance between adjacent points is given by the Point Spacing parameter.

The FilledCube effect creates a 10x10x10 cube which is filled with the
Points.  The distance between adjacent points is given by the Point Spacing
parameter.

The Sphere effect creates a grid of points on the surface of a sphere and
modulates the size of the sphere in a sinusoidal fashion.   The points are
laid on the surface of the sphere in a series of stacked rings of varying
radius.  The number of rings is given by the Axial Points parameter, and
the number of points on each ring is given by the Radial Points parameter.
The product of these two quantities must be less than or equal to 1000.  The
Minimum Radius and Maximum Radius parameters give the size boundaries for the
underlying sphere as it changes size.  The Velocity Theta(R) parameter gives
the speed at which the sphere pulsates.  At 20.0 degrees per frame, the
sphere would go through a complete size cycle every 18 frames, or over 3Hz
at 60 fps.

The Corkscrew effect gives each point a radius and a height value, and moves
it around in a circle in the X-Y plane, and down in the Z direction.  The
radii of all of the points are distributed evenly within a range.  The
minimum (inner) diameter is given by the Minimum Radius parameter.  The
thickness of the cylinder is calculated as a fixed percentage of the Minimum
Diameter.  The height of the cylinder is given by the Height parameter.  The
Minimum Velocity (Theta) and Minimum Velocity (Z) parameters specify the
minimum radial and axial speed of the points.  The actual velocities are
chosen randomly in a range between the minimum and a fixed percentage more
than the minimum.

The GridCurve effect places all of the points on a large square grid (31 x 31
with a few left over).  The points stay stationary in the X and Y plane but
move in the Z direction to 'bend' around the surface of a sphere.  In this
way the grid is modulated to curve around a sphere.  The Side Length
parameter specifies the length of each side of the grid.  The Radius
parameter gives the radius of the imaginary sphere around which the grid will
be bent.  This parameter should be larger that the Side Length parameter.
The timing of the grid's movement is handled by the Stationary Frames and
Moving Frames parameters.  The GridCurve effect executes a 2-phase cycle.
First, the grid will be still (and flat) for Stationary Frames number of
frames.  Then the grid will curve through a complete sinusoidal cycle in
Moving Frames number of frames.  This 2-phase cycle is executed for the
number of frames specified in the second parameter of the command.

The RandomCloud effect is simply a 'cloud' of randomly-placed points which
move in small random steps.  The three extra parameters specify the size of
the cube in which the points are initially confined.

The SnowField effect simulates a set of particles which are confined to a
plane and being acted upon by an underlying force field.  The force field is
a sum-of-sines vector field which changes with time.  It is very similar to
the background effect for NeonJax3D, but the force field is a *vector* field,
and each point in the field has direction.  The Initial Field Size parameter
specifies the length of any side of the initial field of points.  When the
effect is running the points are allowed to spread out into an area with
twice the side length, or 4 times the area.  The Scale Factor specifies the
scaling factor for the lowest frequency sine component in the force field.
In order to make the effect look un-patterned, the product of the Initial
Field Size and the Scaling Factor should be less than 180 degrees.  The
Maximum Sin Acceleration parameter controls the maximum rate at which the
phase velocities of the sine components may be varied.   The Positive and
Negative Threshold parameters are used to create a 'dead zone' where the
force field will not act on the particles at all.  The Positive Threshold
must be in the range [0,1], and the Negative Threshold must be in the range
[-1,0].  The Maximum Force parameter specifies the maximum amount of force
which may be exerted per frame on any point by the force field.  The Friction
Coefficient controls the amount of frictional force which will be applied
every frame.  Many of these parameters are very sensitive to variation.  It
may be easiest to start with one of the examples provided and tweak the
values to see their effects.  It is difficult to tune the parameters of this
effect to get a good quasi-stable but dynamic state.  It has the tendency to
be either too dead (over-damped) or too chaotic (under-damped).

The GaseousSphere effect simulates a set of particles which act like oxygen
molecules in a balloon.  Each point travels with a constant velocity until
reaching the edge of the sphere, where it ricochets while maintaining the
same speed.  The Radius parameter specifies the radius of the sphere
containing the points.  The Points parameter controls the total number of
points displayed.  The Minimum and Maximum Velocity parameters give the range
of permitted velocities.  The Minimum Radius must be greater than or equal to
0 and must be less than Radius.  If this parameter is greater than 0, then
the points are initialized in such a way that they never enter any portion of
the sphere where the distance to the center is less than Minimum Radius.  In
this way the points can be made to skim around the surface of the sphere
rather than travel randomly in all directions through it.

The BouncingCubes effect simulates several cubes which behave similarly to
cubes of gelatin.  This effect simulates gravity and causes the cubes to
bounce around within a virtual arena.  The Arena Size parameter specifies the
length of each side of the arena.  The Cube Size gives the length of each
side of each cube.   Each cube automatically requires 8 points, for the 8
corners.  Additional points can be added to the line segments between the
corners.  The Inter Points parameter controls the number of points between
each pair of corners.  The total number of points required for each cube is
8+ Inter Points * 12. The total number of cubes is floor(1000/PointsPerCube).
The allowed range of Inter Points is [0,15].  The GravityStrength parameter
controls the strength of the applied gravity.  The BouncingCubes effect
simulates the bouncing of the cubes by using struts: springs and dampers.
There are 12 Outer Springs and Dampers which are placed between each pair of
adjacent corners.  There are also 4 Inner Springs and Dampers which are
placed between the four pairs of opposite corners.  The Spring and Damper in
each pair are placed mechanically in parallel with each other.  The Outer
Spring and Damper Coefficients, and the Inner Spring and Damper Coefficients,
adjust the properties of these struts to achieve the desired effect.  This
effect is also difficult to tune properly.  Since most quantities are stored
as integers, there are severe oscillations which can result from round-off
type errors if the parameters are not properly set.

The Vortex effect is like a funnel or a whirlpool.  Each point starts at the
top with a random radius between Minimum Radius and 25% more than Minimum
Radius, and proceeds downward with an exponentially decaying radius.  The
height of the Vortex is always 256.  The Maximum Velocity (Theta) parameter
specifies the maximum angular velocity for a point, which is reached at
the bottom (z = 255).  The Minimum and Maximum Velocity (Final Z) parameters
control the range of possible final Z velocities for the points (at z=255).
The actual velocities (angular and Z) for a point are scaled back from the
randomly pre-selected Final values.  Both the angular and Z velocities are
smaller at smaller Z levels.

The Marquee effect uses the Path objects to display line drawings in a movie
marquee-like display.  The Points march around the path referenced by the
Path Name parameter.  The Velocity parameter determines the speed of all of
the points, in steps per second.  The Number of Points parameter specifies
the total number of points displayed for this effect.  It is important to
control the point spacing to make this effect look good.  For example, if a
Path has 1000 steps and you do a Marquee display with 200 points, then the
points displayed will be 5 steps (or pixels) away from each other.  The
effect may not look good if this point spacing value is too low or too high.
Path definitions may be created from two-color 8-bit BMP images with the
PathFind.exe program.  See the 'PathFind\PathFind.txt' file for more
information.

The SaturnRings effect simulates a planet with rings.  250 Points are used
to form the planet, and the remaining 750 Points zip around the belt of the
planet to form the ring.  The planet also rotates independently from the
frame of reference of the Points object.  The Ring Height parameter sets the
thickness of the planet's ring, in pixels.  The Minimum and Maximum Ring
Radius parameters control the width and the inner radius of the ring.   The
Planet Radius parameter specifies the radius of the planet, in pixels.  The
Planet Rotation Velocity parameter gives the angular speed of one component
of the planet's orientation state.  The other two components of the planet's
orientation state are incremented by a small value every frame.  The Minimum
Ring Velocity parameter controls the range of velocities of the points in the
ring.  Each point's angular velocity is randomly chosen from the range
between the Minimum Ring Velocity and 5 times the Minimum Ring Velocity.

-----------------------------------------------------------------------------
 ++-----------------------------------------------------------------------++
 ||                     8. NeonJax3D Engine Overview                      ||
 ||                 (a.k.a. Crash Course in 3D Graphics)                  ||
 ++-----------------------------------------------------------------------++

This section gives some of the low-level details of the NeonJax3D engine.
The NeonJax3D screen saver engine is about 10,000 lines of MMX-enhanced
assembly language code wrapped with a few thousand lines of C for interfacing
with Windows.  It was designed to be small and fast.

The 'camera' in the NeonJax3D world is placed at the origin (0,0,0) and is
looking in the +Z direction.  The 'up' vector of the camera is -Y.  This
means that the NeonJax3D coordinate system mimics the traditional raster
graphics coordinate system.  The center of the screen is (0,0,0) and X
increases to the right, while Y increases down.

NeonJax3D uses a *right-hand* coordinate system.  The rule of thumb (the
right-hand rule) says that if you curl your fingers from +X to +Y, then
your thumb will be pointing in the +Z direction.  This means that Z increases
*INTO* the monitor.   Since the camera is located at (0,0,0), and the objects
must be in front of the camera, the objects should have positive Z values in
order to be visible.  Any polygon or point with a Z value smaller than 32 or
so will not be drawn.  The perspective transform is calculated such that an
object with a Z coordinate of 256 will have a 1:1 ratio between its world
space coordinates and its screen coordinates.  At Z = 128 an object will move
2 screen coordinates for every world coordinate, and with a Z coordinate of
512, the object will move 1/2 of a pixel per world coordinate moved.

A surface normal is a special 3D vector which is perpendicular to a plane.
These vectors are used for calculating the color of a polygon.  Each polygon
has its own surface normal vector which is rotated along with the polygon
itself.  NeonJax3D uses unit surface normals, so the length (magnitude) of
each surface normal is one.  Each polygon (triangle) has two sides, called
the inside and the outside.  NeonJax3D uses backface culling so polygons
which are showing their inside side are not drawn.  Only the outside of a
polygon is shown.  To make this scheme work properly, it is necessary to
designate which side is the inside and which side is out.  This is done in
NeonJax3D by defining the vertices for each polygon in a certain order.
The Poly directive (in an Object in the World) defines a polygon and
specifies the names of its three vertices.  To correctly define the polygon
in a way which specifies the correct inside/outside orientation, the three
vertices must be ordered in a counter-clockwise direction as a viewer is
looking at the outside of the polygon.

Every polygon in the NeonJax3D demo is hit by light coming from the same
angle.  This direction may be defined by using the Light property of a Scene.
The default Light vector is (0,0,1) which causes the light to move in a +Z
direction.  This creates very even and direct illumination.  Polygons which
are parallel to the monitor surface will be painted with Color 256 when using
the default Light vector.  If the Light vector is set to (0,0,-1) then
polygons which are parallel to the monitor will be painted with Color -256.

The angular orientation of each Item in the Scene is controlled by 3 state
variables, called Phi(x), Phi(y), and Theta(z).  The first two are like
spherical coordinates; they specify an axis of rotation.  The Theta(z)
variable specifies the amount of rotation to apply to the object around the
axis of rotation.  If the Theta(z) value is 0, then the object will not be
rotated at all regardless of the values of Phi(x) and Phi(y).  Refer to the
diagram below:

                                          z
                          2              ^
                        O               /
                         \             /            
                                      /        O  3
                           \         /       /
                                    /     /
                           ( \     /   /
                          (       / /
                         (     \ /
                  Phi(x) (      +---------------------> x
                         (     /|
                          (     |
                           ( /  |
                                |
                           /    |
                                |
                         /      |
                        O       |
                      1         V
                                
                                y

The diagram above shows the coordinate system of NeonJax3D, and the
calculation of an axis of rotation.  The axis of rotation starts in the -Z
direction (0,0,-1) which is shown as point 1.  The first operation is to
apply a rotation of -Phi(x) about the X axis.  This means that (using the
right-hand rule) positive values of Phi(x) will cause the axis of rotation to
be rotated *UP*.   In the diagram Phi(x) is equal to 45 degrees and the new
axis of rotation (shown as  point 2) is (0,-0.707,-0.707).  The second
operation applies a rotation of -Phi(y) about the Y axis.  Consequently,
positive values of Phi(y) will causes the axis of rotation to be rotated to
the *RIGHT* or counter-clockwise.  The diagram shows the axis of rotation at
point 3 after a rotation with Phi(y) equal to 135 degrees.  The final axis of
rotation will be at (0.5, -0.707, 0.5).

The Theta(z) value specifies the quantity of rotation which is applied to the
Item around the axis of rotation.  You may use the right-hand rule to
determine directionality.  Continuing with the diagram above, if the viewer's
hand points the thumb in the direction of the axis of rotation, the fingers
will curl in the direction of rotation which will be applied for positive
Theta(z) values.  In this case, the Item will rotate counter-clockwise around
the axis of rotation (point 3) by Theta(z) degrees.  This rotation is with
respect to the object's center. All of the objects in the example files are
centered around (0,0,0).

The Phi(x) value is valid from -90 to 90 degrees.  The Phi(y) and Theta(z)
values are both valid between 0 and 360 degrees.

-----------------------------------------------------------------------------
 ++-----------------------------------------------------------------------++
 ||                  9. Specifications & Limitations                      ||
 ++-----------------------------------------------------------------------++

Maximum Objects              65535
Maximum Scene vertices       16384
Maximum Scene polygons       32768
Maximum Palettes             32
Maximum Paths                32
Maximum Items                256

-----------------------------------------------------------------------------
 ++-----------------------------------------------------------------------++
 ||                           10. Contact                                 ||
 ++-----------------------------------------------------------------------++

To contact Fascination Software, point your web browser at:

                        www.fascinationsoftware.com

And follow the links...

-----------------------------------------------------------------------------
EOF EOF EOF EOF EOF EOF EOF EOF EOF EOF EOF EOF EOF EOF EOF EOF EOF EOF EOF
-----------------------------------------------------------------------------