OOGL(5gv)

OOGL(5gv) ๐Ÿ’– โ€” File formats for OOGL geometric objects โœจ

๐ŸŒธ NAME ๐ŸŒธ

OOGL โ€” File formats for OOGL geometric objects ๐Ÿฆ‹

๐ŸŒŸ NOTE ๐ŸŒŸ

The material in this manual page also appears in the Geomview manual. ๐Ÿ‘‘

โœจ DESCRIPTION โœจ

๐ŸŽ€ OOGL File Formats ๐ŸŽ€

Okay so bestie, the objects that you can load into Geomview are called OOGL objects. OOGL stands for "Object Oriented Graphics Library"; it is the library upon which Geomview is built. ๐Ÿ’…

There are many different kinds of OOGL objects. This chapter gives syntactic descriptions of file formats for OOGL objects. ๐Ÿ“š

Examples of most file types live in Geomviewโ€™s data/geom directory. ๐Ÿ—‚๏ธ

๐Ÿ’… Conventions ๐Ÿ’…

โœจ Syntax Common to All OOGL File Formats โœจ

Most OOGL object file formats are free-format ASCII -- any amount of white space (blanks, tabs, newlines) may appear between tokens (numbers, key words, etc.). Line breaks are almost always insignificant, with a couple of exceptions as noted. Comments begin with # and continue to the end of the line; theyโ€™re allowed anywhere a newline is. ๐Ÿงš

Binary formats are also defined for several objects; *Note Binary format::, and the individual object descriptions. ๐Ÿ’ป

Typical OOGL objects begin with a key word designating object type, possibly with modifiers indicating presence of color information etc. In some formats the key word is optional, for compatibility with file formats defined elsewhere. Object type is then determined by guessing from the file suffix (if any) or from the data itself. ๐Ÿ”

Key words are case sensitive. Some have optional prefix letters indicating presence of color or other data; in this case the order of prefixes is significant, e.g. CNMESH is meaningful but NCMESH is invalid. ๐Ÿšซ

๐Ÿ“ File Names ๐Ÿ“

When OOGL objects are read from disk files, the OOGL library uses the file suffix to guess at the file type. ๐Ÿ•ต๏ธ

If the suffix is unrecognized, or if no suffix is available (e.g. for an object being read from a pipe, or embedded in another OOGL object), all known types of objects are tried in turn until one accepts the data as valid. ๐Ÿ”„

๐ŸŒŸ Vertices ๐ŸŒŸ

Several objects share a common style of representing vertices with optional per-vertex surface-normal and color. All vertices within an object have the same format, specified by the header key word. ๐Ÿ“

All data for a vertex is grouped together (as opposed to e.g. giving coordinates for all vertices, then colors for all vertices, and so on). ๐Ÿงฉ

The syntax is:

  • X Y Z โ€” (3-D floating-point vertex coordinates) or
  • X Y Z W โ€” (4-D floating-point vertex coordinates)

optionally followed by

  • NX NY NZ โ€” (normalized 3-D surface-normal if present)

optionally followed by

  • R G B A โ€” (4-component floating-point color if present, each component in range 0..1. The A (alpha) component represents opacity: 0 transparent, 1 opaque.)

optionally followed by

  • S T or S T U โ€” (two or three texture-coordinate values).

Values are separated by white space, and line breaks are immaterial. โœจ

Letters in the objectโ€™s header key word must appear in a specific order; thatโ€™s the reverse of the order in which the data is given for each vertex. So a CN4OFF objectโ€™s vertices contain first the 4-component space position, then the 3-component normal, finally the 4-component color. You canโ€™t change the data order by changing the header key word; an NCOFF is just not recognized. ๐Ÿ˜ค

๐Ÿงญ Surface normal directions ๐Ÿงญ

Geomview uses normal vectors to determine how an object is shaded. The direction of the normal is significant in this calculation. ๐ŸŽจ

When normals are supplied with an object, the direction of the normal is determined by the data given. ๐Ÿ“Š

When normals are not supplied with the object, Geomview computes normal vectors automatically; in this case normals point toward the side from which the vertices appear in counterclockwise order. ๐Ÿ”„

On parametric surfaces (Bezier patches), the normal at point P(u,v) is in the direction dP/du cross dP/dv. ๐Ÿ“ˆ

๐Ÿ”„ Transformation matrices ๐Ÿ”„

Some objects incorporate 4x4 real matrices for homogeneous object transformations. These matrices act by multiplication on the right of vectors. Thus, if p is a 4-element row vector representing homogeneous coordinates of a point in the OOGL object, and A is the 4x4 matrix, then the transformed point is pโ€™ = p A. This matrix convention is common in computer graphics; itโ€™s the transpose of that often used in mathematics, where points are column vectors multiplied on the right of matrices. ๐Ÿงฎ

Thus for Euclidean transformations, the translation components appear in the fourth row (last four elements) of A. Aโ€™s last column (4th, 8th, 12th and 16th elements) are typically 0, 0, 0, and 1 respectively. ๐Ÿ“

๐Ÿ’ป Binary format ๐Ÿ’ป

Many OOGL objects accept binary as well as ASCII file formats. These files begin with the usual ASCII token (e.g. CQUAD) followed by the word BINARY. Binary data begins at the byte following the first newline after BINARY. White space and a single comment may intervene, e.g.

OFF BINARY     # binary-format "OFF" data follows

Binary data comprise 32-bit integers and 32-bit IEEE-format floats, both in big-endian format (i.e., with most significant byte first). This is the native format for โ€™intโ€™s and โ€™floatโ€™s on Sun-3โ€™s, Sun-4โ€™s, and Irises, among others. ๐Ÿ’พ

Binary data formats resemble the corresponding ASCII formats, with ints and floats in just the places youโ€™d expect. There are some exceptions though, specifically in the QUAD, OFF and COMMENT file formats. Details are given in the individual file format descriptions. *Note QUAD::, *Note OFF::, and *Note COMMENT::. ๐Ÿ“

Binary OOGL objects may be freely mixed in ASCII object streams: ๐ŸŒˆ

LIST
     { = MESH BINARY
       ... binary data for mesh here ...
     }
     { = QUAD
         1 0 0  0 0 1   0 1 0  0 1 0
     }

Note that ASCII data resumes immediately following the last byte of binary data. โšก

Naturally, itโ€™s impossible to embed comments inside a binary-format OOGL object, though comments may appear in the header before the beginning of binary data. ๐Ÿ™…

๐Ÿ”— Embedded objects and external-object references ๐Ÿ”—

Some object types (LIST, INST) allow references to other OOGL objects, which may appear literally in the data stream, be loaded from named disk files, or be communicated from elsewhere via named objects. Gcl commands also accept geometry in these forms. ๐Ÿ”—

The general syntax is:

<oogl-object>   ::=
     [ "{" ]
     [ "define" symbolname ]
     [ "appearance" appearance ]
     [ ["="] object-keyword ...
       | "<" filename
       | ":" symbolname ]
     [ "}" ]

where "quoted" items are literal strings (which appear without the quotes), [bracketed] items are optional, and | denotes alternatives. Curly braces, when present, must match; the outermost set of curly braces is generally required when the object is in a larger context, e.g. when it is part of a larger object or embedded in a Geomview command stream. ๐Ÿงฉ

For example, each of the following three lines:

{ define fred         QUAD 1 0 0  0 0 1  0  1  0 1 0 0 }

{ appearance { +edge } LIST { < "file1" } { : fred } }

VECT 1 2 0   2 0   0 0 0   1 1 2

is a valid OOGL object. The last example is only valid when it is delimited unambiguously by residing in its own disk file. ๐Ÿ“

The "<" construct causes a disk file to be read. Note that this isnโ€™t a general textual "include" mechanism; a complete OOGL object must appear in the referenced file. ๐Ÿ“„

Files read using "<" are sought first in the directory of the file which referred to them, if any; failing that, the normal search path (set by Geomviewโ€™s load-path command) is used. The default search looks first in the current directory, then in the Geomview data directories. ๐Ÿ”

The ":" construct allows references to symbols, created with define. A symbolโ€™s initial value is a null object. When a symbol is (re)defined, all references to it are automatically changed; this is a crucial part of the support for interprocess communication. Some future version of the documentation should explain this better... ๐Ÿค”

Again, white space and line breaks are insignificant, and "#" comments may appear anywhere. ๐Ÿ’ฌ

๐ŸŽจ Appearances ๐ŸŽจ

Geometric objects can have associated "appearance" information, specifying shading, lighting, color, wireframe vs. shaded-surface display, and so on. Appearances are inherited through object hierarchies, e.g. attaching an appearance to a LIST means that the appearance is applied to all the LISTโ€™s members. ๐Ÿ‘—

Some appearance-related properties are relegated to "material" and "lighting" substructures. Take care to note which properties belong to which structure. ๐Ÿง

Hereโ€™s an example appearance structure including values for all attributes. Order of attributes is unimportant. As usual, white space is irrelevant. Boolean attributes may be preceded by "+" or "-" to turn them on or off; "+" is assumed if only the attribute name appears. Other attributes expect values. โœจ

A "" prefix on any attribute, e.g. "+edge" or "*linewidth 2" or "material { *diffuse 1 1 .25 }", selects "override"

โ€ฆstatus for that attribute.

Like, here's the whole vibe, bestie โ€” one big appearance block with every field annotated, so you can see exactly what's going on:

            appearance {               +face               # (Do) draw faces of polygons.  On by default.
โ€edge               # (Donโ€™t) draw edges of polygons
+vect                # (Do) draw VECTs.  On by default.
โ€transparent        # (Disable) transparency.  enabling transparency does NOT result in a correct Geomview picture, but alpha values are used in RenderMan snapshots.
โ€normal              # (Do) draw surfaceโ€normal vectors
normscale 1     # ... with length 1.0 in object coordinates

              +evert               # do evert polygon normals where needed so as to always face the camera

              โ€texturing           # (Disable) texture mapping
               โ€backcull                 # (Donโ€™t) discard clockwiseโ€oriented faces
              โ€concave            # (Donโ€™t) expect and handle concave polygons
               โ€shadelines        # (Donโ€™t) shade lines as if they were lighted cylinders
# These four are only effective where the graphics system supports them, namely on GL and Open GL.

              โ€keepcolor         # Normally, when Nโ€D positional coloring is enabled as with geomviewโ€™s (NDโ€color ...) command, all objectsโ€™ colors are affected.  But, objects with the "+keepcolor" attribute are immune to Nโ€D coloring.

               shading  smooth       # or "shading constant" or "shading flat" or or "shading csmooth". smooth = Gouraud shading, flat = faceted, csmooth = smoothly interpolated but unlighted.

              linewidth 1         # lines, points, and edges are 1 pixel wide.

              patchdice 10 10     # subdivide Bezier patches this finely in u and v

               material {         # Hereโ€™s a material definition; it could also be read from a file as in "material < file.mat"

                  ka  1.0         # ambient reflection coefficient.
                     ambient .3 .5 .3 # ambient color (red, green, blue components) The ambient contribution to the shading is the product of ka, the ambient color, and the color of the ambient light.

                  kd  0.8          # diffuseโ€reflection coefficient.
                      diffuse  .9  1  .4  # diffuse color. (In "shading constant" mode, the surface is colored with the diffuse color.)

                  ks 1.0          # specular reflection coefficient.
                     specular 1 1 1  # specular (highlight) color.
                    shininess  25    # specular exponent; larger values give sharper highlights.

                  backdiffuse .7 .5 0 # backโ€face color for twoโ€sided surfaces If defined, this field determines the diffuse color for the back side of a surface. Itโ€™s implemented by the software shader, and by hardware shading on GL systems which support twoโ€sided lighting, and under Open GL.

                  alpha   1.0     # opacity; 0 = transparent (invisible), 1 = opaque. Ignored when transparency is disabled.

                  edgecolor   1 1 0  # line & edge color

                   normalcolor  0 0 0  # color for surfaceโ€normal vectors
               }
              lighting {         # Lighting model

                  ambient  .3 .3 .3  # ambient light

                   replacelights    # "Use only the following lights to illuminate the objects under this appearance." Without "replacelights", any lights listed are added to those already in the scene.

                                  # Now a collection of sample lights:
                    light {                       color  1 .7 .6      # light color
                       position  1 0 .5 0  # light position [distant light] given in homogeneous coordinates. With fourth component = 0, this means a light coming from direction (1,0,.5).
                  }

                  light {                        # Another light.
                       color  1  1  1
                       position  0 0 .5 1  # light at finite position ...
location  camera           # specified in camera coordinates. (Since the camera looks toward โ€Z, this example places the light .5 unit behind the eye.)
                        # Possible "location" keywords:
                       # global light position is in world (well, universe) coordinates
# This is the default if no location specified.
                      # camera position is in the cameraโ€™s coordinate system
                       # local position is in the coordinate system where the appearance was defined
}
               }                   # end lighting model
texture  {                     clamp st               # or "s" or "t" or "none"
                     file lump.tiff          # file supplying textureโ€map image
                         alphafile mask.pgm.Z     # file supplying transparencyโ€mask image
                     apply  blend                 # or "modulate" or "decal"
                     transform  1 0 0 0      # surface (s,t,0,1) * tfm โ€> texture coords
0   1   0   0
                                    0    0    1    0
                              .5 0 0 1

                     background 1 0 0 1     # relevant for "apply blend"
               }
              }                      # end appearance

๐Ÿ’… so like, who wins when everybody's fighting over the same attribute ๐Ÿ’…

Okay so this is the part where it gets โœจdramaticโœจ, because appearances can stack. There are rules for inheritance of appearance attributes when several of them are imposed at different levels in the hierarchy.

Example time: Geomview itself installs a backstop appearance which provides default values for most parameters; its control panels install other appearances which supply new values for a few attributes; and user-supplied geometry may also contain appearances. Three layers, all yelling at once. ๐Ÿ™ˆ

The general rule is that the child's appearance wins โ€” that's the one closest to the geometric primitives, bestie, it's giving main character energy and it takes the crown. ๐Ÿ‘‘

And further, appearance controls with "override" status โ€” like *+face or material { *diffuse 1 1 0 } โ€” win over those without it.

Geomview's appearance controls use the "override" feature so as to be effective even if user-supplied objects contain their own appearance settings. However, if a user-supplied object contains an appearance field with override status set, that property will be immune to Geomview's controls. Not me getting out-overridden by my own geometry ๐Ÿ’€


๐Ÿฆ‹ Texture Mapping ๐Ÿฆ‹

Some platforms support texture-mapped objects. (On those which don't, attempts to use texture mapping are silently ignored โ€” literally no error, no nothing, it just doesn't happen. ๐Ÿซ ) A texture is specified as part of an appearance structure, as in *Note Appearances::. Briefly: you provide a texture image, which is considered to lie in a square in (s,t) parameter space in the range 0 <= s <= 1, 0 <= t <= 1. Then you provide a geometric primitive, with each vertex tagged with (s,t) texture coordinates. If texturing is enabled, the appropriate portion of the texture image is pasted onto each face of the textured object. Iconic behaviour honestly. ๐ŸŽ€

There is (currently) no provision for inheritance of part of a texture structure; if the texture keyword is mentioned in an appearance, it supplants any other texture specification. One mention and everything else is gone, no merging, periodt.

The appearance attribute texturing controls whether textures are used; and good news โ€” there's no performance penalty for having texture { ... } fields defined when texturing is off. So leave them lying around, it's free. ๐Ÿ’–

The available fields are:

  • clamp none -or- s -or- t -or- st โ€” Determines the meaning of texture coordinates outside the range 0..1. With clamp none, the default, coordinates are interpreted modulo 1, so (s,t) = (1.25,0), (.25,0), and (-.75,0) all refer to the same point in texture space. With s or t or st, either or both of s- or t-coordinates less than 0 or greater than 1 are clamped to 1 or 0, respectively.
  • file filename / alphafile filename โ€” Specifies image file(s) containing the texture. The file file's image specifies color or lightness information; the alphafile, if present, specifies a transparency ("alpha") mask; where the mask is zero, pixels are simply not drawn. Several image file formats are available; the file type must be indicated by the last few characters of the file name:
    • .ppm or .ppm.Z or .ppm.gz โ€” 24-bit 3-color image in PPM format
    • .pgm or .pgm.Z or .pgm.gz โ€” 8-bit grayscale image in PGM format
    • .sgi or .sgi.Z or .sgi.gz โ€” 8-bit, 24-bit, or 32-bit SGI image
    • .tiff โ€” 8-bit or 24-bit TIFF image
    • .gif โ€” GIF image

(Though 4-channel TIFF images are possible, and could represent both color and transparency information in one image, that's not supported in geomview at present.)

For this feature to work, some programs must be available in geomview's search path:

  • zcat for .Z files
  • gzip for .gz files
  • tifftopnm for .tiff files
  • giftoppm for .gif files

If an alphafile image is supplied, it must be the same size as the file image.

  • apply modulate -or- blend -or- decal

apply โ€” okay bestie, this one is literally the whole vibe check for your texture: it says how the texture image gets applied to the surface. And real quick, "surface color" here means the color that surface would have in the absence of texture mapping. no texture, no drama, just the surface being itself. ๐Ÿ’…

  • modulate โ€” this is the default, and it's giving "multiply and move on." The texture color (or lightness, if you're texturing with a gray-scale image ๐Ÿฉถ) gets multiplied by the surface color.
  • blend โ€” here the texture blends between the background color and the surface color. โš ๏ธ the file parameter must specify a gray-scale image. Where the texture image is 0, the surface color is unaffected; where it's 1, the surface gets painted in the color given by background; and for the in-between values the color is interpolated. it's a little gradient moment fr fr ๐ŸŒˆ
  • decal โ€” here the file parameter must specify a 3-color image. If an alphafile parameter is present, its value interpolates between the surface color (where alpha=0) and the texture color (where alpha=1). ๐Ÿซถ and heads up: lighting does not affect the texture color in decal mode โ€” effectively the texture is constant-shaded. lowkey it just refuses to be lit.

background R G B A โ€” specifies a 4-component color, with R, G, B, and A floating-point numbers normally in the range 0..1, used when apply blend is selected. ๐ŸŽจ

transform transformation-matrix โ€” expects a list of 16 numbers, or one of the other ways of representing a transformation (: handlename or < filename). The 4x4 transformation matrix is applied to texture coordinates, in the sense of a 4-component row vector (s,t,0,1) multiplied on the left of the matrix, to produce new coordinates (s',t') which actually index the texture. โœจ matrix math but make it texture.


๐ŸŒˆ Object File Formats ๐ŸŒˆ

๐ŸŸช QUAD: collection of quadrilaterals ๐ŸŸช

The conventional suffix for a QUAD file is .quad.

The file syntax is

[C][N][4]QUAD  -or-  [C][N][4]POLY           # Key word
VERTEX  VERTEX  VERTEX  VERTEX   # 4*N vertices for some N
VERTEX  VERTEX  VERTEX  VERTEX
...

The leading key word is [C][N][4]QUAD or [C][N][4]POLY, where the optional C and N prefixes indicate that each vertex includes colors and normals respectively. That is, these files begin with one of the words

QUAD  CQUAD  NQUAD  CNQUAD  POLY
CPOLY  NPOLY  CNPOLY

(but not NCQUAD or NCPOLY ๐Ÿ™ˆ). QUAD and POLY are synonymous; both forms are allowed just for compatibility with ChapReyes.

Following the key word is an arbitrary number of groups of four vertices, each group describing a quadrilateral. See the Vertex syntax above. ๐Ÿ‘€ The object ends at end-of-file, or with a close-brace if incorporated into an object reference (see above).

A QUAD BINARY file format is accepted; *Note Binary format::. The first word of binary data must be a 32-bit integer giving the number of quads in the object; following that is a series of 32-bit floats, arranged just as in the ASCII format. ๐Ÿ’พ


๐ŸŸช MESH: rectangularly-connected mesh ๐ŸŸช

The conventional suffix for a MESH file is .mesh.

The file syntax is

[U][C][N][Z][4][u][v][n]MESH  # Key word
[NDIM]                 # Space dimension, present only if nMESH
NU    NV              # Mesh grid dimensions
                      # NU*NV vertices, in format specified
                      # by initial key word
VERTEX(u=0,v=0)  VERTEX(1,0)  ...  VERTEX(NU-1,0)
VERTEX(0,1)  ...  VERTEX(NU-1,1)
...
VERTEX(0,NV-1)  ...  VERTEX(NU-1,NV-1)

The key word is [U][C][N][Z][4][u][v][n]MESH. The optional prefix characters mean:

  • U โ€” each vertex includes a 3-component texture space parameter. The first two components are the usual S and T texture parameters for that vertex; the third should be specified as zero. ๐Ÿงต
  • C โ€” each vertex (see Vertices above) includes a 4-component color.
  • N โ€” each vertex includes a surface normal vector.
  • Z โ€” of the 3 vertex position values, only the Z component is present; X and Y are omitted, and assumed to equal the mesh (u,v) coordinate so X ranges from 0 .. (Nu-1), Y from 0 .. (Nv-1) where Nu and Nv are the mesh dimensions โ€” see below.
  • 4 โ€” vertices are 4D, each consists of 4 floating values. Z and 4 cannot both be present. pick a lane bestie ๐Ÿ˜ญ
  • u โ€” the mesh is wrapped in the u-direction, so the (0,v)'th vertex is connected to the (NU-1,v)'th for all v.
  • v โ€” the mesh is wrapped in the v-direction, so the (u,0)'th vertex is connected to the (u,NV-1)'th for all u. Thus a u-wrapped or v-wrapped mesh is topologically a cylinder, while a uv-wrapped mesh is a torus. ๐Ÿฉ iconic shape behavior honestly
  • n โ€” specifies a mesh whose vertices live in a higher dimensional space. The dimension follows the "MESH" keyword. Each vertex then has NDIM components.
Note that the order of prefix characters is significant; a colored, u-wrapped mesh is a CuMESH not a uCMESH. the order is the whole personality. โœจ

Following the mesh header are integers NU and NV, the dimensions of the mesh.

Then follow NU*NV vertices, each in the form given by the header. They appear in v-major order, i.e. if we name each vertex by (u,v) then the vertices appear in the order

(0,0)  (1,0)  (2,0)  (3,0)  ...  (NU-1,0)
(0,1)  (1,1)  (2,1)  (3,1)  ...  (NU-1,1)
...
(0,Nv-1)  ...  (NU-1,NV-1)

A MESH BINARY format is accepted; *Note Binary format::. The values of NU and NV are 32-bit integers; all other values are 32-bit floats. ๐Ÿ’พ


๐ŸŸช Bezier Surfaces ๐ŸŸช

The conventional file suffixes for Bezier surface files are .bbp or .bez. A file with either suffix may contain either type of patch.

Syntax:

[ST]BBP      -or-      [C]BEZ<NU><NV><ND>[_ST]
                      # NU, NV are u- and v-direction
                      # polynomial degrees in range 1..6
                      # ND = dimension: 3->3-D, 4->4-D (rational)
                      # (The '<' and '>' do not appear in the input.)
                      # NU,NV,ND are each a single decimal digit.
                      # BBP form implies NU=NV=ND=3 so BBP = BEZ333.

                      # Any number of patches follow the header
                      # (NU+1)*(NV+1) patch control points
                      # each 3 or 4 floats according to header
VERTEX(u=0,v=0)  VERTEX(1,0)  ...  VERTEX(NU,0)
VERTEX(0,1)  ...  VERTEX(NU,1)
...
VERTEX(0,NV)  ...  VERTEX(NU,NV)

                      # ST texture coordinates if mentioned in header
'S'(u=0,v=0)  'T'(0,0)  'S'(0,NV)  'T'(0,NV)
'S'(NU,0)  'T'(NU,0)  'S'(NU,NV)  'T'(NU,NV)

                      # 4-component float (0..1) R G B A colors
                      # for each patch corner if mentioned in header
'RGBA'(0,0)  'RGBA'(0,NV)
'RGBA'(NU,0)  'RGBA'(NU,NV)

These formats represent collections of Bezier surface patches, of degrees up to 6, and with 3-D or 4-D (rational) vertices. ๐ŸŒธ

The header keyword has the forms [ST]BBP or [C]BEZ<NU><NV><ND>[_ST] (the < and > are not part of the keyword).

The ST prefix on BBP, or _ST suffix on BEZuvn, indicates that each patch includes four pairs of floating-point texture-space coordinates, one for each corner of the patch. ๐Ÿงš

The C prefix on BEZuvn indicates a colored patch, including four sets of four-component floating-point colors (red, green, blue, and alpha) in the range 0..1, one color for each corner.

NU and NV, each a single digit in the range 1..6, are the patch's polynomial degree in the u and v direction respectively.

ND is the number of components in each patch vertex, and must be either 3 for 3-D or 4 for homogeneous coordinates, that is, rational patches.

BBP patches are bicubic patches with 3-D vertices, so BBP = BEZ333 and STBBP = BEZ333_ST. โœจ

Any number of patches follow the header. Each patch comprises a series of patch vertices, followed by optional (s,t) texture coordinates, followed by optional (r,g,b,a) colors.

Each patch has (NU+1)*(NV+1) vertices in v-major order, so that if we designate a vertex by its control point indices (u,v) the order is

(0,0)  (1,0)  (2,0)  ...  (NU,0)
(0,1)  (1,1)  (2,1)  ...  (NU,1)
...
(0,NV)  ...  (NU,NV)

with each vertex containing either 3 or 4 floating-point numbers as specified by the header.

If the header calls for ST coordinates, four pairs of floating-point numbers follow: the texture-space coordinates for the (0,0), (NU,0), (0,NV), and (NU,NV) corners of the patch, respectively. ๐Ÿซถ

If the header calls for colors, four four-component (red, green, blue, alpha) floating-point colors follow, one for each patch corner.

The series of patches ends at end-of-file, or with a close-brace if incorporated in an object reference.

Info file: geomview, --Text-- produced by texinfo-format-buffer from file: geomview.tex


๐ŸŸช OFF Files ๐ŸŸช

The conventional suffix for OFF files is .off.

Syntax:

[ST][C][N][4][n]OFF  # Header keyword
[NDIM]          # Space dimension of vertices, present only if nOFF
NVERTICES  NFACES  NEDGES   # NEdges not used or
X[0]  Y[0]  Z[0]        # Vertices, possibly with normals,
                        # colors, and/or texture coordinates,
                        # in that order, if the prefixes 'N', 'C', 'ST'
                        # are present.
                        # If 4OFF, each vertex has 4 components,
                        # including a final homogeneous component.
                        # If nOFF, each vertex has NDIM components.
                        # If 4nOFF, each vertex has NDIM+1 components.
...
X[NVERTICES-1]  Y[NVERTICES-1]  Z[NVERTICES-1]

okay so that's the vertex table, bestie ๐Ÿ’– the little prefix letters are doing so much work here: N for normals, C for colors, ST for texture coordinates, all in that order. And the key character tells you how fat each vertex is โ€” 4OFF means 4 components per vertex (with a final homogeneous component), nOFF means each vertex has NDIM components, and 4nOFF means each vertex has NDIM+1 components. it's giving "custom vertex width" โœจ

# Faces
NV  =  # vertices on this face
# V[0] ... V[NV-1]: vertex indices in range 0..NVERTICES-1
NV  V[0] V[1] ... V[NV-1]  COLORSPEC
# COLORSPEC continues past V[NV-1] to end-of-line;
# may be 0 to 4 numbers
#   nothing: default
#   integer: colormap index
#   3 or 4 integers: RGB[A] values 0..255
#   3 or 4 floats: RGB[A] values 0..1

then the faces show up, one per line, with the vertex count first and then the indices, then a lil optional COLORSPEC at the end ๐ŸŽ€


OFF files โ€” the name literally stands for "object file format", no cap โ€” represent collections of planar polygons with possibly shared vertices, which is a convenient way to describe polyhedra. the polygons may be concave, but there's no provision for polygons containing holes. that's just not a thing she does, sorry ๐Ÿซถ

An OFF file may begin with the keyword OFF. it's recommended but optional, because a ton of existing files just. don't have it. classic ๐Ÿ’€

Three ASCII integers follow: NVERTICES, NFACES, and NEDGES. these are the number of vertices, faces, and edges, respectively. Current software does not use nor check NEDGES โ€” it needn't be correct, but it must be present. girl is decorative but mandatory, and honestly? same ๐Ÿ’…

The vertex coordinates come next: dimension * NVERTICES floating-point values. They're implicitly numbered 0 through NVERTICES-1. dimension is either 3 (the default) or 4, specified by the key character 4 sitting directly before OFF in the keyword.

Following those are the face descriptions, typically written with one line per face. each one looks like:

N VERT1 VERT2 ... VERTN [COLOR]

here N is the number of vertices on this face, and VERT1 through VERTN are indices into the list of vertices, in the range 0..NVERTICES-1.

The optional COLOR may take several forms. Line breaks are significant here: the COLOR description begins after VERTN and ends with the end of the line (or the next # comment). A COLOR may be:

  • nothing โ€” the default color
  • one integer โ€” index into "the" colormap; see below
  • three or four integers โ€” RGB and possibly alpha values in the range 0..255
  • three or four floating-point numbers โ€” RGB and possibly alpha values in the range 0..1

For the one-integer case, the colormap is currently read from the file cmap.fmap in Geomview's data directory. Some better mechanism for supplying a colormap is likely someday. (somedayโ€ฆ ๐Ÿ˜ญ)

The meaning of "default color" varies. If no face of the object has a color, all inherit the environment's default material color. If some but not all faces have colors, the default is gray (R,G,B,A=.666).


A [ST][C][N][n]OFF BINARY format is accepted; Note Binary format::. It resembles the ASCII format in almost the way you'd expect, with 32-bit integers for all counters and vertex indices and 32-bit floats for vertex positions (and texture coordinates or vertex colors or normals if COFF/NOFF/CNOFF/STCNOFF/etc. format).

Exception: each face's vertex indices are followed by an integer indicating how many color components accompany it. Face color components must be floats, not integer values. So a colorless triangular face might be represented as

int int int int int
3   17   5   9   0

while the same face colored red might be

int int int int int float float float float
3   17   5   9   4   1.0   0.0   0.0   1.0

๐ŸŒˆ VECT Files ๐ŸŒˆ

The conventional suffix for VECT files is .vect.

Syntax:

[4]VECT   NPOLYLINES  NVERTICES  NCOLORS

 NV[0] ... NV[NPOLYLINES-1]      # number of vertices in each polyline

 NC[0] ... NC[NPOLYLINES-1]      # number of colors supplied in each polyline

VERT[0] ... VERT[NVERTICES-1]    # All the vertices (3*NVertices floats)

COLOR[0] ... COLOR[NCOLORS-1]    # All the colors (4*NColors floats, RGBA)

VECT objects represent lists of polylines โ€” strings of connected line segments, possibly closed. a degenerate polyline can be used to represent a point โœจ (iconic behavior honestly)

A VECT file begins with the key word VECT or 4VECT and three integers: NLINES, NVERTICES, and NCOLORS. Here NLINES is the number of polylines in the file, NVERTICES the total number of vertices, and NCOLORS the number of colors as explained below.

Next come NLINES integers

NV[0] NV[1] NV[2] ... NV[NLINES-1]

giving the number of vertices in each polyline. A negative number indicates a closed polyline; 1 denotes a single-pixel point. The sum (of absolute values) of the NV[I] must equal NVERTICES. no pressure but the math HAS to math ๐Ÿ’€

Next come NLINES more integers Nc[i]: the number of colors in each polyline. Normally one of three values:

  • 0 โ€” No color is specified for this polyline. It's drawn in the same color as the previous polyline.
  • 1 โ€” A single color is specified. The entire polyline is drawn in that color.
  • abs(NV[I]) โ€” Each vertex has a color. Either each segment is drawn in the corresponding color, or the colors are smoothly interpolated along the line segments, depending on the implementation.

The sum of the NC[I] must equal NCOLORS.

Next come NVERTICES groups of 3 or 4 floating-point numbers: the coordinates of all the vertices. If the keyword is 4VECT then there are 4 values per vertex. The first abs(NV[0]) of them form the first polyline, the next abs(NV[1]) form the second and so on.

Finally NCOLORS groups of 4 floating-point numbers give red, green, blue and alpha (opacity) values. The first NC[0] of them apply to the first polyline, and so on.

A VECT BINARY format is accepted; Note Binary format::. The binary format exactly follows the ASCII format, with 32-bit ints where integers appear, and 32-bit floats where real values appear. she said "same energy, different bytes" ๐Ÿฆ‹


๐Ÿ’€ SKEL Files ๐Ÿ’€

SKEL files represent collections of points and polylines, with shared vertices. The conventional suffix for SKEL files is .skel.

Syntax:

[4][n]SKEL   [NDIM]                 # Vertex dimension, present only if nSKEL
             NVERTICES  NPOLYLINES

 X[0]  Y[0]  Z[0]                   # Vertices
                                    # (if nSKEL, each vertex has NDim components)
 ...
 X[NVERTICES-1]  Y[NVERTICES-1]  Z[NVERTICES-1]

                                    # Polylines
                                    # NV = # vertices on this polyline (1 = point)
                                    # V[0] ... V[NV-1]: vertex indices
                                    # in range 0..NVERTICES-1
 NV  V[0] V[1] ... V[NV-1] [COLORSPEC]
 ...
                                    # COLORSPEC continues past V[NV-1]
                                    # to end-of-line; may be nothing, or 3 or 4 numbers.
                                    # nothing: default color
                                    # 3 or 4 floats: RGB[A] values 0..1

The syntax resembles that of OFF files, with a table of vertices followed by a sequence of polyline descriptions, each referring to vertices by index in the table. Each polyline has an optional color. family resemblance, we love to see it ๐Ÿ’œ

For nSKEL objects, each vertex has NDIM components. For 4nSKEL objects, each vertex has NDIM+1 components; the final component is the homogeneous divisor.

No BINARY format is implemented as yet for SKEL objects. ๐Ÿšซ (not me waiting for itโ€ฆ)

๐ŸŽ€ SPHERE Files ๐ŸŽ€

The conventional suffix for SPHERE files is .sph.

SPHERE   RADIUS   XCENTER YCENTER ZCENTER

Sphere objects are drawn using rational Bezier patches, which are diced into meshes; their smoothness, and the time taken to draw them, depends on the setting of the dicing level, 10x10 by default. From Geomview, the Appearance panel, the <N>ad keyboard command, or a dice nu nv Appearance attribute sets this. โญ


๐Ÿ‘‘ INST Files ๐Ÿ‘‘

The conventional suffix for an INST file is .inst.

There is no INST BINARY format. ๐Ÿ’…

An INST applies a 4x4 transformation to another OOGL object. It begins with INST followed by these sections, which may appear in any order:

  • geom OOGL-OBJECT โ€” specifies the OOGL object to be instantiated. Note References::, for the syntax of an OOGL-OBJECT. The keyword unit is a synonym for geom.
  • transform ["{"] 4x4 transform ["}"] โ€” specifies a single transformation matrix. Either the matrix may appear literally as 16 numbers, or there may be a reference to a "transform" object, i.e.
"<" file-containing-4x4-matrix

or

":" symbol-representing-transform-object>

Another way to specify the transformation is

transforms OOGL-OBJECT

The OOGL-OBJECT must be a TLIST object (list of transformations) object, or a LIST whose members are ultimately TLIST objects. In effect, the transforms keyword takes a collection of 4x4 matrices and replicates the geom ob

...ject, making one copy for each 4x4 matrix. โœจ

If neither the transform nor the transforms keyword shows up, then like... no transformation gets applied at all (well, technically the identity gets applied, but same vibe). You could use this for, e.g., wrapping an appearance around an externally-supplied object โ€” though honestly a single-membered LIST would do that more efficiently. ๐Ÿ’…

*Note Transformation matrices::, for the matrix format.


Two more INST fields, bestie ๐ŸŽ€

They're called location and origin and they're lowkey iconic.

location [global or camera or ndc or screen or local]

Normally an INST specifies a position relative to its parent object. But the location field lets you put an object literally anywhere else. Choices:

  • location global โ€” attaches the object to the global (a.k.a. universe) coordinate system, which is the exact same one where geomview's World objects, alien geometry, and cameras live.
  • location camera โ€” places the object relative to the camera. (So if there are multiple views, it may show up in a different spatial position in each view. No cap.) The center of the camera's view is along its negative Z axis; positive X is rightward, positive Y upward. Normally the units of camera space are the same as global coordinates. When a camera is reset, the global origin is at (0,0,-3.0).
  • location ndc โ€” places the object relative to the normalized unit cube into which the camera's projection (perspective or orthographic) maps the visible world. X, Y, and Z are each in the range from -1 to +1, with Z = -1 the near and Z = +1 the far clipping plane, and X and Y increasing rightward and upward respectively.

So like, something like

INST transform 1 0 0 0  0 1 0 0  0 0 1 0  -.9 -.9 -.999 1
     location ndc
     geom < label.vect

pastes label.vect onto the lower left corner of each window, and in front of nearly everything else, assuming label.vect's contents lie in the positive quadrant of the X-Y plane. ๐Ÿซถ

It's tempting to use -1 rather than -.999 as the Z component of the position, but that may put the object just nearer than the near clipping plane and make it (partially) invisible, due to floating-point error. So don't. ๐Ÿ˜ญ
  • location screen โ€” places the object in screen coordinates. The range of Z is still -1 through +1 as for ndc coordinates; X and Y are measured in pixels, and range from (0,0) at the lower left corner of the window, increasing rightward and upward.

location local is the default โ€” the object is positioned relative to its parent. ๐Ÿ’œ

origin [global or camera or ndc or screen or local] x y z

The origin field translates the contents of the INST to place the origin at the specified point of the given coordinate system. Unlike location, it doesn't change the orientation, only the choice of origin. Both location and origin can be used together. โœจ

So for example

{ INST
     location screen
     origin ndc 0 0 -.99
     geom { < xyz.vect }
     transform { 100 0 0 0  0 100 0 0  0 0 -.009 0  0 0 0 1 }
}

places xyz.vect's origin in the center of the window, just beyond the near clipping plane. The unit-length X and Y edges are scaled to be just 100 screen units โ€” pixels โ€” long, regardless of the size of the window. ๐Ÿ”ฅ


INST Examples, bestie .............

Here are some examples of INST files ๐Ÿฆ‹

INST
     unit < xyz.vect
     transform {
          1 0 0 0
          0 1 0 0
          0 0 1 0
          1 3 0 1
     }
{ appearance { +edge  material { edgecolor 1 1 0 } }
     INST geom < mysurface.quad }
{INST transform {: T} geom {<dodec.off}}
{  INST
     transforms { LIST
          { < some-matrices.prj }
          { < others.prj }
          { TLIST <still more of them> }
     }
     geom { # stuff replicated by all the above matrices
... }
}

This next one resembles the origin example in the section above, but it makes the X and Y edges be 1/4 the size of the window (1/4, not 1/2, since the range of ndc X and Y coordinates is -1 to +1). ๐Ÿ’…

{ INST
     location ndc
     geom { < xyz.vect }
     transform { .5 0 0 0  0 .5 0 0  0 0 -.009 0  0 0 -.99 1 }
}

LIST Files ๐Ÿ’–

The conventional suffix for a LIST file is .list.

A list of OOGL objects. So simple. So iconic.

Syntax:

LIST OOGL-OBJECT
     OOGL-OBJECT
     ...
Note that there's no explicit separation between the oogl-objects, so they should be enclosed in curly braces ({ }) for sanity. Likewise there's no explicit marker for the end of the list; unless appearing alone in a disk file, the whole construct should also be wrapped in braces, as in:
{ LIST { QUAD ... } { < xyz.quad } }

A LIST with no elements, i.e. { LIST }, is valid, and is the easiest way to create an empty object. For example, to remove a symbol's definition you might write

{ define somesymbol  { LIST } }

TLIST Files ๐ŸŒธ

The conventional suffix for a TLIST file is .grp ("group") or or .prj ("projective" matrices).

A collection of 4x4 matrices, used in the transforms section of and INST object.

Syntax:

TLIST              # key word
     <4x4 matrix (16 floats)>
...                # Any number of 4x4 matrices

TLISTs are used only within the transforms clause of an INST object. They cause the INST's geom object to be instantiated once under each of the transforms in the TLIST. The effect is like that of a LIST of INSTs each with a single transform, and all referring to the same object, but is more efficient. โœจ

Be aware that a TLIST is a kind of geometry object, distinct from a transform object. Some contexts expect one type of object, some the other. ๐Ÿ˜ญ

For example in

INST transform { : MYT } geom { ... }

MYT must be a transform object, which might have been created with the gcl

(read transform { define myT 1 0 0 1 ... })

while in

INST transforms { : MYTS } geom { ... }

or

INST transforms { LIST {: MYTS} {< more.prj} } geom { ... }

MYTS must be a geometry object, defined e.g. with

(read geometry { define MYTS { TLIST 1 0 0 1 ... } })

A TLIST BINARY format is accepted. Binary data begins with a 32-bit integer giving the number of transformations, followed by that number of 4x4 matrices in 32-bit floating-point format. The order of matrix elements is the same as in the ASCII format. ๐Ÿ’ฏ


GROUP Files ๐ŸŒˆ

This format is obsolete, but is still accepted. It combined the functions of INST and TLIST, taking a series of transformations and a single Geom (unit) object, and replicating the object under each transformation.

GROUP ... < matrices > ... unit { OOGL-OBJECT }

is still accepted and effectively translated into

INST transforms { TLIST ... <matrices> ... }
     unit { OOGL-OBJECT }

DISCGRP Files ๐Ÿงš

This format is for discrete groups, such as appear in the theory of manifolds or in symmetry patterns. This format has its own man page. See discgrp(5).


COMMENT Objects โญ

The COMMENT object is a mechanism for encoding arbitrary data within an OOGL object. It can be used to keep track of data or pass data back and forth between external modules. Obsessed, honestly.

Syntax:

COMMENT               # key word
 NAME TYPE   # individual name and type specifier
{ ... }      # arbitrary data

The data, which must be enclosed by curly braces, can include anything except unbalanced curly braces. The TYPE field can be used to identify data of interest to a particular program through naming conventions.

COMMENT objects are intended to be associated with other objects through inclusion in a LIST object. (*Note LIST::.) The "#" OOGL comment syntax does not suffice for data exchange since these comments are stripped when an OOGL object is read in to Geomview. The COMMENT object is preserved when loaded into Geomview and is written out intact. ๐Ÿ‘‘

Here is an example associating a WorldWide Web URL with a piece of geometry:

{ LIST
     { < Tetrahedron}
     {COMMENT GCHomepage HREF { http://www.geomview.org }}
}

A binary COMMENT format is accepted. Its format is not consistent with the other OOGL binary formats. *Note Binary format::. The name and type are followed by

N BYTE1 BYTE2 ... BYTEN

instead of data enclosed in curly braces. ๐Ÿ’€


Non-geometric objects

The syntax of these objects is given in the form used in *Note References::, where "quoted" items should appear literally but without quotes, square bracketed ([ ]) items are optional, and | separates alternative choices.

Transform Objects ๐Ÿ’ซ

Where a single 4x4 matrix is expected โ€” as in the INST transform field, the camera's camtoworld transform and the Geomview xform* commands โ€” use a transform object.

Note that a transform is distinct from a TLIST, which is a type of geometry. TLISTs can contain one or more 4x4 transformations; "transform" objects must have exactly one.

Why have both? In many places โ€” e.g. camera positioning โ€” it's only meaningful to have a single transform. Using a separate

object type enforces this. ๐Ÿ’…

okay so the syntax for a transform object is literally this whole mood:

<transform> ::=
    [ "{" ] (curly brace, generally needed to make the end of the object unambiguous.)
    [ "transform" ] (optional keyword; unnecessary if the type is determined by the context, which it usually is.)
    [ "define" <name> ] (defines a transform named <name>, setting its value from the stuff which follows)
    <sixteen floating-point numbers> (interpreted as a 4x4 homogeneous transform given row by row, intended to apply to a row vector multiplied on its LEFT, so that e.g. Euclidean translations appear in the bottom row)
    | "<" <filename> (meaning: read transform from that file)
    | ":" <name> (meaning: use variable <name>, defined elsewhere; if undefined the initial value is the identity transform)
    [ "}" ] (matching curly brace)

The whole thing should be enclosed in { braces }. Braces are not essential if exactly one of the above items is present, so e.g. a 4x4 array of floats standing alone may but neednโ€™t have braces. No cap. โœจ

Some examples, in contexts where they might be used:

# Example 1: A gcl command to define a transform
# called "fred"

(read transform { transform define fred
    1 0 0 0
    0 1 0 0
    0 0 1 0
    โ€3 0 1 1
} )

# Example 2: A camera object using transform
# "fred" for camera positioning
# Given the definition above, this puts the camera at
# (โ€3, 0, 1), looking toward โ€Z.

{ camera halfyfield 1
  aspect 1.33 camtoworld { : fred } }

๐ŸŽฅ cameras

A camera object specifies the following properties of a camera:

  • position and orientation โ€” specified by either a camera-to-world or world-to-camera transformation; this transformation does not include the projection, so itโ€™s typically just a combination of translation and rotation. Specified as a transform object, typically a 4x4 matrix.
  • "focus" distance โ€” intended to suggest a typical distance from the camera to the object of interest; used for default camera positioning (the camera is placed at (X,Y,Z) = (0,0,focus) when reset) and for adjusting field-of-view when switching between perspective and orthographic views.
  • window aspect ratio โ€” true aspect ratio in the sense <Xsize>/<Ysize>. This normally should agree with the aspect ratio of the cameraโ€™s window. Geomview normally adjusts the aspect ratio of its cameras to match their associated windows.
  • near and far clipping plane distances โ€” note that both must be strictly greater than zero. Very large <far>/<near> distance ratios cause Z-buffering to behave badly; part of an object may be visible even if somewhat more distant than another.
  • field of view โ€” specified in either of two forms. โ€˜fovโ€™ is the field of view -- in degrees if perspective, or linear distance if orthographic -- in the shorter direction. โ€˜halfyfieldโ€™ is half the projected Y-axis field, in world coordinates (not angle!), at unit distance from the camera. For a perspective camera, halfyfield is related to angular field:
halfyfield = tan( Y_axis_angular_field / 2 )

while for an orthographic one itโ€™s simply:

halfyfield = Y_axis_linear_field / 2

This odd-seeming definition is (a) easy to calculate with and (b) well-defined in both orthographic and perspective views.

The syntax for a camera is:

<camera> ::=
    [ "camera" ] (optional keyword)
    [ "{" ] (opening brace, generally required)
    [ "define" <name> ]
    "<" <filename> |
    ":" <name> |
    (or any number of the following, in any order...)
    "perspective" {"0" | "1"} (default 1) (otherwise orthographic)
    "stereo" {"0" | "1"} (default 0) (otherwise mono)
    "worldtocam" <transform> (see transform syntax above)
    "camtoworld" <transform> (no point in specifying both camtoworld and worldtocam; one is constrained to be the inverse of the other)
    "halfyfield" <half-linear-Y-field-at-unit-distance> (default tan 40/2 degrees)
    "fov" (angular field-of-view if perspective, linear field-of-view otherwise. Measured in whichever direction is smaller, given the aspect ratio. When aspect ratio changes -- e.g. when a window is reshaped -- "fov" is preserved.)
    "frameaspect" <aspect-ratio> (X/Y) (default 1.333)
    "near" <near-clipping-distance> (default 0.1)
    "far" <far-clipping-distance> (default 10.0)
    "focus" <focus-distance> (default 3.0)
    [ "}" ] (matching closebrace)

๐ŸชŸ window

A window object specifies size, position, and other window-system related information about a window in a device-independent way.

The syntax for a window object is:

window ::=
    [ "window" ] (optional keyword)
    [ "{" ] (curly brace, often required)
    (any of the following, in any order)
    "size" <xsize> <ysize> (size of the window)
    "position" <xmin> <xmax> <ymin> <ymax> (position & size)
    "noborder" (specifies the window should have no window border)
    "pixelaspect" <aspect> (specifies the true visual aspect ratio of a pixel in this window in the sense xsize/ysize, normally 1.0. For stereo hardware which stretches the display vertically by a factor of 2, "pixelaspect 0.5" might do. The value is used when computing the projection of a camera associated with this window.)
    [ "}" ] (matching closebrace)

Window objects are used in the Geomview โ€˜windowโ€™ and โ€˜ui-panelโ€™ commands to set default properties for future windows or to change those of an existing window.


That's the whole vibe, bestie. This page was served fresh from the Geometry Center, dated Thu Dec 12 02:36:08 CST 1996, and it's OOGL(5) energy all the way. ๐Ÿ’–โœจ

๐Ÿ“ฆ where this page comes from