File: Filein3dImpl.mesa
Last edited by Bier on May 24, 1985 0:23:59 am PDT
Copyright © 1984 by Xerox Corporation. All rights reserved.
Contents: Recreates a 3d database from a 3d text file of the sort produced by Fileout3d.mesa.
Note: When you change this file, you may wish to update versionRope in DisplayList3dImplA.
DIRECTORY
CoordSys,
CSG,
DisplayList3d,
Filein3d,
FS,
GraphicsColor,
IO,
Rope,
SV2d,
SV3d,
SVArtwork,
SVError,
SVModelTypes,
SVSceneTypes,
SweepGeometry,
TFI3d;
Filein3dImpl:
PROGRAM
IMPORTS CoordSys, CSG, DisplayList3d, FS, GraphicsColor, IO, Rope, SVArtwork, SVError, TFI3d
EXPORTS Filein3d =
BEGIN
ArtworkClass: TYPE = SVModelTypes.ArtworkClass;
Assembly: TYPE = SVSceneTypes.Assembly;
AssemblyList: TYPE = SVSceneTypes.AssemblyList;
Artwork: TYPE = SVModelTypes.Artwork;
Color: TYPE = GraphicsColor.Color;
CoordSystem: TYPE = SVModelTypes.CoordSystem;
CoordSysList: TYPE = SVModelTypes.CoordSysList;
FileCamera: TYPE = SVSceneTypes.FileCamera;
LightSource: TYPE = SVModelTypes.LightSource;
LightSourceList: TYPE = LIST OF LightSource;
MasterObject: TYPE = SVSceneTypes.MasterObject;
MasterObjectList: TYPE = SVSceneTypes.MasterObjectList;
MasterObjectClass: TYPE = SVSceneTypes.MasterObjectClass;
Material: TYPE = SVModelTypes.Material;
Matrix3by3: TYPE = SV2d.Matrix3by3;
Matrix4by4: TYPE = SV3d.Matrix4by4;
NameList: TYPE = LIST OF Rope.ROPE;
OMap: TYPE = SVModelTypes.OMap;
Point2d: TYPE = SV2d.Point2d;
Point3d: TYPE = SV3d.Point3d;
PointSetOp: TYPE = SVSceneTypes.PointSetOp; -- {union, intersection, difference}
Scene: TYPE = SVSceneTypes.Scene;
SMap: TYPE = SVModelTypes.SMap;
SpaceFunction: TYPE = REF SpaceFunctionObj;
SpaceFunctionObj: TYPE = SVModelTypes.SpaceFunctionObj;
Vector: TYPE = SV3d.Vector;
LinearMesh: TYPE = REF LinearMeshRecord;
LinearMeshRecord: TYPE = SweepGeometry.LinearMeshRecord;
RevoluteMesh: TYPE = REF RevoluteMeshRecord;
RevoluteMeshRecord: TYPE = SweepGeometry.RevoluteMeshRecord;
LinearMeshArray: TYPE = SweepGeometry.LinearMeshArray;
RevoluteMeshArray: TYPE = SweepGeometry.RevoluteMeshArray;
FileinScene:
PUBLIC
PROC [scene: Scene, f:
IO.
STREAM, wdirForAIS: Rope.
ROPE] = {
csList: CoordSysList;
worldCS: CoordSystem;
sceneName: Rope.ROPE;
version: REAL;
restOfVersionRope: Rope.ROPE;
TFI3d.ReadBlankAndRope[f, "File:"];
TFI3d.ReadBlank[f];
[] ← TFI3d.ReadWord[f];
TFI3d.ReadWhiteSpace[f];
TFI3d.ReadRope[f, "3D file for scene:"];
TFI3d.ReadBlank[f];
sceneName ← TFI3d.ReadWord[f];
TFI3d.ReadWhiteSpace[f];
TFI3d.ReadRope[f, "Produced by Solidviews Version"];
TFI3d.ReadBlank[f];
version ← TFI3d.ReadReal[f];
restOfVersionRope ← TFI3d.ReadLine[f];
IF version >= 2.0 THEN ReadOptions[f, scene];
IF scene.lightSources =
NIL
THEN {
ambientLight: LightSource ← DisplayList3d.CreateAmbientLightSource["Ambient", GraphicsColor.RGBToColor[0.2,0.2,0.2]];
scene.lightSources ← CONS[ambientLight, NIL];
};
TFI3d.ReadBlank[f];
csList ← FileinCoordSystems[f, scene];
FileinLightSources[f, scene];
worldCS ← CoordSys.FindCoordSysInList["WORLD", csList];
FileinObjects[f, scene];
scene.assembly ← FileinAssembly[f, scene, csList, version, wdirForAIS];
IF version >= 3.0 THEN FileinCameras[f, scene, csList, version]
ELSE scene.cameras ← DisplayList3d.InitialCameraList[];
IF version >= 3.0 THEN FileinCameraOrder[f, scene]
ELSE scene.cameraOrder ← LIST["Front"];
TFI3d.ReadBlank[f];
TFI3d.ReadRope[f, "END"];
f.Close[];
};
ReadOptions:
PROCEDURE [f:
IO.
STREAM, scene: Scene] = {
keyWord, option: Rope.ROPE;
good: BOOL;
nextChar: CHAR;
twoCRsFound: BOOL ← FALSE;
TFI3d.ReadBlank[f];
UNTIL twoCRsFound
DO
[keyWord, good] ← TFI3d.ReadKeyWord[f];
IF
NOT good
THEN {
nextChar ← IO.PeekChar[f];
IF nextChar =
IO.
CR
THEN {
[] ← IO.GetChar[f];
twoCRsFound ← TRUE;
};
LOOP};
good ← TFI3d.ReadHorizontalBlank[f];
IF
NOT good
THEN {
nextChar ← IO.PeekChar[f];
IF nextChar =
IO.
CR
THEN {
[] ← IO.GetChar[f];
twoCRsFound ← TRUE;
};
LOOP};
option ← TFI3d.ReadLine[f];
ProcessOption[keyWord, option, scene];
nextChar ← IO.PeekChar[f];
IF nextChar =
IO.
CR
THEN {
[] ← IO.GetChar[f];
twoCRsFound ← TRUE;
};
ENDLOOP;
};
ProcessOption:
PROC [keyWord: Rope.
ROPE, option: Rope.
ROPE, scene: Scene] = {
SELECT TRUE FROM
Known Options
Rope.Equal[keyWord, "background color",
FALSE] => {
scene.backgroundColor ← TFI3d.ReadColor[IO.RIS[option]];
};
Rope.Equal[keyWord, "shadows",
FALSE] => {
good, truth: BOOL;
[truth, good] ← TFI3d.ReadBool[IO.RIS[option]];
IF NOT good THEN RETURN;
scene.shadows ← truth;
};
Rope.Equal[keyWord, "ambient",
FALSE] => {
color: Color;
ls: LightSource;
color ← TFI3d.ReadColor[IO.RIS[option]];
ls ← DisplayList3d.CreateAmbientLightSource["Ambient", color];
DisplayList3d.AddLightSourceToScene[ls, scene];
};
ENDCASE;
}; -- end of ProcessOption
FileinCoordSystems:
PROC [f:
IO.
STREAM, scene: Scene]
RETURNS [csList: CoordSysList] = {
count: NAT;
mat: Matrix4by4;
newCS: CoordSystem;
csName, wrtName: Rope.ROPE;
csList ← NIL;
TFI3d.ReadRope[f, "CoordSystems"];
TFI3d.ReadWhiteSpace[f];
TFI3d.ReadRope[f, "["];
count ← TFI3d.ReadNAT[f];
TFI3d.ReadRope[f, "]:"]; TFI3d.ReadWhiteSpace[f];
FOR i:
NAT
IN[1..count]
DO
TFI3d.ReadRope[f, "CoordSys:"];
csName ← TFI3d.ReadBlankAndWord[f];
TFI3d.ReadWhiteSpace[f];
TFI3d.ReadRope[f, "mat:"];
TFI3d.ReadBlank[f];
mat ← TFI3d.FileinMatrix[f];
TFI3d.ReadBlankAndRope[f, "withRespectTo:"];
wrtName ← TFI3d.ReadBlankAndWord[f];
TFI3d.ReadWhiteSpace[f];
SELECT
TRUE
FROM
Rope.Equal[csName,"WORLD"] => {
newCS ← CoordSys.CreateRoot["WORLD"];
WORLD must be defined with respect to NIL, and must be the identity matrix.
scene.coordSysRoot ← newCS;
csList ← AppendToCoordSystems[newCS, csList];
};
Rope.Equal[csName,"SCREEN"] => {};
SCREEN must be in terms of NIL.
The matrix between them must be a translation
SCREEN is ignored since it depends on viewer size and shouldn't be in these files anyway.
ENDCASE => {
Other coord systems are unrestricted. Create them with the new data.
wrtCS: CoordSystem ← CoordSys.FindCoordSysInList[wrtName, csList];
newCS ← CoordSys.CreateCoordSysInTree[csName,mat,wrtCS,scene.coordSysRoot];
csList ← AppendToCoordSystems[newCS, csList];
};
All coordinate systems other than screen and world will be added to the scene's coord sys list (not the same as csList!) when assemblies (see FileinAssemblies) are added.
ENDLOOP;
}; -- end of FileinCoordSystems
AppendToCoordSystems:
PROC [cs: CoordSystem, list: CoordSysList]
RETURNS [CoordSysList] = {
A copy of List.Nconc1 for CoordSysList instead of LIST OF REF ANY
z: CoordSysList ← list;
IF z = NIL THEN RETURN[CONS[cs,NIL]];
UNTIL z.rest =
NIL
DO z ← z.rest;
ENDLOOP;
z.rest ← CONS[cs,NIL];
RETURN[list];
};
FileinLightSources:
PROC [f:
IO.
STREAM, scene: Scene] = {
count: NAT;
thisLS: LightSource;
lsName: Rope.ROPE;
point3d: Point3d;
color: Color;
TFI3d.ReadRope[f, "LightSources"];
TFI3d.ReadBlankAndRope[f, "["];
count ← TFI3d.ReadNAT[f];
TFI3d.ReadRope[f, "]:"]; TFI3d.ReadWhiteSpace[f];
FOR i:
NAT
IN[1..count]
DO
TFI3d.ReadRope[f, "LightSource:"];
lsName ← TFI3d.ReadBlankAndWord[f];
TFI3d.ReadBlankAndRope[f, "position:"];
TFI3d.ReadBlank[f];
point3d ← TFI3d.ReadPoint3d[f];
TFI3d.ReadBlankAndRope[f, "color:"];
TFI3d.ReadBlank[f];
color ← TFI3d.ReadColor[f];
TFI3d.ReadWhiteSpace[f];
thisLS ← DisplayList3d.CreateLightSource[lsName, point3d, color];
DisplayList3d.AddLightSourceToScene[thisLS, scene];
ENDLOOP;
};
FileinCameras:
PROC [f:
IO.
STREAM, scene: Scene, csList: CoordSysList, version:
REAL] = {
worldCS: CoordSystem ← CoordSys.FindCoordSysInList["WORLD", csList];
count: NAT;
fileCamera: FileCamera;
TFI3d.ReadBlankAndRope[f, "Cameras"];
TFI3d.ReadBlankAndRope[f, "["];
count ← TFI3d.ReadNAT[f];
TFI3d.ReadRope[f, "]:"]; TFI3d.ReadWhiteSpace[f];
FOR i:
NAT
IN[1..count]
DO
fileCamera ← TFI3d.ReadCamera[f, worldCS, scene, version];
DisplayList3d.AddCameraToScene[fileCamera, scene];
ENDLOOP;
};
FileinCameraOrder:
PROC [f:
IO.
STREAM, scene: Scene] = {
count: NAT;
fileCameraName: Rope.ROPE;
TFI3d.ReadBlankAndRope[f, "Initial Camera Order"];
TFI3d.ReadBlankAndRope[f, "["];
count ← TFI3d.ReadNAT[f];
TFI3d.ReadRope[f, "]:"];
IF count > 0
THEN {
TFI3d.ReadBlank[f];
fileCameraName ← TFI3d.ReadWord[f];
DisplayList3d.AddCameraOrderNameToScene[fileCameraName, scene];
FOR i:
NAT
IN[2..count]
DO
TFI3d.ReadBlankAndRope[f, ","];
TFI3d.ReadBlank[f];
fileCameraName ← TFI3d.ReadWord[f];
DisplayList3d.AddCameraOrderNameToScene[fileCameraName, scene];
ENDLOOP;
};
TFI3d.ReadBlank[f];
};
ReadArtwork:
PRIVATE
PROC [f:
IO.
STREAM, csList: CoordSysList, defaultCS: CoordSystem, wdir: Rope.
ROPE, version:
REAL]
RETURNS [artwork: Artwork] = {
source, isColorRope, nextWord, aisFileName: Rope.ROPE ← NIL;
surface: REF ANY;
material: Material;
mat: Matrix3by3;
color: GraphicsColor.Color;
isColorFile: BOOL;
sMap: SMap;
oMap: OMap;
resolution: REAL;
success: BOOL;
csName, className: Rope.ROPE;
coordSys: CoordSystem;
class: ArtworkClass;
IF version > 5.2 THEN {
TFI3d.ReadBlankAndRope[f, "coordSys: "];
csName ← TFI3d.ReadBlankAndWord[f];
IF Rope.Equal[csName, "NIL"] THEN coordSys ← NIL
ELSE coordSys ← CoordSys.FindCoordSysInList[csName, csList];
TFI3d.ReadBlankAndRope[f, "class: "];
className ← TFI3d.ReadBlankAndWord[f];
class ← RopeToArtworkClass[className];
}
ELSE {
coordSys ← defaultCS;
class ← simpleSurface;
};
TFI3d.ReadBlankAndRope[f, "material:"];
TFI3d.ReadBlank[f];
material ← TFI3d.ReadMaterial[f];
TFI3d.ReadBlankAndRope[f, "surface:"];
surface ← TFI3d.ReadSurface[f];
IF (surface #
NIL)
AND class # spaceFunction
THEN {
nextWord ← TFI3d.ReadBlankAndWord[f];
SELECT
TRUE
FROM
Rope.Equal[nextWord, "source:"] => {
-- oMap and sMap are defaulted
source ← TFI3d.ReadBlankAndWord[f];
SELECT
TRUE
FROM
ISTYPE[surface, SVModelTypes.Tube] => {oMap ← tubeO; sMap ← tubeS};
ISTYPE[surface, SVModelTypes.Box] => {oMap ← orthogonal; sMap ← unfoldedBox};
ENDCASE => ERROR;
};
Rope.Equal[nextWord, "SMap:"] => {
TFI3d.ReadBlank[f];
sMap ← TFI3d.ReadSMap[f];
TFI3d.ReadBlankAndRope[f, "OMap:"];
TFI3d.ReadBlank[f];
oMap ← TFI3d.ReadOMap[f];
TFI3d.ReadBlankAndRope[f, "source:"];
source ← TFI3d.ReadBlankAndWord[f];
};
ENDCASE => ERROR;
isColorRope ← TFI3d.ReadBlankAndWord[f];
SELECT
TRUE
FROM
Rope.Equal[isColorRope, "colorFile", FALSE] => isColorFile ← TRUE;
Rope.Equal[isColorRope, "bwFile", FALSE] => isColorFile ← FALSE;
ENDCASE => ERROR;
TFI3d.ReadBlankAndRope[f, "resolution:"];
TFI3d.ReadBlank[f];
resolution ← TFI3d.ReadReal[f];
TFI3d.ReadBlankAndRope[f, "mat:"];
TFI3d.ReadBlank[f];
mat ← TFI3d.FileinMatrix3by3[f];
success ← TRUE;
[aisFileName,,] ←
FS.ExpandName[source, wdir
!
FS.Error => {
IF error.group = user
THEN {
success ← FALSE;
SVError.Append[error.explanation];
CONTINUE;
};
}];
IF NOT success THEN ERROR SVArtwork.FileNotFound;
TFI3d.ReadBlankAndRope[f, "color:"];
TFI3d.ReadBlank[f];
color ← TFI3d.ReadColor[f];
artwork ← SVArtwork.CreateFileArtwork[coordSys, material, surface, oMap, sMap, aisFileName, isColorFile, color, resolution, mat]; -- may generate ERROR SVArtwork.FileNotFound
}
ELSE {
IF surface =
NIL
AND class#spaceFunction
THEN {
TFI3d.ReadBlankAndRope[f, "color:"];
TFI3d.ReadBlank[f];
color ← TFI3d.ReadColor[f];
artwork ← SVArtwork.CreateColorArtwork[color, material]
}
ELSE {
spaceFunction: SpaceFunction;
TFI3d.ReadBlankAndRope[f, "scalars:"];
spaceFunction ← NEW[SpaceFunctionObj];
TFI3d.ReadBlank[f];
spaceFunction.scalars ← TFI3d.ReadPoint3d[f];
TFI3d.ReadBlankAndRope[f, "func: colorcube"];
artwork ← SVArtwork.Create3DArtwork[coordSys, material, spaceFunction];
};
};
};
RopeToArtworkClass:
PROC [className: Rope.
ROPE]
RETURNS [class: ArtworkClass] = {
SELECT TRUE FROM
Rope.Equal[className, "justColor"] => class ← justColor;
Rope.Equal[className, "simpleSurface"] => class ← simpleSurface;
Rope.Equal[className, "spaceFunction"] => class ← spaceFunction;
ENDCASE => ERROR;
};
FileinAssembly:
PROC [f:
IO.
STREAM, scene: Scene, csList: CoordSysList, version:
REAL, wdirForAIS: Rope.
ROPE]
RETURNS [thisA: Assembly] = {
thisCS: CoordSystem;
artwork: Artwork;
scalars: Vector;
primOrComp: Rope.ROPE;
asName, csName, opRope, chairName: Rope.ROPE;
pointSetOp: PointSetOp;
subAssemblies: LIST OF Assembly;
TFI3d.ReadBlankAndRope[f, "Assembly:"];
asName ← TFI3d.ReadBlankAndWord[f];
TFI3d.ReadBlankAndRope[f, ","];
TFI3d.ReadBlankAndRope[f, "coordSys:"];
csName ← TFI3d.ReadBlankAndWord[f];
thisCS ← CoordSys.FindCoordSysInList[csName, csList];
TFI3d.ReadBlankAndRope[f, ","];
primOrComp ← TFI3d.ReadBlankAndWord[f];
SELECT TRUE FROM
Rope.Equal[primOrComp, "Composite",
FALSE] => {
TFI3d.ReadBlankAndRope[f, "artwork:"];
TFI3d.ReadBlank[f];
artwork ← ReadArtwork[f, csList, thisCS, wdirForAIS, version];
TFI3d.ReadBlankAndRope[f, "subassemblies"];
TFI3d.ReadBlankAndRope[f, "["];
IF version < 5.2 THEN TFI3d.ReadBlankAndRope[f, "point set op:"];
opRope ← TFI3d.ReadBlankAndWord[f];
pointSetOp ← CSG.RopeToPointSetOp[opRope];
TFI3d.ReadBlankAndRope[f, "]"];
TFI3d.ReadWhiteSpace[f];
[] ← FileinSubassemblyNames[f];
thisA ← DisplayList3d.CreateClusterAssemblyAtExistingCoordSys[asName, pointSetOp, scene, thisCS, FALSE, NIL];
thisA.artwork ← artwork;
subAssemblies ← FileinAssemblies[f, scene, csList, version, wdirForAIS];
WireUpAssemblyToSubassemblies[thisA, subAssemblies, scene];
};
Rope.Equal[primOrComp, "Primitive",
FALSE] => {
obName: Rope.ROPE;
masterObjectFound: BOOL;
TFI3d.ReadBlankAndRope[f, "scalars:"];
TFI3d.ReadBlank[f];
scalars ← TFI3d.ReadPoint3d[f];
TFI3d.ReadBlankAndRope[f, "artwork:"];
TFI3d.ReadBlank[f];
artwork ← ReadArtwork[f, csList, thisCS, wdirForAIS, version];
TFI3d.ReadBlankAndRope[f, "object:"];
obName ← TFI3d.ReadBlankAndWord[f];
[thisA, masterObjectFound] ←
DisplayList3d.CreatePrimitiveAtExistingCoordSys[asName, obName, scalars, scene, thisCS, artwork, FALSE, NIL];
IF NOT masterObjectFound THEN ERROR MasterObjectNotFound;
IF version >= 5.3
AND Rope.Equal[obName, "jack",
FALSE]
THEN {
TFI3d.ReadBlankAndRope[f, "sittingOn:"];
chairName ← TFI3d.ReadBlankAndWord[f];
IF Rope.Equal[chairName, "NIL", FALSE] THEN thisA.sittingOn ← NIL
ELSE thisA.sittingOn ← chairName;
};
};
ENDCASE => SIGNAL ErrorInAssemblyFileout;
}; -- end of FileinAssembly
MasterObjectNotFound: PUBLIC ERROR = CODE;
FileinAssemblies:
PROC [f:
IO.
STREAM, scene: Scene, csList: CoordSysList, version:
REAL, wdirForAIS: Rope.
ROPE]
RETURNS [asList:
LIST
OF Assembly] = {
count: NAT;
thisA: Assembly;
asList ← NIL;-- initially
TFI3d.ReadBlankAndRope[f, "Subassemblies"];
TFI3d.ReadBlankAndRope[f, "["];
count ← TFI3d.ReadBlankAndNAT[f];
TFI3d.ReadBlankAndRope[f, "]:"]; TFI3d.ReadWhiteSpace[f];
FOR i:
NAT
IN[1..count]
DO
thisA ← FileinAssembly[f, scene, csList, version, wdirForAIS];
asList ← AppendToAssemblyList[thisA, asList];
ENDLOOP;
};
ErrorInAssemblyFileout: PUBLIC SIGNAL = CODE;
WireUpAssemblyToSubassemblies:
PROC [assem: Assembly, subA:
LIST
OF Assembly, scene: Scene] = {
thisSub: Assembly;
FOR al:
LIST
OF Assembly ← subA, al.rest
UNTIL al =
NIL
DO
thisSub ← al.first;
DisplayList3d.ConnectAssemblyToParent[thisSub, assem];
ENDLOOP;
};
AppendToAssemblyList:
PROC [as: Assembly, list:
LIST
OF Assembly]
RETURNS [
LIST
OF Assembly] = {
A copy of List.Nconc1 for AssemblyListObj instead of LIST OF REF ANY
z: LIST OF Assembly ← list;
IF z = NIL THEN RETURN[CONS[as,NIL]];
UNTIL z.rest =
NIL
DO z ← z.rest;
ENDLOOP;
z.rest ← CONS[as,NIL];
RETURN[list];
};
AppendToNameList:
PROC [name: Rope.
ROPE, list: NameList]
RETURNS [NameList] = {
A copy of List.Nconc1 for NameList instead of LIST OF REF ANY.
z: NameList ← list;
IF z = NIL THEN RETURN[CONS[name,NIL]];
UNTIL z.rest =
NIL
DO z ← z.rest;
ENDLOOP;
z.rest ← CONS[name,NIL];
RETURN[list];
};
FileinSubassemblyNames:
PROC [f:
IO.
STREAM]
RETURNS [nameList: NameList] = {
count: NAT;
thisName: Rope.ROPE;
nameList ← NIL;
TFI3d.ReadBlankAndRope[f, "["];
count ← TFI3d.ReadBlankAndNAT[f];
TFI3d.ReadBlankAndRope[f, "]:"];
TFI3d.ReadBlankAndRope[f, "("];
IF count = 0 THEN {TFI3d.ReadBlankAndRope[f, ")"]; RETURN;};
thisName ← TFI3d.ReadBlankAndWord[f];
nameList ← AppendToNameList[thisName, nameList];
FOR i:
NAT
IN[2..count]
DO
TFI3d.ReadRope[f, ", "];
thisName ← TFI3d.ReadBlankAndWord[f];
nameList ← AppendToNameList[thisName, nameList];
ENDLOOP;
TFI3d.ReadBlankAndRope[f, ")"];
TFI3d.ReadWhiteSpace[f];
};
FileinObjects:
PROC [f:
IO.
STREAM, scene: Scene] = {
count: NAT;
obName, obClass: Rope.ROPE;
moClass: MasterObjectClass;
moClassFound: BOOL;
mo: MasterObject;
TFI3d.ReadRope[f, "Objects"];
TFI3d.ReadBlankAndRope[f, "["];
count ← TFI3d.ReadNAT[f];
TFI3d.ReadRope[f, "]:"];
TFI3d.ReadWhiteSpace[f];
FOR i:
NAT
IN[1..count]
DO
TFI3d.ReadBlankAndRope[f, "Master Object:"];
obName ← TFI3d.ReadBlankAndWord[f];
TFI3d.ReadWhiteSpace[f];
TFI3d.ReadRope[f, "class:"];
obClass ← TFI3d.ReadBlankAndWord[f];
TFI3d.ReadBlank[f];
[moClass, moClassFound] ← DisplayList3d.FindClassFromName[obClass];
IF NOT moClassFound THEN ERROR MasterObjectClassNotFound;
mo ← moClass.filein[f, obName];
DisplayList3d.AddMasterObjectToScene[mo, scene];
ENDLOOP;-- next master object
TFI3d.ReadBlank[f];
}; -- end of FileinObjects
MasterObjectClassNotFound: PUBLIC ERROR = CODE;
END.