GLIDE 2.0
Graphics Language for Interactive and Dynamic Environments
0 Table of Contents
- Introduction
- Language Overview
- Basic elements
- Defining Static Scenes
- Object description statements
- Statements to define cameras
- Differences between GLIDE and PHIGS viewing
models
- Statements to define lighting
- Explanation of GLIDE lighting
- Statements to build hierarchies
- Geometric instances
- Camera instances
- Light instances
- Statements to view a GLIDE scene
- Including Files
- Defining dynamic scenes
- Dynamic values
- glfc - GLIDE File Compiler
- Declaration statements
- Static Declaration
- Variables
- Using C functions in dynamic expressions
- Hints on Style
- A GLIDE example
- Defaults
- 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:
- : the light vector, has direction opposite to the
direction of incident light.
- : the ``view vector'' - not to be confused with
the GLIDE view vector. It is the vector from the point under consideration
to the COP.
- : the surface normal on the same side of the surface
as . Note that this is not necessarily the outward
surface normal.
- : the ``reflection vector'' - calculated as
Note: , , and are all unit
vectors.
Figure 3: Vectors Used in Lighting Calculations
- - the distance from the light source to the point
under consideration.
- - a color triple. Each of the equations below involving
or any subscripted , can be decomposed
into 3 equivalent equations for the red, green and blue color components.
Each of the color values must lie between 0 and 1. If in any of the calculations
a color value falls outside this range, it must be normalized.
- - The diffuse color of a surface - given by the
colorvalue in a surface statement.
- - The specular color of a surface - calculated
from
- - The color of the illuminating light - given by
the colorvalue triple in any light statement.
surface id
- specify the ``diffuse color'' of the surface -
i.e. the color of the surface when viewed under diffuse illumination (or
the normal color of the surface). This is .
- , and are the ambient,
diffuse and specular reflection coefficients respectively.
- is the exponent in Phong's specular term.
- is the ``metallic factor'' of the surface and is
used to calculate , the ``specular color'' of the surface.
If is the color of the illuminating light:
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.
- TIME: a float indicating the time (in seconds) elapsed since
the application started running.
- MOUSE_X: a float indicating the X-coordinate of the mouse cursor
position expressed in normalized screen device coordinates (between 0 and
1).
- MOUSE_Y: a float indicating the Y-coordinate of the mouse cursor
position expressed in normalized screen device coordinates (between 0 and
1).
- FRAME: an unsigned int indicating the current frame number since
the application started running.
- RESOLUTION_X: an unsigned int indicating the horizontal resolution
of the display screen (in pixels).
- RESOLUTION_Y: an unsigned int indicating the vertical resolution
of the display screen (in pixels).
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