ThreeDIO.mesa
Copyright © 1985 by Xerox Corporation. All rights reserved.
Bloomenthal, July 26, 1986 11:57:27 am PDT
Crow, October 14, 1986 11:52:45 am PDT
DIRECTORY IO, Rope, ThreeDBasics;
ThreeDIO: CEDAR DEFINITIONS
~ BEGIN
Type Declarations
Error:     ERROR [reason: ROPE];
ROPE:     TYPE ~ Rope.ROPE;
STREAM:    TYPE ~ IO.STREAM;
Triple:    TYPE ~ ThreeDBasics.Triple;
TripleSequence:  TYPE ~ ThreeDBasics.TripleSequence;
IntegerSequence:  TYPE ~ ThreeDBasics.IntegerSequence;
RealSequence:  TYPE ~ ThreeDBasics.RealSequence;
NatSequence:    TYPE ~ ThreeDBasics.NatSequence;
NatTable:    TYPE ~ ThreeDBasics.NatTable;
VertexInfo:   TYPE ~ ThreeDBasics.VertexInfo;
VertexInfoSequence: TYPE ~ ThreeDBasics.VertexInfoSequence;
Vertex:    TYPE ~ ThreeDBasics.Vertex;
ShadingValue:  TYPE ~ ThreeDBasics.ShadingValue;
FieldType:   TYPE ~ {integer, real, triple, nats, none};
FieldDescription: TYPE ~ RECORD [id: ROPE, type: FieldType];
Field:     TYPE ~ RECORD [
      id: ROPE,        -- name of the field
      type: FieldType,      -- type of the field
      sequence: REF ANY     -- ref to field sequence
      ];
FieldSequence:  TYPE ~ RECORD [
      length: NAT,
      element: SEQUENCE maxLength: INTEGER OF REF Field
      ];
Line:   TYPE ~ REF LineRec;
LineRec:  TYPE ~ RECORD [
rope:     ROPENIL,       -- text of this line
index:     INTEGER ← 0,      -- current index into the rope
length:     INTEGER ← 0,      -- length of the rope
stream:    STREAMNIL      -- the associated io stream
];
File Format
Data in a ThreeDIO file is preceded by a separate keyline that specifyies the data format. This
keyline is a keyword followed by a `~' and an arbitrary number of field descriptions. The
field descriptions may optionally be separated by commas. The field description consists of a
colon-terminated identifier and a case-insensitive fieldType. Whitespace may appear before
any of the punctuations ('~', ':', or ',').
A sample keyline is:
PointSet~ id: Integer, xyzCoords: Triple, rgbColor: Triple
The data following a keyline is terminated by another keyline or by end of file. Any line
that is not a keyline, is not a blank line, and does not begin with "--" is assumed to be valid
data whose format is defined by the preceding keyline.
Comments begin with "--" and may be a separate line within the data or may terminate a line
of data or keyline.
NOTE!!!! FS.StreamOpen should be called assuming a Tioga formatted file is to be read. This is
the default, so don't worry unless you have done something explicit with the streamOptions
field. In particular, StreamOption.tiogaRead must be TRUE. The symptom of wrongness here is
reading apparent garbage past the end of the file.
Errors
Procedures that take a keyword as an argument may raise ERROR Error["keyword not found"].
Procedures that return data may raise ERROR Error["bad conversion"]. Procedures that fail to
find expected data may raise ERROR ["bad format"].
Read Procedures
GetLine: PROC [stream: STREAM] RETURNS [line: Line];
Return the next line from the stream.
GetWord: PROC [line: Line] RETURNS [word: ROPE];
Return the next whitespace-delimited word in line, advancing the line index by one word.
GetInteger: PROC [line: Line] RETURNS [INTEGER];
Convert the next word in line to an integer and advance the line index accordingly.
GetReal: PROC [line: Line] RETURNS [REAL];
Convert the next word in line to a real and advance the line index accordingly.
GetTriple: PROC [line: Line] RETURNS [Triple];
Convert the next three words in line to a triple and advance the line index accordingly.
GetNats: PROC [line: Line] RETURNS [nats: REF NatSequence];
Convert the remainder of the line into a sequence of nats.
NextKeyword: PROC [stream: STREAM, circularSearch: BOOLFALSE] RETURNS [key: ROPE];
Return the next keyword. The file index points to the beginning of the key line.
FindKeyword: PROC [stream: STREAM, keyword: ROPE, circularSearch: BOOLFALSE]
RETURNS [line: Line];
Return the line beginning with keyword followed by "~". line is returned with its index set
to after the "~". The file index points to the beginning of the line following the key line.
The following read procedures leave the stream pointer at the end of the data read. All
searches for a keyword begin at the current file position. If circularSearch is TRUE, the search
will, upon reaching end of file, resume at the file beginning and stop at the current position.
ReadRope: PROC [stream: STREAM, keyword: ROPE, circularSearch: BOOLFALSE]
RETURNS [ROPE];
Return remainder of the key line after the keyword.
ReadInteger: PROC [stream: STREAM, keyword: ROPE, circularSearch: BOOLFALSE]
RETURNS [INTEGER];
Return integer after the key line.
ReadReal: PROC [stream: STREAM, keyword: ROPE, circularSearch: BOOLFALSE]
RETURNS [REAL];
Return real after the key line.
ReadTriple: PROC [stream: STREAM, keyword: ROPE, circularSearch: BOOLFALSE]
RETURNS [Triple];
Return triple after the key line.
The remaining Read procedures take an optional argument, nElements. If nElements is left
defaulted to zero, then the read procedure will attempt to convert all lines past the keyword
line until a new keyword line or comment line is found. The number of such lines is first
determined by reading ahead in the file. This can be time consuming for large files. If the
client knows the number of such lines, however, this look-ahead can be eliminated by
supplying a positive value for nElements.
ReadIntegerSequence: PROC [
stream: STREAM, keyword: ROPE, circularSearch: BOOLFALSE, nElements: INT ← 0]
RETURNS [REF IntegerSequence];
ReadRealSequence: PROC [
stream: STREAM, keyword: ROPE, circularSearch: BOOLFALSE, nElements: INT ← 0]
RETURNS [REF RealSequence];
If key non-nil, search file forward from current stream position for the key; if not found,
search file from its beginning.
ReadTripleSequence: PROC [
stream: STREAM, keyword: ROPE, circularSearch: BOOLFALSE, nElements: INT ← 0]
RETURNS [REF TripleSequence];
ReadNatTable: PROC [
stream: STREAM, keyword: ROPE, circularSearch: BOOLFALSE, nElements: INT ← 0]
RETURNS [REF NatTable];
ReadVertexInfoSequence: PROC [
stream: STREAM, keyword: ROPE, circularSearch: BOOLFALSE, nElements: INT ← 0]
RETURNS [REF VertexInfoSequence];
Read object coordinates, shading normal, color, transmittance, texture coordinates.
(All other values in vertexInfo are specific to a given view).
If, within the file, no fields are specified following the keyword, then all five of the above
data are presumed present and in the order indicated. Otherwise, the individual fields must
be indicated according to the following identifier conventions:
"xyzCoords":  surface x, y, and z coordinates at vertex (Triple)
"normalVec":  surface normal vector at vertex (Triple)
"rgbColor":  color as r, g, and b values from 0 to 1 at vertex (Triple)
"transmittance": surface transmittance at vertex (Real)
"textureCoords": vertex texture coordinates (Triple)
ReadFields: PROC [
stream: STREAM, keyword: ROPE, circularSearch: BOOLFALSE, nElements: INT ← 0]
RETURNS [fields: REF FieldSequence];
Read a sequence of lines from the file, beginning after the keyword.
For example, suppose a file contains the key line:
Polygons~ index: Integer color: Triple vertices: Nats
followed by a set of lines, each containing a polygon index (integer), a color (triple) and a
sequence of vertex indices (nats). The information could be read from the file as follows:
indices: REF IntegerSequence;
colors: REF TripleSequence;
vertices: REF NatTable;
polygons: REF FieldSequence ← ThreeDIO.ReadFields[stream, "Polygons"];
FOR n: NAT IN [0..fields.length) DO
SELECT TRUE FROM
Rope.Equal[polygons[n].id, "index"] => indices ← NARROW[polygons[n].sequence];
Rope.Equal[polygons[n].id, "color"] => colors ← NARROW[polygons[n].sequence];
Rope.Equal[polygons[n].id, "vertices"] => vertices ← NARROW[polygons[n].sequence];
ENDCASE => NULL;
ENDLOOP;
If one wished, for example, to print the vertices of the second polygon:
IF polygons.length > 1 THEN {
FOR n: NAT IN [0..vertices[1].length) DO
Print[vertices[1][n]];
ENDLOOP;
};
Write Procedures
WriteVertexInfoSequence: PROC [
stream: STREAM, keyword: ROPE, vertexInfo: REF VertexInfoSequence,
xyz, normal, color, trans, texture: BOOLTRUE];
Write object coordinates, shading normal, color, transmittance, texture coordinates.
(All other values in vertexInfo are specific to a given view.) Omit any of the vertex
info fields if the corresponding boolean is false.
WriteFields: PROC [stream: STREAM, keyword: ROPE, fields: REF FieldSequence];
END.