GLASS objects are stored in plaintext files, using the following format.
How GLASS reads an object file
GLASS reads the object file by breaking it into words.
A word is a continuous string of non-whitespace characters surrounded by
whitespace, or a string of characters surrounded by double quotes ("). The double quotes
do not count towards the word. For example if a GLASS object file contained the line:
foo
bar "foo bar"
GLASS would read this as three words, `foo', followed by `bar', and `foo bar'.
Comments are started by the hash character (#), and a terminated by the next newline. Comments are completely ignored by GLASS. For example:
# A comment
begin something # Another comment
# More comments
end
GLASS would read this as:
begin something
end
Options in a GLASS object file
The following fields are read from the file:
An example of a texture component is:
begin texture
name "marble texture"
image "textures/marble.rgb"
end
This defines a new texture with the name "marble texture", that uses the image file
"marble.rgb" which is found in the the subdirectory "textures/" which is in the directory
the GLASS object is in.
Materials
Materials define the lit properties, and the texture used by triangles in the GLASS object.
A material component has seven fields. These are:
An example of a material is:
begin material
name "blue marble"
texture "marble texture"
ambient 0.1 0.1 0.8 1.0
diffuse 0.1 0.1 0.8 1.0
specular 1.0 1.0 1.0 1.0
emission 0.0 0.0 0.0 1.0
shininess 10.0
end
An example of a triangle list is:
begin triangle_list
name "marble pyramid"
{
material "blue marble"
pos 0 0.0 0.0 -5.0
col 0 1.0 0.0 0.0
nor 0 0.0 -1.0 0.0
tex 0 0.5 0.0
pos 1 4.330127 0.0 2.5
col 1 0.0 1.0 0.0
nor 1 0.0 -1.0 0.0
tex 1 0.9330127 0.75
pos 2 -4.330127 0.0 2.5
col 2 0.0 0.0 1.0
nor 2 0.0 -1.0 0.0
tex 2 0.0669873 0.75
}
{
material "blue marble"
pos 0 4.330127 0.0 2.5
col 0 0.0 1.0 0.0
nor 0 0.774597 0.447214 -0.447214
tex 0 0.9330127 0.75
pos 1 0.0 0.0 -5.0
col 1 1.0 0.0 0.0
nor 1 0.774597 0.447214 -0.447214
tex 1 0.5 0.0
pos 2 0.0 5.0 0.0
col 2 1.0 1.0 0.0
nor 2 0.774597 0.447214 -0.447214
tex 2 0.5 0.5
}
{
material "blue marble"
pos 0 0.0 0.0 -5.0
col 0 1.0 0.0 0.0
nor 0 -0.774597 0.447214 -0.447214
tex 0 0.5 0.0
pos 1 -4.330127 0.0 2.5
col 1 0.0 0.0 1.0
nor 1 -0.774597 0.447214 -0.447214
tex 1 0.0669873 0.75
pos 2 0.0 5.0 0.0
col 2 1.0 1.0 0.0
nor 2 -0.774597 0.447214 -0.447214
tex 2 0.5 0.5
}
{
material "blue marble"
pos 0 -4.330127 0.0 2.5
col 0 0.0 0.0 1.0
nor 0 0.0 0.447214 0.894427
tex 0 0.0669873 0.75
pos 1 4.330127 0.0 2.5
col 1 0.0 1.0 0.0
nor 1 0.0 0.447214 0.894427
tex 1 0.9330127 0.75
pos 2 0.0 5.0 0.0
col 2 1.0 1.0 0.0
nor 2 0.0 0.447214 0.894427
tex 2 0.5 0.5
}
end
This defines a multi-coloured tetrahedron, that when lit has the material "blue marble".
Variables
A variable controls transforms used by the GLASS object. It has four fields.
An example of a variable is:
begin variable
name "size"
min 0.1
max 10.0
value 1.0
end
An example of an active point is:
begin active_point
name "pyramid tip"
initial_dir 0.0 1.0 0.0
end
The type is followed by n parameters, which can be a floating point constant, or a variable. Variables are used by adding "V::" to the front of the variables name.
Examples of transforms are:
transform TRANSLATE 1.2 -2.1 3.9
transform SCALE_EVEN "V::scale factor"
transform SCALE 1.0 "V::y scale factor" 2.8
An example of two components are:
begin component
index 0
transform SCALE_EVEN "V::size"
list "marble pyramid"
end
begin component
index 1
transform TRANSLATE_Y 5.0
active_point "pyramid tip"
end
To draw the structure, convert the indices of the components to three character numbers, for example the index 21 would go to 021. Start by writing the index of the root component. If the root has a child, its index would go directly below it. If the root has a sibling, its index would be written to the right of the root index, with 8n-3 dashes (-), between them. (n is the number of rows across you want this index). Continue to do this for each component, building up the tree of how the components link together.
This is perhaps hard to explain, but easy to do in practice (see the below examples).
An example of a structure is:
begin structure
000
001
end
This shows that component 000 (index=0), is the root component, and component 001 (index=1), is a child of this component.
An example of a more complicated structure is:
000
001---------------------013-----015
002-----003-----010 014 016
004 005 011 017 019
006 007 012 018 020
008 009 021 023
022 024
As you can see, this way is easier to do by hand, as you can see the "big picture" as
you link the components together. If you had used the next_index, and
child_index fields, you would be more likely to make a mistake.
A complete GLASS object
All the above components can be written into the file in any order, although it is
perhaps a good idea to stick to the above order, to keep the file logical. Collecting
the examples used above, we can create a textured pyramid, with one variable that
changes the size of the pyramid, and a point on the top of the pyramid that allows us to
find out how high it is.
The finished object:
# An example of how to create a GLASS object
# A textured pyramid, with a variable to change the size, and
# an active point to find the height of the pyramid.
#
# See glass.sourceforge.net for details
name "pyramid"
version "1.0.0"
# The texture used by the pyramid
begin texture
name "marble texture"
image "textures/marble.rgb"
end
# The material used by the surfaces of the pyramid,
# uses the above texture
# It's a blue colour
begin material
name "blue marble"
texture "marble texture"
ambient 0.1 0.1 0.8 1.0
diffuse 0.1 0.1 0.8 1.0
specular 1.0 1.0 1.0 1.0
emission 0.0 0.0 0.0 1.0
shininess 10.0
end
# The triangles that make up the pyramid
begin triangle_list
name "marble pyramid"
{
material "blue marble"
pos 0 0.0 0.0 -5.0
col 0 1.0 0.0 0.0
nor 0 0.0 -1.0 0.0
tex 0 0.5 0.0
pos 1 4.330127 0.0 2.5
col 1 0.0 1.0 0.0
nor 1 0.0 -1.0 0.0
tex 1 0.9330127 0.75
pos 2 -4.330127 0.0 2.5
col 2 0.0 0.0 1.0
nor 2 0.0 -1.0 0.0
tex 2 0.0669873 0.75
}
{
material "blue marble"
pos 0 4.330127 0.0 2.5
col 0 0.0 1.0 0.0
nor 0 0.774597 0.447214 -0.447214
tex 0 0.9330127 0.75
pos 1 0.0 0.0 -5.0
col 1 1.0 0.0 0.0
nor 1 0.774597 0.447214 -0.447214
tex 1 0.5 0.0
pos 2 0.0 5.0 0.0
col 2 1.0 1.0 0.0
nor 2 0.774597 0.447214 -0.447214
tex 2 0.5 0.5
}
{
material "blue marble"
pos 0 0.0 0.0 -5.0
col 0 1.0 0.0 0.0
nor 0 -0.774597 0.447214 -0.447214
tex 0 0.5 0.0
pos 1 -4.330127 0.0 2.5
col 1 0.0 0.0 1.0
nor 1 -0.774597 0.447214 -0.447214
tex 1 0.0669873 0.75
pos 2 0.0 5.0 0.0
col 2 1.0 1.0 0.0
nor 2 -0.774597 0.447214 -0.447214
tex 2 0.5 0.5
}
{
material "blue marble"
pos 0 -4.330127 0.0 2.5
col 0 0.0 0.0 1.0
nor 0 0.0 0.447214 0.894427
tex 0 0.0669873 0.75
pos 1 4.330127 0.0 2.5
col 1 0.0 1.0 0.0
nor 1 0.0 0.447214 0.894427
tex 1 0.9330127 0.75
pos 2 0.0 5.0 0.0
col 2 1.0 1.0 0.0
nor 2 0.0 0.447214 0.894427
tex 2 0.5 0.5
}
end
# A variable to control the scale of the pyramid
begin variable
name "size"
min 0.1
max 10.0
value 1.0
end
# An active point to get the height of the pyramid
begin active_point
name "pyramid tip"
initial_dir 0.0 1.0 0.0
end
# The components
# Scale the pyramid, and draw it
begin component
index 0
transform SCALE_EVEN "V::size"
list "marble pyramid"
end
# Translate up to the top of the (unscaled) pyramid, and put
# an active point there. (This component will inherit the
# scale transform from the above one).
begin component
index 1
transform TRANSLATE_Y 5.0
active_point "pyramid tip"
end
# How the components link together
# Could have done this in the definitions of each component,
# but since writing this by hand, it's easier this way
begin structure
000
001
end