GLIDE 2.0

Graphics Language for Interactive and Dynamic Environments

0 Table of Contents

  1. Introduction
  2. Language Overview
    1. Basic elements
  3. Defining Static Scenes
    1. Object description statements
    2. Statements to define cameras
      1. Differences between GLIDE and PHIGS viewing models
    3. Statements to define lighting
      1. Explanation of GLIDE lighting
    4. Statements to build hierarchies
      1. Geometric instances
      2. Camera instances
      3. Light instances
    5. Statements to view a GLIDE scene
    6. Including Files
  4. Defining dynamic scenes
    1. Dynamic values
    2. glfc - GLIDE File Compiler
    3. Declaration statements
    4. Static Declaration
    5. Variables
    6. Using C functions in dynamic expressions
  5. Hints on Style
  6. A GLIDE example
  7. Defaults
  8. Authors

1 Introduction

GLIDE is a language used to create descriptions of dynamic scenes. A scene is an illuminated collection of objects viewed through a camera. GLIDE allows a user to hierarchically describe objects, illuminate them using different types of lights, and then specify the way in which this scene is viewed by an observer. The various components of the scene can be dynamic, meaning that their values can be time-varying, or interactive, meaning that they can be dependent on input devices.

A GLIDE file has a .glf extension (pronounced glyph), short for GLIDE format.

2 Language overview

A legal GLIDE file contains statements in the following order:

version-statement

declaration-statements

scene-statements


The first line in a GLIDE file defines the GLIDE version number. version-statement for GLIDE Version 2.0 is

GLIDEv2.0

declaration-statements deal with the representation of dynamic values. scene-statements are used to build up a hierarchical representation of the environment that can be either static or dynamic. Section 3 explains the definition of static scenes. Section 4 describes the process of extending this definition to construct dynamic environments.

2.1 Basic elements

A basic element of GLIDE is a triple which can be either static or dynamic. It may represent various things such as a position or orientation in 3D space, or the intensity of the three color components of a light.

A static triple consists of 3 floating point numbers surrounded by parentheses. Dynamic triples will be discussed in Section 4.1.

triple ::= ( <FLOAT> <FLOAT> <FLOAT> )

A dynamic pointer can be substituted for a dynamic triple. This is described in Section 4.1.

An id, short for identifier, is a positive integer less than 1048576(=220).

Every entity in a GLIDE file has an associated id. Within a file, the id values are assumed unique for each type of entity. For example, every point in a GLIDE file must have a different id, but a face could have the same id as a point in the file.

An idlist is a list of identifiers referring to other entities defined in the GLIDE file.

idlist ::= ( id1 id2 ... idn )

A flag is a symbolic constant that can either be static or dynamic. Dynamic flags are described in Section 4.1.

A matrix is a 4x4 matrix used to perform a general transformation. Matrices are written in row order as 16 floating point numbers enclosed in parentheses. The matrices are used to transform row vectors. A matrix can be dynamic just like a triple, and a pointer can be substituted for a dynamic matrix. This is described in Section 4.1.

Two other basic GLIDE elements are names and strings. A name is a sequence of alphanumeric characters that constitutes a valid C identifier name. A string is any valid C expression or filename surrounded by $ signs. For example, i and mouse_position_0 are valid names, while $5.3$, $i+4$ and $../include/cube.glf$ are valid strings.

The arguments following a keyword in a GLIDE statement are either a triple, an identifier, an idlist, a flag, a matrix, a pointer, a name or a string. They are denoted by suffixes of triple, id, idlist, flag, matrix, pointer, name or str respectively.

3 Defining static scenes

The only statement in declaration-statements for a static file is

static

This statement should appear in all static files before any of the scene-statements

scene-statements is a sequence of zero or more of the GLIDE statements described in the following secions to describe both the objects and viewing parameters in the scene. In the GLIDE statements listed below, all keywords are indicated in boldface.

3.1 Object description statements

The fundamental geometric object supported in GLIDE is a polyhedron - a solid object bounded by polygonal faces. In GLIDE, a polyhedron is described using a boundary representation (B-REP) by defining the individual polygonal faces that bound an object. Each polygonal face is described as an ordered list of vertices, the perimeter of the face being constructed by connecting these vertices in order. In GLIDE, vertices, polygonal faces and the polyhedra that they bound are defined by the point, face and object statements.

The vertices of an object are defined in the object's local space known as the Object Coordinate System.

point id pointtriple

A point statement defines a point whose position in 3D is given by pointtriple. For example:

point 3 (0 0 5.6)

defines a point with identifier 3 to lie on the z-axis, 5.6 units from the origin.

face id surfaceid pointidlist

A face statement describes a planar polygon which has surface properties specified by surfaceid and is formed by connecting the points listed in pointidlist. The first and last points in the list are connected automatically to form a closed polygon. The order in which the points are defined is important. The outside of the face is the side from which the points appear in a counter-clockwise order. For example:

face 4 5 (1 2 3 4)

defines a face with identifier 4, whose surface properties are defined by the surface whose identifier is 5, and whose boundary is defined by the points with identifiers 1, 2, 3 and 4 in order.

A surfaceid of 0 indicates that no surface is currently defined for this face, allowing an appropriate surface to be defined later during instancing.

surfaceid can be an included identifier as explained in Section 3.6.

object id solidflag shadingflag faceidlist

An object statement describes a polyhedron bounded by the polygons listed in faceidlist. solidflag can have a value of either SOLID_FLAG or HOLLOW_FLAG. A value of SOLID_FLAG indicates that the object has a closed hull filled with solid material, therefore allowing back-facing polygons to be discarded during rendering. A value of HOLLOW_FLAG means that the object is hollow, and perhaps not even closed. The faces are thus considered to be two-sided and no back-face removal can be performed. shadingflag defines the way the object is shaded during rendering. It can have a value of either WIRE_FLAG, FLAT_FLAG, GOURAUD_FLAG, PHONG_FLAG or MAX_FLAG, that respectively represent wireframe, flat shading, Gouraud shading, Phong shading or the best shading that the renderer supports.

For example, the following statements define a regular tetrahedron centered at the origin.
    point 1 (1 -1 1)
    point 2 (-1 1 1)
    point 3 (1 1 -1)
    point 4 (-1 -1 -1)

    face 1 1 (2 1 3)
    face 2 1 (4 3 1)
    face 3 1 (3 4 2)
    face 4 1 (1 2 4)

    object 1 SOLID_FLAG MAX_FLAG (1 2 3 4)
surface id colortriple shadingtriple lightingtriple

A surface statement defines the material properties of a surface. colortriple defines the diffuse color of the surface as an RGB triple, where the red, green and blue components are each between 0 and 1. shadingtriple specifies coefficients of reflectivity for ambient, diffuse, and specular reflection. lightingtriple defines parameters for lighting models. The first float is the exponent in the Phong lighting term. The second float is the metallic factor of the surface and is used to calculate the specular color of the surface from its diffuse color and the color of the illuminating light. The third float is ignored and is optional. The use of these terms is explained in Section 3.3.

3.2 Statements to define cameras

The objects are viewed through a camera to produce the corresponding image. The 2-dimensional image is created by projecting the portion of the world visible through the camera down from 3-dimensions. This projection is easily calculated (as a simple division) if the image plane passes through the origin and is normal to the principal viewing direction, which is along a principal coordinate axis. This is called a canonical viewing position. However, the positions and principal viewing directions of a camera are arbitrarily defined in the World Coordinate System and, in general, are not in canonical positions. Rather than directly performing the projection in World coordinates, it is easier to first transform the objects into a new coordinate system in which the camera is canonically positioned, and then perform the projection in this coordinate system. This new coordinate system is called the View Reference Coordinate System (VRCS).

The camera statement defines a camera that can be used to view a part of the world.
camera id
        projection projectionflag
        cop coptriple
        vrp vrptriple
        vup vuptriple
        vpwindow lefttriple righttriple
        clipplanes cliptriple
endcamera


Figure 1: Definition of the VRCS

The projectionflag defines the type of projection made by the camera. Its value can be either PARALLEL_FLAG to represent a parallel projection, or PERSPECTIVE_FLAG to represent a perspective projection.

The coptriple defines the Center of Projection (COP) in the case of a perspective projection. It is the location of the camera in Object coordinates. In the case of a parallel projection, the actual center of projection is at infinity, and the COP value is used to calculate the direction of projection.

The vrptriple defines the View Reference Point (VRP) in Object coordinates. This is the point on which the camera is fixated, the center of attention. It is the origin of the VRCS. The COP and the VRP define the View Plane, or image plane. The View Plane passes through the VRP and its normal, the View Plane Normal (VPN), is defined by the vector from the VRP to the COP. In the case of a parallel projection, the direction of projection is the vector from the COP to the VRP. Oblique projections are not supported in GLIDE , so the VPN is always opposite to the direction of projection.

The vuptriple defines the View Up Vector in Object coordinates. Its projection onto the view plane defines the up direction of the projected image.

The VRCS is a right-handed coordinate system and is fully specified by the above three parameters. The origin of the VRCS is the VRP, and its principal axes are called the , and axes. The vector from VRP to COP is the axis. The cross product of the View Up Vector with the axis gives the axis, and the cross product of the axis with the axis gives the axis.


Figure 2: Viewing parameters. The shaded region is the view frustum

The vpwindow statement defines the View Plane Window in the VRCS. lefttriple and righttriple define its lower-left and upper-right corners respectively as (xmin, ymin, *) and (xmax, ymax, *) in View Reference coordinates on the image plane. * indicates that the third component of the triple is ignored and is hence optional. The viewing pyramid is defined to have its apex at the Center of Projection and pass through the four corners of the View Plane Window.

The clipplanes statement defines the front and back clipping planes that truncate the viewing pyramid to produce a frustum. cliptriple is interpreted as (zfront, zback, *) where zfront and zback define the distances of the front and back clipping planes respectively from the View Reference Point. These distances are measured along the View Plane Normal. Again, the * indicates that the third component of the triple is ignored and is hence optional. For anything to be visible, zfront must be closer to the COP than zback.

All these parameters need not be defined for each camera. If a parameter is not defined, its corresponding default value is used. The defaults are:

camera id
        projection 	PERSPECTIVE_FLAG
        cop 0 0 1
        vrp 0 0 0
        vup 0 1 0
        vpwindow (-1 -1) (1 1)
        clipplanes (1 -1)
endcamera

3.2.1 Differences between GLIDE and PHIGS viewing models

The GLIDE viewing model is a simplification of the PHIGS viewing specification. There are two differences between the PHIGS and GLIDE viewing models. In PHIGS, the COP is defined in the VRCS, not in Object coordinates. Secondly, for parallel projections, PHIGS defines the direction of projection to be the vector from the COP to the center of the View Plane Window, while GLIDE defines the direction of projection to be -VPN.

3.3 Statements to define lighting

GLIDE supports four types of light sources - ambient, directional, point and spot lights. All these different types of lights share the same identifier namespace.

ambientlight id colortriple

directionallight id colortriple directiontriple

pointlight id colortriple pointtriple fallofftriple

spotlight id colortriple pointtriple directiontriple fallofftriple

The ambient light affects a surface regardless of geometry. A directional light is located at infinity and does not attenuate with distance, but shines in a given direction. A point light is located at a finite position and radiates light equally in all directions. A spot light is also located at a finite position, but its light is radiated along a principal direction. colortriple defines the RGB components (between 0 and 1) of the color of a light. pointtriple defines the position of a light in 3D space. directiontriple defines the principal direction in which a light points in 3D space. The first float of fallofftriple defines the dead distance for the attenuation with distance. The second float defines the exponent for the attenuation with distance. The third float defines the exponent for the angular falloff between the principal direction of the light and the vector from the light to the point being illuminated. This last float is used only in the case of a spot light and is optional in the case of a point light.

3.3.1 Explanation of GLIDE lighting

The following symbols are used below: Note: , , and are all unit vectors.


Figure 3: Vectors Used in Lighting Calculations
surface id ambientlight id

Specifies the background illumination. It only makes sense to define one ambient lighting term, so only the last ambientlight statement in a GLIDE file is relevant. The color of a surface illuminated by ambient light is

directionallight id

This is a light source at infinity with light being radiated in one principal direction . In this case and is constant for all points under consideration. The color of a surface illuminated by a directional light source is

pointlight id
This is a light source located at that radiates light equally in all directions. is now different for each point on the surface and is the vector from the point under consideration to the light source. is the ``dead distance'' and is the exponent in the falloff factor. If is the distance from the light source to the point under consideration, the color of a surface illuminated by a point light source is

spotlight id

This is a light source located at but like a directional light source, it radiates light in one principal direction. is the vector in the principal direction of the radiated light. again is different for each point on the surface and is the vector from the point under consideration to . is the distance from the light source to the point. and are the same as for a pointlight and is exponent of the cosine of the angle between and . The color of a surface illuminated by a spotlight is

The final color of the point under consideration is the sum of the ambient term and the colors contributed by each directional, point, and spot light source.

3.4 Statements to build hierarchies

Objects whose component vertices are initially defined in local coordinate systems, are appropriately placed and oriented in the World Coordinate System by the application of geometric transformations. A modular way of constructing a complicated scene is to build up a hierarchy by creating multiple instances of primitive objects and appropriately altering the geometric and appearance attributes of each of these instances. Geometric attributes are altered by the application of geometric transformations. Cameras and lights can also be similarly instanced.

In GLIDE, such a hierarchy is built up in a recursive manner using groups which are equivalent to compound objects. Groups are collections of instances of both primitive objects as well as other groups, lights and cameras.
group id  
      instance-statement 
      instance-statement 
      ...
endgroup

instance-statement ::=  geometry-instance-statement | 
                        camera-instance-statement | 
                        light-instance-statement

geometry-instance-statement ::= instance grobjid surfaceid shadingflag [ onoffflag ] 
                                         transformation-statement 
                                         transformation-statement 
                                         ... 
                                endinst

camera-instance-statement ::=   camerainstance cameraid [ onoffflag ]
                                               transformation-statement 
                                               transformation-statement 
                                               ... 
                                endinst

light-instance-statement ::=    lightinstance lightid  [ onoffflag ] 
                                              transformation-statement 
                                              transformation-statement 
                                              ... 
                                endinst

transformation-statement  ::=   translate  translatetriple |
                                scale  scaletriple |
                                rotate  axistriple angletriple |
                                general  generalmatrix | 
                                <empty-string>
The translate, scale, rotate and general statements define transformations. These statements may only occur within an instance-statement. translatetriple and scaletriple specify the 3D translation and scaling respectively. The axistriple defines the direction of the axis of rotation. The angle of rotation is given in degrees by the first float in angletriple. The last 2 floats in angletriple are ignored and hence are optional. generalmatrix is a 4x4 homogeneous transformation matrix in the form that transforms row vectors.

Groups and objects share the same local identifier name space. The group statement is used to define the scene hierarchy. The three different types of instance statements may only occur within a group statement. Each instance includes transformations which place the referenced entity with the coordinate space of the current group. The transformations within an instance-statement are applied one at a time, from the outside, (i.e. in a command post sense) in the order specified.

grobjid, lightid and cameraid in the instance statements can be included identifiers. This is explained in Section 3.6.

3.4.1 Geometric instances

The geometry-instance-statement is used to create an instance of either an object or another group specified by grobjid.

For example, the following statements define an instance of the tetrahedron defined in Section 3.1. This new tetrahedron is twice the size of the original one and is also rotated about the z-axis by 30 degrees.
    group 2
        instance 1 0 MAX_FLAG
            scale (2 2 2)
            rotate (0 0 1) (30)
        endinst
    endgroup
Each geometric instance has an associated surfaceid. As explained in Section 3.1, faces of objects can be defined without associated surfaces (by making surfaceid have a value 0 in a face statement). When such an object is instanced, all its faces that do not have associated surfaces will take on the properties of the surface defined by the surfaceid in the instance statement. Faces that already have associated surfaces will not be affected by this.

For example:
    face 1 4 ( ... )
    face 2 0 ( ... )

    object 1 SOLID_FLAG PHONG_FLAG (1 2 ... )
    object 2 SOLID_FLAG WIRE_FLAG (1 2 ... )
    
    group 3
        instance 1 5 FLAT_FLAG ON_FLAG
            ...
        endinst
        instance 2 0 FLAT_FLAG
            ...
        endinst
    endgroup
In the above example, in the instance of object 1, face 2 has the surface properties of the surface with identifier 5 (since it did not originally have an associated surface), while face 1 (which was defined with an associated surface) continues to have the surface properties of surface 4.

If surfaceid is 0, then nothing is changed in the object and a higher level instance can then be used to set the surface properties of faces without associated surfaces. In the above example, face 2 in instance 2 still does not have an associated surface.

Each geometric instance also has an associated shadingflag that defines the way every object in the instance is shaded during rendering. shadingflag can have values WIRE_FLAG, FLAT_FLAG, GOURAUD_FLAG, PHONG_FLAG or MAX_FLAG where the interpretation of the flags is the same as in the object statement (Section 3.1). If shadingflag is less than (i.e. lower shading quality) the shading flag of an object or another instance beneath the current instance in the hierarchy, then the value of shadingflag overrides the other flag. In other words, the effective shading flag of a particular instance of an object is the lowest of all the shading flags above it. In the above example, the instance of object 1 in group 3 is flat shaded, because the lower FLAT_FLAG defined in the instance overrides the original PHONG_FLAG of the object. On the other hand, the instance of object 2 is wireframe as the original WIRE_FLAG is not overridden by the higher FLAT_FLAG of the instance.

Finally, each instance has an optional onoffflag that can be used to selectively disable that part of the hierarchy. onoffflag can take values either ON_FLAG or OFF_FLAG. If its value is OFF_FLAG, then this instance cannot be traversed. If onoffflag is not specified, the default value is ON_FLAG.

3.4.2 Camera instances

The camerainstance statement similarly creates an instance of a camera (cameraid). onoffflag is an optional flag that can take values ON_FLAG or OFF_FLAG. A value of OFF_FLAG defines this camera to be turned off, while the default value of ON_FLAG defines the camera to be turned on. Cameras are explained in Section 3.2.

Since many of the parameters that define a camera are geometric in nature, cameras can be instanced in groups with the appropriate transformations applied to these attributes. This allows cameras to be conceptually attached to geometric objects and be transformed along with the objects.

A camera has a global viewing effect, meaning that it can create an image of any part of the scene, irrespective of its location in the group hierarchy. Cameras are only tied to this hierarchy in order to allow their geometric attributes to be transformed in the same way as objects.

3.4.3 Light instances

The lightinstance statement creates an instance of a light (lightid). The optional onoffflag is identical to that in the camerainstance statement in that its value can be either OFF_FLAG, or the default ON_FLAG. lightid can be an ambient, directional, point or spot light. Section 3.3 describes the various types of lights and the statements that define them.

Lights have certain geometric attributes (position, principal direction etc.) and these will be transformed by the transformations applied to the instance. This allows lights to be integrated with objects in the scene (for instance, headlights attached to the front of a car), thereby allowing for the same transformations to be applied to both the objects and the lights.

All lights have a global effect, meaning that they illuminate everything in the scene, irrespective of where they appear in the object hierarchy. Multiple instances of the same light add their contribution to the cumulative illumination. Note that this is different from cameras, where only one instance of the same camera can be active.

3.5 Statements to view a GLIDE scene

The image produced by a camera is rendered into a viewport, which is a rectangular region on a display screen window. Multiple windows can exist simultaneously on the screen and a window can have multiple non-overlapping viewports.
window id
        origin origintriple
       size sizetriple
       normorigin normorigintriple
       normsize normsizetriple
       background colortriple
endwindow
The window statement defines a window on the display screen. The dimensions and location of the window can either be defined in absolute pixel coordinates or in Normalized Device Coordinates (NDC) of the screen between 0 and 1.

The origin is defined in absolute coordinates by the origin statement. origintriple is interpreted as (xmin ymin *) and the lower-left corner of the window is at (xmin ymin) where both xmin and ymin are in absolute pixel coordinates. The normorigin statement defines the window origin in NDC. normorigintriple is interpreted in the same way as origintriple above, except for the fact that xmin and ymin are in NDC.

Similarly, the dimensions of the window are defined either by the size statement for absolute coordinates or the normsize statement for NDC. Both sizetriple and normsizetriple are interpreted as (xsize ysize *) where xsize and ysize are the horizontal and vertical sizes of the window respectively. As before, xsize and ysize are in absolute coordinates for sizetriple, and in NDC for normsizetriple.

If both normalized and absolute coordinates are initialized, the normalized value will override the absolute.

colortriple defines the background color that the window is cleared to. It is an RGB triple.

None of the triples defining the parameters of a window can be dynamic. They must all be static.

All these parameters need not be defined for each window. If a parameter is not defined, its corresponding default value is used. The defaults are:
window id
       normorigin (0 0)
       normsize (1 1)
       background (1 1 1)
endwindow
A viewport is the region of a display device window into which the image on a camera's view plane is mapped.
viewport id
         window windowid
         normextent bottomlefttriple toprighttriple
endviewport
windowid defines the window into which the image is mapped. This can be an included identifier as defined in Section 3.6 The extent of the viewport on the window is defined by bottomlefttriple and toprighttriple, which are interpreted as (xmin ymin *) and (xmax ymax *) respectively. The lower-left corner of the viewport is (xmin ymin) and its upper-right corner is (xmax ymax). xmin, ymin, xmax and ymax are all normalized relative to the window size and are between 0 and 1. As usual, a * in the third value of a triple is ignored and hence optional.

render viewportid cameraid grobjid

A render statement causes the image of some part of the group hierarchy to be rendered into a viewport on a display window. cameraid contains the identifier of the camera that produces the image. viewportid defines the viewport into which the image is drawn.

grobjid defines the root of the portion of the hierarchy that will be rendered. The only entities that exist in the context of this render statement are those that are contained in this hierarchy. Everything not under this hierarchy (geometry, cameras and lights) is ignored.

Any number of render statements can be specified in a single file, but there must be at least one for anything to be displayed.

viewportid, cameraid and grobjid can all be included identifiers, as described in Section 3.6.

There is only one camera associated with each render statement. However, more than one instance of cameraid may exist in the hierarchy rooted at grobjid. Since instances are not given unique identifiers, this creates an ambiguity in which of these instances is referred to by cameraid. By default, the first instance whose onoffflag is set to ON_FLAG encountered in a depth-first search of the hierarchy rooted at grobjid will be used. In other words, if more than one instance is on, then the leftmost instance is chosen. It is thus the responsibility of the user to set the onoffflags of the camera instances appropriately. If there are no instances of this camera, the base-level camera is used.

For example:
    camera 8
    endcamera

    group 1
        # instance A
        camerainstance 8 ON_FLAG
        endinst
    endgroup 

    group 2
        # instance B
        camerainstance 8 OFF_FLAG
        endinst
        # instance C
        camerainstance 8 ON_FLAG
        endinst
    endgroup 

    group 3
        # instance D
        camerainstance 8 ON_FLAG
        endinst
    endgroup 
 
    group 6
        # contains A
        instance 1 0 MAX_FLAG OFF_FLAG
        endinst
        # contains B, C
        instance 2 0 MAX_FLAG ON_FLAG
        endinst
    endgroup

    group 7
        # contains D
        instance 3 0 MAX_FLAG ON_FLAG
        endinst
        # contains A, B, C
        instance 6 0 MAX_FLAG ON_FLAG
        endinst
    endinst

    render 45 8 6
In the example above, there are four instances of camera 8 (commented as A, B, C and D) in the hierarchy below group 7. The root of the hierarchy to be rendered is at group 6. There are three instances of camera 8 (A, B and C) under it. Of these, instance A is not encountered in a traversal because the instance of group 1 is turned off. That leaves instances B and C. B is the first instance of camera 8 encountered in a depth-first traversal of group 6. Since it is turned off it is not used. The first instance of camera 8 that is on is C, and hence it is the one that is used to generate the image.

3.6 Including Files

include-statements is a sequence of zero or more include statements of the following form:

include filestr fileid

This statement causes the GLIDE file filestr to be included in the current environment. Inclusion defines a new scope for identifiers, so there will be no conflict between entities with the same id in both the including and included files. fileid is the identifier used to reference the scope created by this inclusion and is a positive integer less than 4096. Objects, groups and surfaces within this scope can be accessed by the including file. An identifier defined in the include file can be referenced as:

includeid ::= fileid : id

Included identifiers can refer to groups, objects, surfaces, cameras, windows and viewports. As noted earlier, the face, instance, lightinstance, camerinstance, viewport and render statements can use included identifiers.
include $cube.glf$  10
include $../lib/icosa.glf$  5
...
face 1 10:3 (1 2 3 4)
...
group 2
    instance 5:2 0 MAX_FLAG
    endinst
endgroup
The surfaces properties of face 1 in the main file now come from the surface 3 defined in cube.glf. Group 2 in the main file contains an instance of group 2 defined in ../lib/icosa.glf. This demonstrates that similar entities in different files can have the same identifiers.

Currently only one level of included scopes can be directly referenced.

4 Defining dynamic scenes

As its name implies, GLIDE allows the modeling of interactive and dynamic environments. A dynamic value is one that is either time-varying or dependent on an input device. The coordinates of points, transformation values, viewing parameters, lighting parameters, flags etc. are not restricted to be constant values but can all be dynamic values.

Dynamic values are obtained by evaluating dynamic expressions that are defined in the GLIDE file. Before a frame is rendered, each dynamic expression is evaluated to provide its current value. Rather than interpret the expressions each frame, a C file containing these expressions is generated. This C file can then be compiled and linked with the renderer. This approach was chosen in the interests of both speed and expressiveness since any valid C expression, including arbitrary C functions, can be used to define a dynamic value.

4.1 Dynamic values

In GLIDE , a dynamic expression is defined by enclosing a valid C expression between $ signs for a scalar value and $$ signs for a vector value.

A C expression returning a float value and surrounded by $ signs can be used in a triple instead of a static float value. Similarly, a C expression returning an appropriate symbolic constant value and surrounded by $ signs can be used in place of a static value for any flag.

The following 6 global variables are defined by GLIDE and their values are updated each frame. The above 6 global variables and the various symbolic constants representing flag values are all defined in the file glide.h.

Examples of valid dynamic expressions are:
    $4+2$
    $100*MOUSE_X$
    $fabs(sin(TIME))$
A dynamic triple contains one or more dynamic float values. A dynamic triple can be used anywhere a static triple can. For example:

scale ( 1.5 $2*fabs(sin(TIME))$ 4 )

defines a scaling transformation where the scale factor in the y-direction is a time-varying value.

translate ($MOUSE_X$ $MOUSE_Y$ $100*log(TIME)$)

defines a translation in which all three components are dynamic.

A matrix is written as 16 floating point values between parentheses. A dynamic matrix is obtained by replacing any or all of these 16 values with dynamic values.

Dynamic expressions can also return pointers to arrays of floats, and in this case, they must be surrounded by $$ signs. For example:

point 3 ( $$get_coords()$$ )

initializes the coordinates of point 3 to the three floating point values that the function get_coords() returns a pointer to.

Dynamic expressions returning pointers can be used to set the value of a dynamic triple as well as the value of a dynamic matrix.

A dynamic flag is created by a dynamic expressions that returns an appropriate value for the flag. For example:

camerainstance 5 $(i > 5) ? ON_FLAG : OFF_FLAG$

C code is generated for every dynamic value, so use them only when needed.

4.2 glfc - GLIDE File Compiler

As mentioned earlier, rather than evaluate the dynamic values before every frame by interpreting the dynamic expressions, C functions to evaluate each expression are generated. These functions are called before every frame to obtain the respective values.

glfc (pronounced glyph-see ) is the GLIDE File Compiler that emits the appropriate C code for the dynamic expressions in the GLIDE file. The output C file is named glide.dynam.c and this must be compiled and linked in with the application program. The application program must now call the GLIDE parser on the input file before rendering it. The parser now uses the functions defined in glide.dynam.c to build up the data structures that contain the data defined in the input file.

glfc produces a function for each GLIDE file encountered (i.e. one for the main file, and one for each included file). The function contains code to evaluate each dynamic value in the file.

For example, if the input GLIDE file contains the following definitions:
    point 30 ( 2.5  $10 * MOUSE_X$  $MOUSE_Y * sin(TIME/100)$ )
      ...
    point 44 ( $$get_coords()$$ )
      ...
    camerainstance 5  $ON_FLAG$
      ...
    lightinstance 6  $(dist > 5.5) ? ON_FLAG : OFF_FLAG$
      ...
and assuming that the above values happen to be the 27th, 35th, 102nd and 103rd dynamic values defined in the file, the relevant part of glide.dynam.c will be:
    typedef void (*GLF_FUNC_TYPE)(int, int *, float *);

    void GLF_DYNAMIC_FUNC_0(int _which, int *_intval, float *_floatval)
    {
        float* _floatptr;

        switch (_which) {
              ...
            case 27:
                _floatval[0] = 2.500000f;
                _floatval[1] = 10 * MOUSE_X;
                _floatval[2] = MOUSE_Y * sin(TIME/100);
                break;
              ...
            case 35:
                _floatptr = get_coords();
                _floatval[0] = _floatptr[0];
                _floatval[1] = _floatptr[1];
                _floatval[2] = _floatptr[2];
                break;
              ...
            case 102:
                *_intval = ON_FLAG;
                break;
              ...
            case 103:
                *_intval = (dist > 5.5) ? ON_FLAG : OFF_FLAG;
                break;
              ...
        }
    }
get_coords() will have to be defined externally as a function returning a pointer to an array of 3 floats and dist will have to be defined externally as well.

The dynamic information in the input file to the parser must be the same since glfc was last run on the file. The behavior of the parser cannot be predicted if the dynamic values in its input file are different from those when glide.dynam.c was last made. If any dynamic information is changed, glfc must be run again on the file and the application must be rebuilt with the new glide.dynam.c .

Since no code is generated for static values, do not use dynamic values unless necessary. In the above example, if the flag argument to the camerainstance statement were not surrounded by $ signs, it would have been interpreted as a static value and no code would have been generated for it.

4.3 Declaration statements

declaration-statements is a sequence of statements in the following order:

static-statement
include-statements
cfile-statements
var-statements

4.4 Static Declaration

If a file is declared to be static then code generation for it can be optimized as glfc will not have to generate code for any triples in this file. If an included file is declared to be static, no code is generated for it.

static-statement is an optional static statement.

static

If this is the first statement in a GLIDE file following the version statement, the file is declared to be static. An error will result if a file is declared to be static, but either the file itself or any files that it includes contains a dynamic expression.

If the first statement following the version statement is something other than a static statement, then the file is assumed to contain dynamic values. Included files in this case may be static.

4.5 Variables

Variables can be used to represent common subexpressions that occur in many dynamic expressions. var-statements is a sequence of zero or more var statements.

var typename varname assignstr

typename
is any standard C type that can appear on the left-hand side of an assignment. varname is the name of the variable, and this can be an array. assignstr is the C statement that assigns the appropriate value to the variable.

For example:
    var float t1     $t1 = 5*TIME + 2$
    var float m[16]  $init_matrix(m)$

    point 2 3 (5 0 $2 * t1$)
      ...
    group 5
        instance 4 0 MAX_FLAG
            general ( $$ m $$ )
        endinstance
    endgroup
This defines a float variable t1 whose value is 5*TIME + 2 and a point whose z-coordinate changes with time as 10*TIME + 4. m is a matrix whose value is initialized by the function init_matrix() and it is then used to transform instance 4 in group 5.

4.6 Using C functions in dynamic expressions

Since a dynamic expression can be any valid C expression, GLIDE allows these expressions to contain calls to externally defined functions. There are two ways in which these external routines can be defined.

cfile-statements is a sequence of zero or more cinclude and extern statements.

cinclude filestr

filestr
, which is assumed to be the C file containing auxiliary functions, is textually included into the C file generated by glfc. This will thus have to be recompiled every time the GLIDE file is altered.

extern typename funcstr

This statement generates a corresponding extern statement in the C file generated by glfc, defining funcstr to be of type typename. The file containing the referenced functions or variables must then be linked together with the application.

For example, the following GLIDE command

extern float $*slider_value(float min, float max)$

will cause the following line to be output in glide.dynam.c :

extern float *slider_value(float min, float max);

Thus the application program will have to define the function slider_value to fit this prototype.

5 Hints on Style

If GLIDE objects are defined in a modular fashion, it enables the building of a library of objects that can be shared. There are a few guidelines to follow to facilitate this sharing.

All files should be appropriately commented, clearly describing what each object and group represents. Independent, complicated objects should ideally be in separate files.

Many dynamic values are defined to be functions of the GLIDE built-in global variables TIME, MOUSE_X, MOUSE_Y and FRAME. Since they are global, GLIDE does not provide a direct way to create instances of them with different transformations. For example, if a dynamic object is defined to rotate as a function of TIME, there is no direct way to make the object rotate faster without explicitly rewriting its dynamic expression. This rewriting will be made easier if every independent use of a global built-in does not use the built-in directly. A level of indirection can be added by writing the expression as a function of a local variable. For example, a behavior written as an explicit function of TIME, can be rewritten as a function of a local variable t1, defined as var float t1 $TIME$. It is now easy to transform t1 to be $3*TIME + 4.5$ to scale time by a factor of 3 and add an offset of 4.5.

6 A GLIDE example

This example defines a simple wheel rolling on the horizontal plane. The direction of movement of the wheel is controlled by the x-coordinate of the mouse. The following file defines a static wheel.
    GLIDEv2.0

    # FILE: wheel.glf
    
    # define a very primitive wheel 
    #     id of wheel = 2

    # define a wedge as 1/6th of the wheel
    point 1 (0.173 0.1 0.2)
    point 2 (0.173 -0.1 0.2)
    point 3 (0.866 0.5 0.2)
    point 4 (0.866 -0.5 0.2)
    point 5 (0.173 0.1 -0.2)
    point 6 (0.173 -0.1 -0.2)
    point 7 (0.866 0.5 -0.2)
    point 8 (0.866 -0.5 -0.2)

    surface 1 (1.0 0.0 0.0) (0.4 0.5 1.0) (120 0.5 0)
    surface 2 (1.0 1.0 1.0) (1.0 1.0 1.0) (120 0.5 0)

    # form the faces of the wedge
    face 1 0 (1 2 4 3)
    face 2 0 (7 8 6 5)
    face 3 0 (5 6 2 1)
    face 4 0 (1 3 7 5)
    face 5 0 (2 6 8 4)
    face 6 0 (8 7 3 4)

    # the wedge
    object 1  SOLID_FLAG  FLAT_FLAG  (1 2 3 4 5 6)

    # define 6 instances of the wedge suitably rotated to 
    #    create the entire wheel
    group 2
        instance 1 1  FLAT_FLAG
        endinst
        instance 1 2  FLAT_FLAG
            rotate (0 0 1) (60)
        endinst
        instance 1 1  FLAT_FLAG
            rotate (0 0 1) (120)
        endinst
        instance 1 2  FLAT_FLAG
            rotate (0 0 1) (180)
        endinst
        instance 1 1  FLAT_FLAG
            rotate (0 0 1) (240)
        endinst
        instance 1 2  FLAT_FLAG
            rotate (0 0 1) (300)
        endinst
    endgroup
The following file defines the C function that incrementally updates the position of the wheel. We need a mechanism to be able to remember the previous position of the wheel, and this is provided using static variables in a C function.
    /*
        FILE: turtle.c

        A function to return the current position of the wheel
        calculated incrementally in a turtle geometry fashion
   
        The coordinates of the position are stored in the static
        external array pos, and a pointer to this is returned.
     */

    #include "glide.h"

    static float pos[3] = {0.0, 0.0, 0.0};

    float *
    get_pos(float vel, float ang)
    {
        pos[0] += vel * (cosf(ang*3.14/180.0f));
        pos[1] -= vel * (sinf(ang*3.14/180.0f));

        return pos;
    }
Finally, the main GLIDE file includes wheel.glf and textually includes the C file turtle.c and defines the dynamic wheel.
    GLIDEv2.0

    # include file wheel.glf giving it filedid 1
    include $wheel.glf$ 1
    
    # include the C file with the turtle geometry function
    cinclude $turtle.c$
    
    # define variables 
    # angle defines the orientation of the wheel as a function
    #    of the mouse position
    var float angle $angle = MOUSE_X*360$
    
    # vel defines the linear velocity of the wheel
    var float vel $vel = 0.02$
    
    # a stationary camera
    camera 1
        vrp (0 0 0)
        vup (0 1 0)
        cop (0 0 5)
        clipplanes (20 -20 0)
        projection PERSPECTIVE_FLAG
    endcamera
    
    # lights to illuminate the scene - they have a global effect
    ambientlight 1 (0.5 0.5 0.5)
    pointlight 2 (0 0 1) (0 3 0.5) (0.1 1 0)
    
    # instance the wheel and move it around
    group 2
        # instance object 2 from wheel.glf
        instance 1:2 0 FLAT_FLAG
            # rotate the wheel about its axis
            rotate (0 0 1) ($-TIME*60$)
            # make the wheel point in the direction of angle
            rotate (0 1 0) ($angle$)
            # find the new position of the wheel
            translate ($$get_pos(vel, angle)$$)
        endinst
        
        # instance camera 1
        camerainstance 1
            # transform the camera to be located 3 units above the
            #   wheel and pointed in same direction as the wheel is
            #   heading and tipped downwards 
            rotate (1 0 0) (-45)
            rotate (0 1 0) ($angle$)
            translate ($$get_pos(vel, angle)$$)
        endinst
    
        # instance the lights
        lightinstance 1
        endinst
        lightinstance 2 
        endinst
    endgroup

    # make the root of the world with a stationary camera
    #  and the previously defined group
    group 1
        camerainstance 1
        endinst
    
        instance 2 0 FLAT_FLAG
        endinst
    endgroup
    
    window 8
    endwindow
    
    viewport 10 
        window 8
        normextent (.1 .1) (.9 .9)
    endviewport
    
    window 2
        normorigin (0 0)
        normsize (0.2 0.2)
    endwindow
    
    viewport 11
        window 2
    endviewport
    
    # render the wheel into viewport 10 
    #   the first instance of camera 1 encountered in traversing group 1
    #   is the stationary one
    render 10 1 1
    
    # render the wheel into viewport 11
    #   the first instance of camera 1 encountered in traversing group 2
    #   is the moving one
    render 11 1 2

7 Defaults

The following lists the parser-initialized defaults for GLIDE :
camera id
        projection 	PERSPECTIVE_FLAG
        cop 0 0 1
        vrp 0 0 0
        vup 0 1 0
        vpwindow (-1 -1) (1 1)
        clipplanes (1 -1)
endcamera

viewport id
         window windowid
         normextent (0 0) (1 1)
endviewport

window id
       normorigin (0 0)
       normsize (1 1)
       background (1 1 1)
endwindow
The optional onoffflags in the instance, camerainstance and lightinstance statements defaults to ON_FLAG.

The default surface properties for faces without associated surfaces is
surface 0 (0.2 0.9 0.2) (1 1 0) (0 0 0)

8 Authors

Maryann Simmons and Fielding Mellish.

The static part of the language is loosely based upon SDL (Scene Description Language). SDL was the descendant of many generations of object representation languages used in CS 184 over the years. Carlo Sèquin defined the instancing model.

Ken Geis and Lucas Pereira helped with upgrading GLIDE to Version 2.0 including the revision of the parser and the data structures.


WWW Maven: Dan Garcia (ddgarcia@cs.berkeley.edu) Send me feedback