File: Filein3dImpl.mesa
Last edited by Bier on August 16, 1983 9:59 am
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,
GraphicsColor,
IO,
Matrix3d,
Rope,
Shading,
SVArtwork,
SVDisplayListFiling,
SVMappings,
SVMatrix2d,
SVVector3d,
SweepGeometry,
TFI3d;
Filein3dImpl: PROGRAM
IMPORTS CoordSys, DisplayList3d, IO, Matrix3d, Rope, SVArtwork, SVDisplayListFiling, TFI3d
EXPORTS Filein3d =
BEGIN
Artwork: TYPE = SVArtwork.Artwork;
Color: TYPE = GraphicsColor.Color;
FileCamera: TYPE = DisplayList3d.FileCamera;
Matrix3by3: TYPE = SVMatrix2d.Matrix3by3;
Matrix4by4: TYPE = Matrix3d.Matrix4by4;
OMap: TYPE = SVArtwork.OMap;
Point3d: TYPE = Matrix3d.Point3d;
Point2d: TYPE = Matrix3d.Point2d;
Material: TYPE = SVArtwork.Material;
SMap: TYPE = SVArtwork.SMap;
AssemblyList: TYPE = REF AssemblyListObj;
AssemblyListObj: TYPE = DisplayList3d.AssemblyListObj;
PointSetOp: TYPE = DisplayList3d.PointSetOp;-- {union, intersection, difference}
Assembly: TYPE = REF AssemblyObj;
AssemblyObj: TYPE = DisplayList3d.AssemblyObj;
MasterObject: TYPE = REF MasterObjectRec;
MasterObjectRec: TYPE = DisplayList3d.MasterObjectRec;
MasterObjectList: TYPE = DisplayList3d.MasterObjectList;
MasterObjectClass: TYPE = REF MasterObjectClassObj;
MasterObjectClassObj: TYPE = DisplayList3d.MasterObjectClassObj;
Scene: TYPE = REF SceneObj;
SceneObj: TYPE = DisplayList3d.SceneObj;
Vector: TYPE = SVVector3d.Vector;
LightSource: TYPE = REF LightSourceObj;
LightSourceObj: TYPE = Shading.LightSourceObj;
LightSourceList: TYPE = LIST OF LightSource;
LinearMesh: TYPE = REF LinearMeshRecord;
LinearMeshRecord: TYPE = SweepGeometry.LinearMeshRecord;
RevoluteMesh: TYPE = REF RevoluteMeshRecord;
RevoluteMeshRecord: TYPE = SweepGeometry.RevoluteMeshRecord;
LinearMeshArray: TYPE = SweepGeometry.LinearMeshArray;
RevoluteMeshArray: TYPE = SweepGeometry.RevoluteMeshArray;
CoordSystem: TYPE = REF CoordSysObj;
CoordSysObj: TYPE = CoordSys.CoordSysObj;
CoordSysList: TYPE = CoordSys.CoordSysList;
NameList: TYPE = LIST OF Rope.ROPE;
FileinScene: PUBLIC PROC [scene: Scene, f: IO.STREAM ] = {
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];
TFI3d.ReadBlank[f];
csList ← FileinCoordSystems[f, scene];
FileinLightSources[f, scene];
worldCS ← CoordSys.FindCoordSysFromName["WORLD", csList];
FileinObjects[f, scene];
FileinSceneAssembly[f, scene, csList];
IF version >= 3.0 THEN FileinCameras[f, scene, csList]
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: BOOLFALSE;
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;
};
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.CreateCoordSys["WORLD", Matrix3d.Identity[], NIL];
WORLD must be defined with respect to NIL,
and must be the identity matrix.
scene.worldCS ← newCS;
DisplayList3d.AddCoordSysToScene[newCS, scene];
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.FindCoordSysFromName[wrtName, csList];
newCS ← CoordSys.CreateCoordSys[csName,mat,wrtCS];
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] = {
worldCS: CoordSystem ← CoordSys.FindCoordSysFromName["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];
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];
};
FileinSceneAssembly: PROC [f: IO.STREAM, scene: Scene, csList: CoordSysList] = {
cs: CoordSystem;
cs ← CoordSys.FindCoordSysFromName["sceneAssembly", csList];
DisplayList3d.AddCoordSysToScene[cs, scene]; -- sceneAssembly is added to scene first
scene.assembly ← FileinAssembly[f, scene, csList]; -- doesn't fill in coordSys field
scene.assembly.coordSys ← cs; -- so fill in coordSys field now.
};
ReadArtwork: PRIVATE PROC [f: IO.STREAM] RETURNS [artwork: Artwork] = {
source, isColorRope, nextWord: Rope.ROPENIL;
surface: REF ANY;
material: Material;
mat: Matrix3by3;
color: GraphicsColor.Color;
isColorFile: BOOL;
sMap: SMap;
oMap: OMap;
resolution: REAL;
TFI3d.ReadBlankAndRope[f, "material:"];
TFI3d.ReadBlank[f];
material ← TFI3d.ReadMaterial[f];
TFI3d.ReadBlankAndRope[f, "surface:"];
surface ← TFI3d.ReadSurface[f];
IF surface # NIL 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, SVMappings.Tube] => {oMap ← tubeO; sMap ← tubeS};
ISTYPE[surface, SVMappings.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];
};
TFI3d.ReadBlankAndRope[f, "color:"];
TFI3d.ReadBlank[f];
color ← TFI3d.ReadColor[f];
IF surface = NIL THEN artwork ← SVArtwork.CreateColorArtwork[color, material]
ELSE artwork ← SVArtwork.CreateFileArtwork[material, surface, oMap, sMap, source, isColorFile, color, resolution, mat]; -- may generate ERROR SVArtwork.FileNotFound
};
FileinAssembly: PROC [f: IO.STREAM, scene: Scene, csList: CoordSysList] RETURNS [thisA: Assembly] = {
objectOrSubassemblies: Rope.ROPE;
thisCS: CoordSystem;
artwork: Artwork;
scalars: Vector;
asName, csName, opRope: Rope.ROPE;
pointSetOp: PointSetOp;
subAssemblies: LIST OF Assembly;
TFI3d.ReadRope[f, "Assembly:"];
asName ← TFI3d.ReadBlankAndWord[f];
TFI3d.ReadBlankAndRope[f, ","];
TFI3d.ReadBlankAndRope[f, "coordSys:"];
csName ← TFI3d.ReadBlankAndWord[f];
thisCS ← CoordSys.FindCoordSysFromName[csName, csList];
TFI3d.ReadBlankAndRope[f, ","];
TFI3d.ReadBlankAndRope[f, "scalars:"];
TFI3d.ReadBlank[f];
scalars ← TFI3d.ReadPoint3d[f];
TFI3d.ReadBlankAndRope[f, "artwork:"];
TFI3d.ReadBlank[f];
artwork ← ReadArtwork[f];
TFI3d.ReadWhiteSpace[f];
is it primitive or compostite?
objectOrSubassemblies ← TFI3d.ReadWord[f];
SELECT TRUE FROM
composite
Rope.Equal[objectOrSubassemblies, "subassemblies", TRUE] => {
TFI3d.ReadBlankAndRope[f, "[point set op:"];
opRope ← TFI3d.ReadBlankAndWord[f];
SELECT TRUE FROM
Rope.Equal[opRope, "union", TRUE] => pointSetOp ← union;
Rope.Equal[opRope, "intersection", TRUE] => pointSetOp ← intersection;
Rope.Equal[opRope, "difference", TRUE] => pointSetOp ← difference;
ENDCASE => ERROR;
TFI3d.ReadBlankAndRope[f, "]"];
TFI3d.ReadWhiteSpace[f];
[] ← FileinSubassemblyNames[f];
thisA ← DisplayList3d.CreateClusterAssembly[asName, pointSetOp];
thisA.coordSys ← thisCS;
thisA.scalars ← scalars;-- but of course this will never be used by a composite
thisA.artwork ← artwork;
subAssemblies ← FileinAssemblies[f, scene, csList];
WireUpAssemblyToSubassemblies[thisA, subAssemblies, scene];};
primitive
Rope.Equal[objectOrSubassemblies, "object:", TRUE] => {
obName: Rope.ROPE;
masterObjectFound: BOOL;
TFI3d.ReadBlank[f];
obName ← TFI3d.ReadWord[f];
TFI3d.ReadWhiteSpace[f];
[thisA, masterObjectFound] ←
DisplayList3d.CreatePrimitiveAssembly[asName, obName, [1,1,1], scene];
IF NOT masterObjectFound THEN ERROR MasterObjectNotFound;
thisA.coordSys ← thisCS;
thisA.scalars ← scalars;
thisA.artwork ← artwork;
};
ENDCASE => SIGNAL ErrorInAssemblyFileout;
}; -- end of FileinAssembly
MasterObjectNotFound: PUBLIC ERROR = CODE;
FileinAssemblies: PROC [f: IO.STREAM, scene: Scene, csList: CoordSysList] 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];
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;
SVDisplayListFiling.AddSubassemblyToAssemblyWithCS[thisSub, assem, scene, thisSub.coordSys];
This operation also adds the coordinate system to the scene.
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.