There are Geomview notes in brackets interspersed throughout this guide telling you what to do in Geomview to see what we're talking about. Later notes assume you both know how to do and have done what previous notes told you about. All of the files referred to in this document should be in the directory of sample OOGL files that comes with Geomview.
In this tutorial we have included icons for OOGL objects being discussed in each example; you can click on these icons to download the corresponding files which you can load into Geomview.
The OOGL Specification is a complete reference for the syntax of file formats. This tutorial is an attempt to lead you more gently into the world of OOGL.
We start with a very simple object: a square. Specifically, the unit square in the xy plane at z=0.
"square.quad": QUAD -1 -1 0 1 -1 0 1 1 0 -1 1 0
The header "QUAD" identifies the file type. (You can also use the header "POLY" for this type for historical reasons.) A QUAD file is a list of 4*n vertices where n is the number of quadrilaterals. This file only contains one quadrilateral. You can also use this format to specify triangles: just use a degenerate quadrilateral where two of the four vertices are identical. The vertices in this file are simple: just the x,y, and z coordinates of the point.
[GEOMVIEW: Download the file "square.quad" by clicking on the icon above, and save it on your computer. Type "geomview square.quad" from a shell window. Spin the square around with the left mouse after Geomview loads it. Feel free to play with Geomview a while if the fancy strikes you during this tutorial.]
The next file has more complex vertices that include a color with a point.
"csquare.quad": CQUAD -1 -1 0 1 0 0 1 1 -1 0 0 1 0 1 1 1 0 0 1 0 1 -1 1 0 1 0 0 1
It's got the same points as the previous square, but with two red and two green corners. The header is now "CQUAD" to indicate that its vertices contain color information as well as point information. Colors are specified by (r,g,b,a) 4-tuples of floating point numbers between 0 and 1. Any color that can be displayed on a computer screen can be encoded by some combination of red, green and blue. The fourth component, alpha, represents opacity: 0 is transparent and 1 is opaque. The X, NextStep, and some SGI platforms ignore alpha information entirely, but a Renderman snapshot will use the alpha information if transparency is enabled. Some SGI platforms use the alpha information, but the picture is guaranteed to be incorrect.
[GEOMVIEW: Delete the current object by hitting the Delete button. To load csquare.quad, click on the "csquare.quad" icon above. If you're running Geomview from a Unix shell, hit the Load Button and type "csquare.quad" (hit RETURN when you're done typing) into the popup box that appears. (If you're browsing and are not sure about file names, you can use the File Browser Button to look around in a directory.)
You're probably wondering why it's all one color. The default shading mode is flat shading, where each polygon or polygonal face is the same color. The other two shading modes, constant and smooth, will both display multicolored faces where the colors smoothly interpolated between vertices. Constant shading ignores all lighting information, while smooth shading interpolates lighting as well as coloring between the vertices.
To change shading mode, first open up the Appearance panel by clicking on the Appearance line in the More Panels browser. Now switch from mode to mode by clicking on different lines in the Shading browser.]
Time to move on to bigger and better things.
"dodec.quad": QUAD 0 0 0.794654 0 0.491123 0.794654 0.356822 0.491123 0.794654 0.467086 0.151765 0.794654 0 0 0.794654 -0.467086 0.151765 0.794654 -0.356822 0.491123 0.794654 4.89153e-09 0.491123 0.794654 0 0 0.794654 -0.288675 -0.397327 0.794654 -0.57735 -0.187593 0.794654 -0.467086 0.151766 0.794654 0 0 0.794654 0.288675 -0.397327 0.794654 4.36694e-09 -0.607062 0.794654 -0.288675 -0.397327 0.794654 0 0 0.794654 0.467086 0.151766 0.794654 0.57735 -0.187592 0.794654 0.288675 -0.397327 0.794654 0 0.710761 0.35538 0 0.491123 0.794654 -0.356822 0.491123 0.794654 -0.467086 0.642889 0.491123 . . . < 55 lines of numbers deleted>
Now we've got a more interesting object: a dodecahedron. Since dodecahedra have 5-sided faces, each of its 12 faces is actually made out of 5 quadrilaterals for a total of 20 quadrilaterals in this Quad object.
[GEOMVIEW: Delete the square and load "dodec.quad". Since the 5 quadilaterals on each face all fit together perfectly, the fact that there are indeed many of them on each face is only apparent when the edges are drawn. To turn on edge drawing, hit the Edges button on the Appearance panel. ]
There is a much more efficient way of representing a dodecahedron.
"dodec.off": OFF 20 12 30 1.214124 0.000000 1.589309 0.375185 1.154701 1.589309 -0.982247 0.713644 1.589309 -0.982247 -0.713644 1.589309 0.375185 -1.154701 1.589309 1.964494 0.000000 0.375185 0.607062 1.868345 0.375185 -1.589309 1.154701 0.375185 -1.589309 -1.154701 0.375185 0.607062 -1.868345 0.375185 1.589309 1.154701 -0.375185 -0.607062 1.868345 -0.375185 -1.964494 0.000000 -0.375185 -0.607062 -1.868345 -0.375185 1.589309 -1.154701 -0.375185 0.982247 0.713644 -1.589309 -0.375185 1.154701 -1.589309 -1.214124 0.000000 -1.589309 -0.375185 -1.154701 -1.589309 0.982247 -0.713644 -1.589309 5 0 1 2 3 4 5 0 5 10 6 1 5 1 6 11 7 2 5 2 7 12 8 3 5 3 8 13 9 4 5 4 9 14 5 0 5 15 10 5 14 19 5 16 11 6 10 15 5 17 12 7 11 16 5 18 13 8 12 17 5 19 14 9 13 18 5 19 18 17 16 15
The "OFF" header tells us it's a polylist file. The second line in the file tells us that there are 20 vertices, 12 faces, and 30 edges. (The OOGL libraries presently don't use the edges value, so you can just use 0 if you don't happen know the number of edges.) The next 20 lines give a list of vertices. The last 12 lines specify the faces: the first number is the number of vertices in that face. Since our polyhedron happens to be regular, all faces have the same number of vertices (in this case, 5). The rest of the numbers on the line are indices into the above list of vertices.
Besides being far more compact, the Polylist file format embeds connectivity information in the Geom. OOGL has no way of knowing whether any two quadrilaterals in a Quad object are connected. But with a Polylist, OOGL can interpolate normals across connected faces. The normals of an object are used to calculate shading information. Interpolated normals make an object look smooth instead of faceted. This is often desirable if you are trying to approximate a curved surface by breaking it up into small pieces.
[GEOMVIEW: Go ahead and load "dodec.off" without deleting the other one. Now you've got two Geoms in your world. Most actions apply to the currently picked object. When you start up geomview, the currently picked object is the whole world. You can independently control any object in the world by picking it as the target of your actions. Double-clicking the right mouse button when the mouse is over an object picks it: double-clicking the right mouse over empty space picks the whole world. You can also pick objects by clicking on the appropriate line in the Object browser.
The two dodecahedra are probably superimposed. Pick one of them as your target, click on the "Translate" line in the motion browser, and move the picked object away from the center of the world with the left mouse. (To return to "Rotate" mode, click the appropriate line in the motion browser.)
Now pick the whole world again and draw the normals by hitting the "Normals" button on the Appearance panel. Switch between Flat and Smooth Shading modes (by clicking in the Shading browser) and notice that the Polylist changes but the Quad doesn't.
Sometimes using the mouse to click on browser lines and buttons is cumbersome. The bracketed characters shown on the control panels are keyboard shortcuts that duplicate the effect of using the mouse to click on that line or button. For instance, "an" (the "a" stands for "appearance") toggles drawing normals and "t" switches the motion to translation. In a further shortcut, you can use the prefix of an object ("g" or "c" followed by a number, as shown in brackets in the Object browser) before most commands to simultaneously pick an object and do some action to it. For instance, "g0r" lets you immediately rotate the world. ]
Let's compare two ways of coloring a Polylist.
facecube.off: # off file with per face color OFF 8 6 12 1.0 1.0 1.0 1.0 1.0 -1.0 1.0 -1.0 1.0 1.0 -1.0 -1.0 -1.0 1.0 1.0 -1.0 1.0 -1.0 -1.0 -1.0 1.0 -1.0 -1.0 -1.0 4 0 2 3 1 .05 .8 .1 .75 4 4 5 7 6 .2 .05 .8 .75 4 0 4 6 2 .9 .9 .02 .75 4 1 3 7 5 .0 .7 .4 .75 4 0 1 5 4 .1 .4 .7 .75 4 2 6 7 3 .7 .7 0 .75
vertcube.off: # off file with per vertex colors COFF 8 6 12 1.0 1.0 1.0 .05 .8 .1 .75 1.0 1.0 -1.0 .2 .05 .8 .75 1.0 -1.0 1.0 .9 .9 .02 .75 1.0 -1.0 -1.0 .0 .7 .4 .75 -1.0 1.0 1.0 .1 .4 .7 .75 -1.0 1.0 -1.0 .7 .7 0 .75 -1.0 -1.0 1.0 0. 0. 0. .75 -1.0 -1.0 -1.0 1. 1. 1. .75 4 0 2 3 1 4 4 5 7 6 4 0 4 6 2 4 1 3 7 5 4 0 1 5 4 4 2 6 7 3
Everything following a "#" is a comment for humans to read and is ignored by OOGL. The header for a plain Polylist file is optional, but if you have anything besides points in a vertex you do need a proper header. The object is the unit cube, which has 8 vertices, 6 faces, and 12 edges. The first has per-face coloring and the second has per-vertex coloring.
A subtle point: the header for vertcube.off is "COFF" as you would expect but the header for facecube.off is just "OFF" because the header refers only to the structure of the vertices, not the entire file.
[GEOMVIEW: Delete everything by picking the world and hitting the Delete Object button. Now load "facecube.off" and "vertcube.off". Translate one of them away from the center so that you can see what you're doing. Switch both Polylists between Constant, Flat, and Smooth Shading modes.
Shading is done according to light sources that you have control over. To play with the lights, open the Light panel by clicking on the Light line in the More Panels browser. When you hit the Show Lights button, you will see light beams that you can drag around to move the lights. You can also add, delete, change the intensity of, and change the color of lights.]
The vertices of a Mesh file are connected in a rectangular grid.
tent.mesh: CMESH 3 3 0 0 0 1 0 0 1 1 0 1 0 1 0 1 2 0 0 0 0 1 1 0 1 0 1 0 0 1 1 1 1 0 1 0 1 2 1 0 0 0 1 1 0 2 0 1 0 0 1 1 2 1 0 1 0 1 2 2 0 0 0 1 1
The "CMESH" header tells us that this is a Mesh file and each vertex contains both point and color information. The second line means that both the u and v dimensions of the mesh are 3, so there will be 3*3 = 9 vertices. Each vertex that's not on an outer edge is connected to its 4 surrounding neighbots by an edge. In "tent.mesh", only the point (1,1,1) is an inside point. The 9 vertices, when named (u,v), are specified in v-major order, just like an array in C:
(0,0)---(1,0)---(2,0) | | | (0,1)---(1,1)---(2,1) | | | (0,2}---(1,2)---(2,2)
[GEOMVIEW: Delete everything and load "tent.mesh". Go into Smooth Shading mode to see each vertex with its own color so that it's obvious how the points in the file correspond with the image in the viewer.]
If you want the mesh to be closed along either (or both) of the u or v edges, insert either a "u" or "v" in the header just before the "MESH".
"wraptent.mesh": CuMESH 3 3 0 0 0 1 0 0 1 1 0 1 0 1 0 1 2 0 0 0 0 1 1 0 1 0 1 0 0 1 1 1 1 0 1 0 1 2 1 0 0 0 1 1 0 2 0 1 0 0 1 1 2 1 0 1 0 1 2 2 0 0 0 1 1
[GEOMVIEW: Load "wraptent.mesh" and compare the two Meshes, translating them apart from each other as necessary.]
There's an extremely efficient way to describe a mesh when the x and y coordinates match the u and v coordinates of every point.
"ztent.mesh": ZMESH 3 3 0 1 0 0 1 0 0 1 0
"ztent.mesh" is exactly the same shape as "tent.mesh", although its vertices don't have any colors. The header "ZMESH" means that only the z-coordinate of each point is specified and the x and y coordinates of each point are set equal to its (u,v) position in the grid.
[GEOMVIEW: Load "ztent.mesh" to verify that it's really the same shape as "tent.mesh"]
A Vect is a collection of polylines, which are lines with 1 or more vertices. Here's a file specifying an "X" and the x-axis in red, a "Y" and the y-axis in green, and a "Z" and the z-axis in blue.
"xyz.vect": VECT 8 19 3 2 2 2 2 2 3 2 4 1 0 0 1 0 0 1 0 0 0 0 1 0 0 1 -.05 .05 1 .05 .25 1 .05 .05 1 -.05 .25 0 0 0 0 1 0 -.05 1 .25 0 1 .15 .05 1 .25 0 1 .15 0 1 .05 0 0 0 0 0 1 -.05 .25 1 .05 .25 1 -.05 .05 1 .05 .05 1 1 0 0 1 0 1 0 1 0 .6 1 1
The header is always "VECT": no letters can be tacked on the front. The second line means that there are 8 polylines, which have a total of 19 vertices and 3 colors. There is no indexing into a list of vertices like a polylist: every single vertex must be specified separately. The third line lists the number of vertices in each polyline. In "xyz.vect", the only polylines with more than 2 vertices are the upper part of the "Y", which has 3, and the "Z", which has 4. The fourth line lists the number of colors in each polyline. When a polyline has no colors it inherits the previously set color. Next come the 19 vertices: only points are allowed. Finally, the 3 colors are given on the last three lines.
[GEOMVIEW: Delete everything, load and look at "xyz.vect". Do the same thing for all the remaining examples.]
For those who already understand how to create parametric surface patches, the syntax of Bezier surface patches is described in the OOGL man page. The art of constructing parametric surfaces is not easily explained: thus, it is beyond the scope of this tutorial to discuss them.
Lists and Insts are complex Geoms that can be used to create a hierarchical tree of objects.
A List is just a collection of other Geoms.
"ref.list": LIST < xyz.vect < dodec.quad { = QUAD -1 -1 0 1 -1 0 1 1 0 -1 1 0}The header is always exactly "LIST". The first two subgeoms refer to other files, using the syntax " < filename ". We have omitted the optional surrounding braces. The third is a literal, or in-line, object. Although this particular syntax would still work if we left off the surrounding braces and equal sign, very similar syntax would not so we follow the "when in doubt, use braces" rule.
[GEOMVIEW: Geomview looks for filenames in the current directory, the pathname in the GEOMDATA environment variable, and the same directory as the file that it's currently reading.]
An Inst is one or more 4x4 transforms applied to another Geom. These matrices can represent all of the 3D transformations such as rotation, translation, scaling, shearing and perspective. We use 4x4 matrices instead of 3x3 matrices so that we can use homogenous coordinates and concatenate all transformations without treating translations as special cases that require adding instead of multiplying. 4x4 matrices can also be used for such operations such as 4D rotation or projective hyperbolic transformations. A linear algebra or computer graphics textbook is a good place to start if you are unfamiliar with these ideas.
"ref.inst": INST geom { < ref.list } transforms { = TLIST 1 0 0 0 0 1 0 0 0 0 1 0 2 0 0 1 1 0 0 0 0 1 0 0 0 0 1 0 0 2 0 1 1 0 0 0 0 1 0 0 0 0 1 0 0 0 2 1 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 }
The header is always exactly "INST". The value following the "geom" keyword is a filename reference to "ref.list", which is the List we saw above. It could also be an in-line Geom or a handle. We surround the value with braces to avoid ambiguity.
The value of the "transforms" keyword is an in-line TList. It could also be a filename reference or a handle. (See OOGL Specification for specifics.) A TList is actually a full-fledged Geom, but we don't ever load a file like "foo.tlist" into the viewer because TLists are just a collection of transforms with no associated subgeom, so there's nothing to see.
A transform is exactly 16 numbers. The first three are a translations: 2 units in the x, y and z directions, respectively. The last is just the identity. The length of the TList is the number of instantiations of the unit: in this case, 4.
If we could not use instantiation, we would have had to compute 4 entirely new Geoms, since the actual points in space of an object are different if you move it. Since the unit of an Inst can be another Inst, you can build up a complex hierarchy. For instance, to build a solar system you only need to generate one sphere. All the planets can be scaled and translated instantiations of that single Geom.
"warp.inst": INST transform { 1 0 0 0 0 9 0 0 0 0 3 0 0 0 0 1 } geom { < dodec.off }
This Inst has a single transform instead of a list of them. Thus we use the keyword "transform" instead of "transforms". A transform is not a Geom, so there is no header before the 16 numbers. We could also have a handle here. (See OOGL Specification for an explanation of handles.) Finally, we have "dodec.off" as our geom. The order of the geom and the transforms/transform is irrelevant.
This tutorial doesn't document binary files or object appearances. See the OOGL Specification for details.
White space in OOGL files is mostly for the benefit of human readers. "ZMESH 3 3 0 1 0 0 1 0 0 1 0" is a legal OOGL file. The only exception is that there cannot be a line break between the last vertex index for a Polylist face and the next 4 color floats.
[GEOMVIEW: When a Geom is loaded, it is automatically normalized to fit inside a unit cube centered around the origin. The default camera viewpoint is at {0,0,-3} looking toward the origin. To see the unaltered size and position of an object, pick the None line in the Normalization browser on the Obscure panel. In general it doesn't matter what the coordinate range of an object is as long as the entire file is consistent: {0,1}, {-1,1}, {0,100}, {-1000,-500}, {17,36} are all valid ranges.