A GLASS objectA GLASS object is a structured 3D object. Its shape is made up of components, which are the solid parts of the object. These are linked together by a structure which is fixed when it is created (by hand or using an editor), but the objects shape can be modified by using variables, that change "joints" in the object. Feedback is available by using active points that give the position and direction of specific places in the object.
These three usable parts, the components, variables, and active points are explained in more detail below.
A component is a collection of triangles. It is the smallest unit in a GLASS object, and is what is linked together to make the object. The triangles are stored internally in the GLASS object structure, or by using openGL display lists. Each component has a unique name, allowing its visibility to be modified, or for it to be drawn on its own.
Variables control the transforms that link the components together. Each variable has a unique name, a value, and the minimum and maximum values the variable can take. By modifying one variable, the shape of the GLASS object can be changed.
Active points can be present in the object. An active point allows the program using the GLASS object to find the position and direction of a point in the object, after it has been moved by the various transforms. Each active point has a unique name.
Using GLASS in a projectTo use a GLASS object the following things must be done:
Optionally, libraries may be used.
For GLASS to work, openGL must be correctly set up. The display must be set up (using GLUT
for instance), lighting must be prepared if it is to be used, depth testing must be
enabled, back face culling (if wanted), and the desired blending function set up.
As is with openGL if the display is correctly set up
then the default settings will enable most GLASS objects to be displayed fine, but you
will want to consider these settings for efficient/correct display.
The version of glass can be obtained using the function:
This returns a string that describes the current version of glass. For example, for
version 1.0.0 this returns "1.0.0" (like you'd never expect). The string is used
internally by GLASS so don't free it!
First your program will need to include the GLASS header file glass.h, with the following standard command.
A GLASS object is stored in the GlassObject structure. The internals of the structure are not relevant, all that is required is that this structure is passed to the GLASS functions. An empty GLASS object is then declared as follows:
Where foo is the name of the object you want to create.
To actually load a glass object all you need to use the first GLASS function. Keep in mind that loading the object will create textures, and display lists.
The prototype for the loading function is:
Where fname is the path of the object file. This returns a pointer to the GLASS object.
Using the previous example, the GLASS object in the file models/hello.model would be loaded using:
So now you have a loaded GLASS object (assuming the object was valid).
Objects can be grouped together into libraries, which allow objects to share textures/materials/components/variables/active points. The prototype of the function that creates GLASS libraries is:
Where name is the name of the new library. This returns a pointer to the GLASS library. The GLASS library pointer is dealt with in the same way as a GLASS object pointer.
To add objects to this library, the following function is used:
Where library is the pointer to the library created (as above), fname is the path of the GLASS object file. This returns a pointer to the added GLASS object.
The difference between this function, and the previous loading function is that the loaded object is added to the library. When the object is assembling itself while loading, it first looks inside itself for items (variables, active points etc), and then in the other objects in the library. This means it is important that objects are loaded into the library in the correct order, with objects not linking to anything else first.
Libraries are useful in programs where the GLASS objects have an underlining
theme. For example in a space game a fleet of ships might all have the
same gun turrets. By having the turret components stored in a model file,
and this being part of a library, many GLASS objects can access this component
without it having to be defined in each model. This also means you can change
it once, and all ships in the fleet will have the new turret automatically.
Where object is a valid GLASS object, and name is the name of the component/variable/active point. The return values are the index of that component/variable/active point. -1 is returned if the component/variable/active point doesn't exist. The names are case sensitive.
For example if you had loaded a model of a tank, which was made up of two components, the hull, and the turret, which were linked by a rotation in the y-axis controlled by a variable turret heading, and the end of the turret had an active point, barrel; These would be found by:
The values of the variables would all be >= zero, but the value for
com_fish would be -1, since there is no component fish in the object.
The prototypes for retrieving the properties of a variable are:
Where object is a valid GLASS object, and variable is a valid index of a variable in that object. The first and last two functions return the value, minimum value, and maximum value respectively for that variable. The values are stored in the GLfloat format to be compatible with openGL. If the variable doesn't exist the returned values are undefined. The second function returns a pointer to the value of the variable. This is particularly useful as this is a pointer to the actual stored value, and so changes as the variable changes. Since it is used internally it shouldn't be freed or modified. If variable doesn't exist in this case the function returns NULL.
The prototypes for the functions that modify variables are:
Where object is a valid GLASS object and variable is the index of a variable for that object. value is the new value of the variable, and dvalue is the change in value for a variable. Both functions return FALSE if the variable doesn't exist, and TRUE otherwise.
For example with the tank, the following code would rotate the turret by 5 degrees:
Modifying a components visibilityA component can be hidden, or shown. Note that this affects all uses of this component, as components can be reused in one or more models. The prototype is:
Where object is a valid GLASS object, component is the index of a component in that object, and visible is either TRUE or FALSE and is the new visibility state of that component. This function returns FALSE if the component doesn't exist, otherwise TRUE.
For example if the tanks turret exploded, so it was no longer visible, but you still wanted to draw the tank object, the following code would be used:
Drawing components/objectsEither single components can be drawn, or the whole object. Drawing a single component displays only that component, without any transforms. Drawing the object draws the components, by transforming as the structure and variables define, and updating the active points position and direction (if they have changed). These functions just draw triangles to openGL, so make sure that the screen is cleared etc. The prototypes are:
Where object is a valid GLASS object and component is the index of a component in that object. The first function returns FALSE if the component doesn't exist, and the second returns FALSE if an error occurs while drawing the object.
With the tank again... Say that the turret had exploded (see above), and you wanted to draw the tank, with the turret rising above the tank, then you would do the following:
Reading active pointsActive points are only updated when the object is drawn, so you'll want to access them after that has happened. There are two functions for active points, one to return its current position, and one to return the current direction. The prototypes for these are:
Where object is a valid GLASS object and apoint is the index of an active point in that object. These functions return an array of 3 GLfloats for the current position, or direction of the active point. They both return FALSE if the active point doesn't exist. These arrays (like for the variables), are used internally by GLASS and shouldn't be freed or modified, they do however continue to be updated, and can be reused like for the variables.
With the tank example, active points are useful to find where the end of the turrets barrel is, so projectiles can be created at the correct position, and fired in the correct direction. By getting the position of the active point apt_barrel, the position of the barrel (relative to the tank) is found. And the direction of the active point is the direction the barrel is pointing. So when the tank is fired:
Removing GLASS objects/LibrariesWhen you've finished with a GLASS object, it can be freed using the following function:
Where object is a valid GLASS object.
This function removes the object, and everything it used (e.g. textures). Note that now object is an invalid pointer, so setting it to NULL would be a good idea.
To free a library, use:
This will remove the library, and all the objects who are members of it.
And that's it!That's all there is, as you can see (unless this isn't very obvious... :) ), the idea was to keep it simple. If you have any questions/comments feel free to email me at firstname.lastname@example.org. All feedback is appreciated. Feel free to modify the tutorial if you think it necessary, and give me the new version.
Robert Cleaver Ancell Last modified: Fri Aug 17 18:18:48 NZST 2001