Scene graph file format description

Kekoa Proudfoot
August 22, 2000

Introduction
------------

The scene graph file format is used to describe scenes for our scene
viewer.  The scene graph contains transformations, objects, and lights.
Objects and lights are individually configurable, allowing a variety of
models, surface shaders, and light shaders to be specified.  Trackball
transformations allows the scene to be interactively manipulated.

Basics
------

In the file format, white space and indenting are not important, except to
the extent that they separate the various items specified in the file.
Comments are allowed using either C /* */ or C++ // comment syntax.
Identifiers are case-sensitive.

The descriptions below describe the scene graph file grammar.
Non-terminals are designated using capital letters, and all terminals are
in lower case.  An asterisk (`*') denotes an item that may appear zero or
more times.

Scenes
------

The file format consists of a list of scene specifiers:

    SCENE_LIST = SCENE*

    SCENE = scene NAME { SCENE_ITEMS }

A NAME is either a C identifier or a string in double quotes:

    NAME  = IDENT
    NAME |= STRING

A scene's NAME allows the scene to be easily identified and selected.

Scene items
-----------

A scene contains a list of scene items.  This list in turn consists of a
single geometry specifier and an optional view specifier.  These specifiers
may appear in any order:

    SCENE_ITEMS = SCENE_ITEM*

The geometry specifier is used to delimit the specification of
transformations, lights, and objects from the rest of the scene:

    SCENE_ITEMS = geometry { GEOMETRY_ITEMS }

The view specifier is used to delimit the specification of view-specific
information:

    SCENE_ITEMS |= view { VIEW_ITEMS }

The view specifier is optional because a view has default values.  These
default values are described later in the section on view items.

Geometry items
--------------

There are many kinds of geometry items, and these items appear as a list
within a geometry specifier:

    GEOMETRY_ITEMS = GEOMETRY_ITEM*

Geometry items are applied consecutively in the order they appear in the
geometry specifier.  Transformations are concatenated; objects and lights
use the transformation that is "current" at the point in the file where
they are invoked.

The first four geometry items are static transformations:

    GEOMETRY_ITEM  = translate FLOAT FLOAT FLOAT ;
    GEOMETRY_ITEM |= rotate FLOAT FLOAT FLOAT FLOAT ;
    GEOMETRY_ITEM |= scale FLOAT ;
    GEOMETRY_ITEM |= scale FLOAT FLOAT FLOAT ;

These four items specify translations, rotations of an angle (in degrees)
about an axis, uniform scales, and non-uniform scales respectively.

A FLOAT is equivalent to a C floating point constant value.

There are also two versions of the dynamic trackball transformation:

    GEOMETRY_ITEMS |= ball NAME FLOAT FLOAT FLOAT FLOAT FLOAT ;
    GEOMETRY_ITEMS |= ball NAME FLOAT FLOAT FLOAT FLOAT FLOAT { BALL_ITEMS }

The first version specifies a ball with a default configuration, while the
second version allows non-default configuration through the specification
of BALL_ITEMS.  Both versions associate a NAME with the ball, so the ball
can be selected easily, as well as five FLOAT values to specify an initial
ball scale, an initial rotation angle (in degrees), and an initial rotation
axis (x, y, and z).  A ball can be further configured by specifying one or
more BALL_ITEM modifiers:

    BALL_ITEMS = BALL_ITEM*

    BALL_ITEM  = constrain FLOAT ;
    BALL_ITEM |= zoomview FLOAT ;
    BALL_ITEM |= rotateview FLOAT ;

The constrain modifier specifies whether or not the ball's rotation should
be initially restricted to rotating about its y axis.  Rotation is
restricted if FLOAT is non-zero.

The zoomview modifier specifies whether or not the ball's scale should be
used to zoom the entire view, not scale the subsequent geometry.  The
entire view is scaled if FLOAT is non-zero.

The rotateview modifier specifies whether or not the ball's rotation should
be used to rotate the entire view, not rotate the subsequent geometry.  The
entire view is rotated if FLOAT is non-zero.  Rotating the view using
rotateview changes the view matrix.  This is in contrast to ordinary
transformations, which instead affect the model matrix.

If more than one ball has zoomview enabled, the initial view zoom is the
scale of the last zoomview-enabled trackball in the scene.  If more than
one ball has rotateview enabled, the initial view rotation is the rotation
of the last rotateview-enabled trackball in the scene.

Objects and lights may also be specified:

    GEOMETRY_ITEM |= object NAME { OBJECT_ITEMS }
    GEOMETRY_ITEM |= light NAME { LIGHT_ITEMS }

Again, a NAME is used to identify each object and light.

In order to limit the effect of certain transformations, curly braces may
be paired to push (`{') and pop (`}') the current transformation:

    GEOMETRY_ITEM |= { GEOMETRY_ITEMS }

Finally, note that geometry items with curly braces do not require trailing
semicolons.  For these geometry items, trailing semicolons are optional.
Extra semicolons are ignored:

    GEOMETRY_ITEM |= ;

Object items
------------

Objects may be configured by a list of items:

    OBJECT_ITEMS = OBJECT_ITEM*

There are three kinds of object items:

    OBJECT_ITEM  = model NAME ;
    OBJECT_ITEM |= shader NAME ;
    OBJECT_ITEM |= PARAM ;

The first kind of object item specifies a model for the object.  If
unspecified, a default model is used, and if specified more than once, the
last model is used.  In our case, the default model is the first model in
the scene viewer configuration file.

The second kind of object item specifies a surface shader for the object,
with similar behavior to the model specifier if the shader is unspecified
or specified more than once.

The final object item specifies a constant to be used as a non-default
shader parameter.  It has several forms:

    PARAM  = param NAME STRING
    PARAM |= param NAME FLOAT
    PARAM |= param NAME { FLOAT , FLOAT , FLOAT  }
    PARAM |= param NAME { FLOAT , FLOAT , FLOAT , FLOAT }
    PARAM |= param NAME { FLOAT , FLOAT , FLOAT , FLOAT , ... , FLOAT }
    PARAM |= param NAME { FLOAT , FLOAT , FLOAT , FLOAT , ... , FLOAT }

The first specifies a string, and is used to name a texture for shader
texref parameters.  The second specifies a scalar, and is used to specify
shader bool parameters (true if non-zero) and shader float and clampf
parameters.  The third and fourth specify three- and four-vectors
respectively for float3, clampf3, float4, and clampf4 shader parameters.
The fifth has 9 comma-separated float values and the sixth has 16
comma-separated values.  They are used to specify three-by-three and
four-by-four matrices in row major order for shader matrix3 and matrix4
parameters.

Although these parameters are constant, they may be used to configure
per-primitive-group and per-vertex shader parameters.

The param specifier allows the default object parameter settings to be
overridden or extended.  In our viewer, the default object parameter
settings are:

    param __modelview <matrix>
    param __projection <matrix>
    param __normal <vector>
    param __tangent <vector>
    param __binormal <vector>
    param __position <vector>
    param uv <vector>
    param __ambient { 1, 1, 1, 1 }
    param time <scalar>
    param fixedtime <scalar>
    param viewmat <matrix>
    param <texname> <texref>

Values in angle braces are computed internally by the viewer and are not
constant.  The time parameter is time measured in seconds; the fixedtime
parameter is a constant (but possibly non-zero) time value; viewmat is the
view matrix; <texname> matches any name defined to be a texture in the
viewer.

Light items
-----------

Like objects and almost everything else, lights may be configured by a
list of items:

    LIGHT_ITEMS = LIGHT_ITEM*

There are seven kinds of light items.  The first two allow light shaders
and light shader parameters to be specified:

    LIGHT_ITEM  = shader NAME ;
    LIGHT_ITEM |= PARAM ;

Both behave similarly to the object equivalents, in particular with respect
to default behavior.

The default light parameters are:

    param color <vector>
    param ac 1
    param al 0.01
    param aq 0
    param __lightpos <vector>
    param __lightdir <vector>
    param __lightup <vector>
    param time <scalar>
    param fixedtime <scalar>
    param <texname> <texref>

The default color value depends on an internal viewer dim_lights setting.
If dim_lights is false, or if there are no active lights, the color value
is { 1, 1, 1, 1 }.  Otherwise the color value is:

    { 1 / num_lights, 1 / num_lights, 1 / num_lights, 1 }.

The time, fixed time, and <texname> parameters operate identically to the
corresponding default surface parameters, as described above.

Four light items configure the light's position and orientation:

    LIGHT_ITEM |= pos FLOAT FLOAT FLOAT ;
    LIGHT_ITEM |= pos FLOAT FLOAT FLOAT FLOAT ;
    LIGHT_ITEM |= dir FLOAT FLOAT FLOAT ;
    LIGHT_ITEM |= up FLOAT FLOAT FLOAT ;

The position is a homogeneous four-vector.  If only three components are
specified, the homogeneous coordinate is set to 1.

When the light's position and orientation are specified in this way, they
are automatically transformed by the light's current transformation.

The default position and orientation are given by:

    pos 0 0 1 ;
    dir 0 0 -1 ;
    up 0 1 0 ;

The final light item allows the light's initial toggle setting to be
configured:

    LIGHT_ITEM |= hide FLOAT ;

If FLOAT is non-zero, the light is initially disabled.  All lights are
by default enabled.

View items
----------

Views are configured by a list of items:

    VIEW_ITEMS = VIEW_ITEM*

There are four kinds of view items:

    VIEW_ITEM  = pos FLOAT FLOAT FLOAT ;
    VIEW_ITEM |= dir FLOAT FLOAT FLOAT ;
    VIEW_ITEM |= up FLOAT FLOAT FLOAT ;
    VIEW_ITEM |= dice FLOAT ;

The first three specify the initial viewer position and orientation.  The
last specifies an initial scene object dice factor.  The dice factor is
rounded to the nearest integer; the resulting integer must be within 1 to
10 inclusive.

Default values are:

    pos 0 0 1 ;
    dir 0 0 -1 ;
    up 0 1 0 ;
    dice 5 ;

Sample scenes
-------------

A basic scene with one object and many lights.  Only one light is enabled
initially:

scene "default" {
    geometry {
        {
            ball "object" 1 0 0 0 1 { zoomview 1 ; }
            object "object" { model "plane" ; }
        }
        {
            ball "light 1" 4.33013 56.6003 -0.769274 0.590284 -0.244504 ;
            light "light 1" { }
        }
        {
            ball "light 2" 4.33013 -56.6003 0.769274 0.590284 -0.244504 ;
            light "light 2" { hide 1; }
        }
        {
            ball "light 3" 4.33013 56.6003 0.769274 -0.590284 -0.244504 ;
            light "light 3" { hide 1; }
        }
        {
            ball "light 4" 4.33013 -56.6003 -0.769274 -0.590284 -0.244504 ;
            light "light 4" { hide 1; }
        }
        {
            ball "light 5" 4.33013 0 0 0 1 ;
            light "light 5" { hide 1; }
        }
    }
    view {
        pos 0 0 10 ;
    }
}

A more-complex scene with six different surface shaders and two different
light shaders; one trackball allows the spheres to be manipulated together:

scene "crazy spheres" {
    geometry {
        {
            ball "all objects" 1.7 71.425 -0.018 -0.849 0.528 { zoomview 1 ; }
            {
                translate 1.4 0 0 ;
                object "object 1" {
                    model "sphere" ;
                    shader "poolball_with_env" ;
                }
            }
            {
                translate -1.4 0 0 ;
                object "object 2" {
                    model "sphere" ;
                    shader "litembosstest" ;
                }
            }
            {
                translate 0 1.4 0 ;
                object "object 3" {
                    model "sphere" ;
                    shader "quake_sky" ;
                }
            }
            {
                translate 0 -1.4 0 ;
                object "object 4" {
                    model "sphere" ;
                    shader "anisotropic_ball_texture" ;
                }
            }
            {
                translate 0 0 1.4 ;
                object "object 5" {
                    model "sphere" ;
                    shader "earth" ;
                }
            }
            {
                translate 0 0 -1.4 ;
                object "object 6" {
                    model "sphere" ;
                    shader "glossy_moons" ;
                }
            }
        }
        {
            ball "light 1" 4.33013 56.6003 -0.769274 0.590284 -0.244504 ;
            light "light 1" {
                shader "simple_light" ;
	    }
        }
        {
            ball "light 2" 4.33013 -56.6003 -0.769274 0.590284 -0.244504 ;
            light "light 2" {
                shader "star_projector_anim" ;
	    }
        }
    }
    view { pos 0 0 10 ; dir 0 0 -1 ; up 0 1 0 ; dice 2 ; }
}
