YAODL(6D) YAODL(6D)
YAODL - the 3D data format used by the powerflip demo
YAODL stands for 'Yet Another Object Description Language', and is a
format for three-dimensional models that supports NURBS, polygons, and
quad-meshes, and object properties such as facet or vertex normals,
texture coordinates, and object, facet and vertex colors. It also
supports hierarchical models, coordinate transformations (rotations,
scales, translations), and instancing (using the same data more than
once). It is not an official data format of Silicon Graphics, it is just
a data format created for the powerflip demo program. This document is
intended for intrepid programmers who want to display their data using
the powerflip program, and for the terminally curious.
A YAODL file consists of several YAODL objects separated by commas. A
YAODL object has one of the following forms:
(object_type argument1, argument2, ...)
(object_type argument1, ... : property1, property2, ... )
integer integer integer ...
float float float ...
"Some Charater String"
name = {one of the forms above}
name
There is also a binary form that is described below.
The set of object types and their expected arguments is described more
fully below. It will be simplest to start with a few examples of YAODL
objects:
red = (colors 1.0 0.0 0.0),
This defines a color called 'red'. It might be used later like this:
(polygons (vertices -1. -1. 0. 1. -1. 0.
1. 1. 0. -1. 1. 0.),
: red),
This defines one red square. Red is a property of the polygon, so it
must be specified after the ':' in the polygons object. Properties
affect only the object they are associated with (if there were other
objects after the red square, the red color would not affect them).
Why was the type of red 'colors' instead of 'color'? In the YAODL file
format, almost all types are plural; a 'colors' object can contain more
than one color. When matching up objects with their properties, they
must have the same plurality. So, for the red polygon example, there was
one polygon (with 4 vertices) that matches up with one color. If,
instead, we wanted one polygon with a different color at each of its
vertices we could have said:
(polygons (vertices
-1. -1. 0. 1. -1. 0.
1. 1. 0. -1. 1. 0.,
: colors
1. 0. 0. 0. 1. 0.
0. 0. 1. 1. 1. 1.,
Page 1
YAODL(6D) YAODL(6D)
))
Note that both the 'vertices' and the 'colors' types take one argument (a
list of floating point values), and each 3 values define one vertex
position or one RGB color. Integers are not automatically converted to
floating point values, so make sure your colors and vertices have decimal
points in them.
Each set of curly-braces defines a scope. Names defined inside a scope
are local to that scope and over-ride names in higher scopes. Names must
be declared before they are referenced.
A few more notes about syntax before describing the types more fully.
There are two styles of comments allowed in a YAODL file; C-style
(beginning with '/*' and ending with '*/' anywhere in the file) and
Shell-style (beginning with '#' as the first character on the line and
extending to the end of the line. Comments are treated as whitespace,
along with blanks, tabs, and new-lines, and are ignored by the parser,
serving only to separate elements.
group
Group is used to construct an object hierarchy. Groups have an
arbitrary number of arguments, each of which can be any YAODL
object. If there are properties associated with the group, then
each property must have as many items as there are number of items
in the group. For example, if the YAODL object is (group object1,
object2 : colors) then there must be two colors in the colors array
(the first will be the color of object1, then second the color of
object2).
vertices
take a list of floats as an argument. Every 3 floats defines one
vertex. Vertices don't mean anything by themselves; they are used
as part of more complicated geometric type. Normals, colors and
texture coordinates are often used as properties of vertices.
polygons
take a series of vertices as arguments. Each vertices type defines
one polygon. Polygons are very inefficient; use of them is not
recommended. Wherever possible, use the more efficient
indexpolygons (see below). Normals and colors are often used as
properties of polygons. Example:
/* Define two polygons, one red and one blue */
(polygons
(vertices 1.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 1.0),
(vertices 1.0 0.0 0.0 0.0 1.0 0.0 3.2 0.0 1.0),
: colors 1.0 0.0 0.0 0.0 1.0 0.0,
),
Page 2
YAODL(6D) YAODL(6D)
indices
takes an arbitrary number of arguments, each of which is a list of
integers. Indices are used in the indexpolygons type to re-use
vertices in a list.
indexpolygons
takes two arguments; first a vertices object, and then an indices
object. The indices are used to form polygons out of the vertices
in the vertex list. The greatest integer in the indices list must
be less than the number of vertices in the vertex list or an error
will occur. Normals and colors may be associated with the polygons
(there must be as many normals or colors as there are arguments to
the indices object).
(indexpolygons
vertices 1.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 1.0 3.2 0.0 1.0,
(indices 0 1 2, 0 1 3), /* Two triangles */
),
regularMesh
Defines a regular 3D mesh. It expects two arguments. The first
argument is a list of 2 integers specifying how many rows and
columns the mesh has. The second is a vertices objects that must
have rows*columns vertices in it. The vertices are connected to
form a grid in three-space. The regularMesh primitive ignores any
attributes associated with it, but you may associate colors and
normals and texture coordinates with the vertices of the mesh, or
encapsulate the mesh in a group and associate a color (or a texture
or a contour) with the group.
colors
takes a list of floats. Every 3 floats defines an RGB color.
Colors should be associated with vertices, polygons, indexpolygons,
or groups. Example:
(indexpolygons
vertices 1.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 1.0 3.2 0.0 1.0,
(indices 0 1 2, 0 1 3),
: colors 1.0 0.0 0.0 0.0 1.0 0.0 /* Red and blue flat-shaded tris
*/
),
normals
take a list of floats. Every 3 floats defines a normal vector.
Normals should be associated with vertices or polygons.
translates
takes a list of floats. Every 3 floats defines an XYZ translation.
Translates are best associated with groups of objects. Example:
# Use the same object twice; once translated:
wheel = ( ... some indexpolygons or something ...),
wheel, (group wheel : (translates 1.0 0.0 0.0)),
Page 3
YAODL(6D) YAODL(6D)
scales
takes a list of floats. Every 3 floats defines how much to scale in
the X, Y, and Z directions. Scales are best associated with groups.
rotates
takes a list of floats. Every 4 floats defines an angle and an
axis; the rotation will be a right-handed rotation of angle degrees
about the given axis. Rotates are best associated with groups.
nurbs
defines a NURBS surface. It takes 4 arguments; a list of S knots, a
list of T knots, 3 integers describing the number of control point
in the S and T directions and the number of coordinates per control
point (3 if it is a non-rational NURB, 4 if it is a rational NURB),
and, finally, the control points themselves. Normals and texture
coordinates are automatically generated for the surface (YAODL does
not allow you to change the default mapping). The only object you
may associate with a nurb is one or more trimcurves objects. If you
want to associate a texture or color with a nurb, encapsulate the
nurb in a group and associate the texture or color with the group.
trimcurves
defines a trimming curve for a NURBS surface. It takes three
arguments; a list of knots (floats), the number of control points
and number of coordinates per control point (integers), and the
control points (floats). Trimcurves must be associated with a nurbs
surface. Example:
(group
nurbs
-1. -1. -1. -1. 1. 1. 1. 1., /* S knots */
1. -1. -1. -1. 1. 1. 1. 1., /* T knots */
4 3, /* Number of S control pts, number of T control pts,
* number of coordinates per control point
*/
-2.5 -3.7 1.0 -1.5 -3.7 3.0 /* Control points */
1.5 -3.7 -2.5 2.5 -3.7 -.75
-2.5 -2.0 3.0 -1.5 -2.0 4.0
1.5 -2.0 -3.0 2.5 -2.0 0.0
-2.5 2.0 1.0 -1.5 2.0 0.0
1.5 2.0 -1.0 2.5 2.0 2.0
-2.5 2.7 1.25 -1.5 2.7 .1
1.5 2.7 -.6 2.5 2.7 .2,
: (trimcurves
0. 0. 0. 1. 1. 2. 2. 3. 3. 4. 4. 4., /* knots */
9 3, /* Number of control points, floats per pt */
1.0 0.0 1.0 1.0 1.0 1.0 /* Control points
0.0 2.0 2.0 -1.0 1.0 1.0
-1.0 0.0 1.0 -1.0 -1.0 1.0
0.0 -2.0 2.0 1.0 -1.0 1.0
1.0 0.0 1.0),
),
scales 0.2 0.2 0.2, textures "henry.rgb"),
Page 4
YAODL(6D) YAODL(6D)
textures
takes a series of character strings, each of which is the name of an
image file (in libimage.a format; the same format used by snapshot,
etc) to be used as a texture map. Textures should be associated
with groups of objects.
texcoords
takes floats as it argument. Each 2 floats defines s and t
coordinates; texcoords should be associated with vertices.
contours
Contours is a way of automatically generating texture coordinates
from a geometry. There are three modes available, corresponding to
the three GL texgen(3G) function. It expects 3 arguments; the first
is a string, either "contour", "linear", "spheremap" or "off". The
second argument is also a character string; either "eye" or
"object", specifying which space the texture coordinates should be
specified in. The third argument is a list of 4 floating point
values, specifying the plane equation for "linear" and "contour"
mode (the values are ignored for "off" and "spheremap" modes, but
must still be present). See the GL texgen() manual page for more
information.
A binary object can appear anywhere in a YAODL file; ASCII and binary may
be freely intermixed (so, for example, you can 'cat' together an ASCII
and binary yaodl file and get a valid YAODL file). Binary objects have
two main advantages over their ASCII form; they are much, much faster to
read in and they generally take up about half the space. The main
disadvantage is that the binary format is unportable. Since it isn't
expected that YAODL will migrate to any other computer architectures,
this shouldn't be a problem.
A binary object starts with an '@' character. Following the '@'
character is a NULL-terminated string which identifies the type of the
object (one of the types mentioned above), and a long (8-byte) integer
which specifies how many bytes of raw binary data follows. The format of
the raw data depends on the type; the following types implement their own
binary formats:
float
This type is just the list of floating point values type. The
spaces before and after the class name identify it as a basic,
built-in type. The format of the data is just raw floating point
values; number_of_bytes/sizeof(float) values will be read (where
number_of_bytes is the long integer that follows the type name).
int This is the built-in integer class. The data is just raw integers;
number_of_bytes/sizeof(int) integer values follow.
Page 5
YAODL(6D) YAODL(6D)
indices
The binary format for the indices type is layed out as follows:
'@' "indices" number_of_bytes number_of_lists
lengths[number_of_lists] data
The number_of_lists specifies how many arguments (groups of
integers) this object has. It is an integer. Next, the length of
each group of integers is given (these lengths are also integers).
Finally, the data in all of the lists is given; the first lengths[0]
items in the data array are the first argument, the next lengths[1]
items are the second, etc. These data values are also integers.
There are probably a lot of bugs lurking in YAODL. It is probably
possible to work around most of them.
There is also a lot of missing functionality in YAODL. It is expected
that future software products from Silicon Graphics will make YAODL
obsolete and fill in the missing functionality.
PPPPaaaaggggeeee 6666 [ Back ]
|