DisplayList3dImplA.mesa
Last edited by Bier on August 5, 1985 5:32:48 pm PDT
Copyright © 1984 by Xerox Corporation. All rights reserved.
Author: Eric Bier in July, 1982
Don't add any more to this file. It won't compile.
DIRECTORY
CoordSys,
CSGGraphics,
DisplayList3d,
DisplayList3dPrivate,
Imager,
ImagerColor,
IO,
Matrix3d,
Rope,
SV2d,
SV3d,
SVArtwork,
SVError,
SVModelTypes,
SVPolygon3d,
SVSceneTypes,
SVRayTypes,
SVToolObject;
DisplayList3dImplA: PROGRAM
IMPORTS CoordSys, CSGGraphics, DisplayList3d, DisplayList3dPrivate, Imager, ImagerColor, IO, Matrix3d, Rope, SVArtwork, SVError, SVPolygon3d, SVToolObject
EXPORTS DisplayList3d, DisplayList3dPrivate =
BEGIN
Version Rope
versionRope: PUBLIC Rope.ROPE ← "Solidviews Version 5.3 OF June 12, 1985 10:17:19 am PDT";
Used for version stamps and initial greeting. Exported to DisplayList3d.
Introduction
Contents: The Solidviews System is involved with the creation and manipulation of three dimensional scenes. A scene is a list of lightsources, and a tree of assemblies. Intermediate nodes in this tree are cluster assemblies. The leaves of this tree are primitive assemblies. Each cluster assembly specifies a point set operation describing how its children should be combined. Each primitive assembly refers to a master object (a shape) and a triplet of scalars describing how this master object should be scaled before being displayed. All assemblies (cluster or primitive) refer to a coordinate system which describes how the object should be positioned and oriented with respect to its parent coordinate system (from which we can derive how it will be positioned in the scene's master coordinate system known as WORLD). Each master object is an instance of a class of shapes called a master object class.
Imported Types
Artwork: TYPE = SVModelTypes.Artwork;
Camera: TYPE = CSGGraphics.Camera;
Classification: TYPE = SVRayTypes.Classification;
Color: TYPE = Imager.Color;
CoordSysList: TYPE = SVModelTypes.CoordSysList;
CoordSystem: TYPE = SVModelTypes.CoordSystem;
CSGTree: TYPE = SVRayTypes.CSGTree;
DrawStyle: TYPE = SVModelTypes.DrawStyle;
FrameBox: TYPE = REF FrameBoxObj;
FrameBoxObj: TYPE = SVModelTypes.FrameBoxObj;
Matrix4by4: TYPE = SV3d.Matrix4by4;
Plane: TYPE = SV3d.Plane;
Point2d: TYPE = SV2d.Point2d;
Point3d: TYPE = SV3d.Point3d;
PointSetOp: TYPE = SVRayTypes.PointSetOp;-- {union, intersection, difference}
Poly3d: TYPE = SV3d.Poly3d;
Primitive: TYPE = SVRayTypes.Primitive;
Projection: TYPE = SVModelTypes.Projection;
Ray: TYPE = SVRayTypes.Ray;
Shape: TYPE = REF ShapeObj;
ShapeObj: TYPE = SVSceneTypes.ShapeObj; -- allocated in CreateAndAddPrimitiveAssembly, etc.
Vector: TYPE = SV3d.Vector;
DisplayList Types
Databases, Scenes, Assemblies, and Lightsources
Database: TYPE = REF DatabaseObj;
DatabaseObj: TYPE = SVSceneTypes.DatabaseObj;
Scene: TYPE = REF SceneObj;
SceneObj: TYPE = SVSceneTypes.SceneObj;
Assembly: TYPE = REF AssemblyObj;
AssemblyObj: TYPE = SVSceneTypes.AssemblyObj;
ToolData: TYPE = REF ToolDataObj;
ToolDataObj: TYPE = SVSceneTypes.ToolDataObj;
FrameBlock: TYPE = REF FrameBlockObj;
FrameBlockObj: TYPE = SVSceneTypes.FrameBlockObj;
AssemblyList: TYPE = REF AssemblyListObj;
AssemblyListObj: TYPE = SVSceneTypes.AssemblyListObj;
LightSource: TYPE = REF LightSourceObj;
LightSourceObj: TYPE = SVModelTypes.LightSourceObj;
LightSourceList: TYPE = SVModelTypes.LightSourceList;
FileCamera: TYPE = REF FileCameraObj;
FileCameraObj: TYPE = SVSceneTypes.FileCameraObj;
FileCameraList: TYPE = SVSceneTypes.FileCameraList;
Master Object Class Types
MasterObjectClass: TYPE = REF MasterObjectClassObj;
MasterObjectClassObj: TYPE = SVSceneTypes.MasterObjectClassObj;
MasterObjectClassList: TYPE = SVSceneTypes.MasterObjectClassList;
FileoutProc: TYPE = SVSceneTypes.FileoutProc;
FileinProc: TYPE = SVSceneTypes.FileinProc;
FileoutPolyProc: TYPE = SVSceneTypes.FileoutPolyProc;
Master Object Types
MasterObject: TYPE = REF MasterObjectRec;
MasterObjectRec: TYPE = SVSceneTypes.MasterObjectRec;
MasterObjectList: TYPE = SVSceneTypes.MasterObjectList;
RayCastProc: TYPE = SVRayTypes.RayCastProc;
RayCastNoBBoxesProc: TYPE = SVRayTypes.RayCastNoBBoxesProc;
RayCastBoundingSpheresProc: TYPE = SVRayTypes.RayCastBoundingSpheresProc;
BoundHedronProc: TYPE = SVSceneTypes.BoundHedronProc;
PreprocessProc: TYPE = SVSceneTypes.PreprocessProc;
LineDrawProc: TYPE = SVSceneTypes.LineDrawProc;
NormalsDrawProc: TYPE = SVSceneTypes.NormalsDrawProc;
CountPlanarSurfacesProc: TYPE = SVSceneTypes.CountPlanarSurfacesProc;
GetPlanarSurfacesProc: TYPE = SVSceneTypes.GetPlanarSurfacesProc;
PlanarSurface: TYPE = REF PlanarSurfaceObj;
PlanarSurfaceObj: TYPE = SVSceneTypes.PlanarSurfaceObj;
PlanarSurfaceList: TYPE = SVSceneTypes.PlanarSurfaceList;
DrawPlanarSurfaceProc: TYPE = SVSceneTypes.DrawPlanarSurfaceProc;
DrawSubBoxesProc: TYPE = SVSceneTypes.DrawSubBoxesProc;
DrawSubSpheresProc: TYPE = SVSceneTypes.DrawSubSpheresProc;
Global Variables
globalDatabase: Database;
globalClassList: MasterObjectClassList ← NIL;
globalMOList: MasterObjectList ← NIL;
Set Up the System
RegisterMasterObjectClass: PUBLIC PROC [
name: Rope.ROPE,
filein: FileinProc,
fileout: FileoutProc,
fileoutPoly: FileoutPolyProc,
rayCast: RayCastProc,
rayCastNoBBoxes: RayCastNoBBoxesProc,
rayCastBoundingSpheres: RayCastBoundingSpheresProc,
getHedron: BoundHedronProc,
preprocess: PreprocessProc,
lineDraw: LineDrawProc,
normalsDraw: NormalsDrawProc,
countSurf: CountPlanarSurfacesProc,
getSurf: GetPlanarSurfacesProc,
drawSurf: DrawPlanarSurfaceProc,
drawSubBoxes: DrawSubBoxesProc,
drawSubSpheres: DrawSubSpheresProc]
RETURNS [moClass: MasterObjectClass] = {
moClass ← NEW[MasterObjectClassObj ← [name, filein, fileout, fileoutPoly, rayCast, rayCastNoBBoxes, rayCastBoundingSpheres, getHedron, preprocess, lineDraw, normalsDraw, countSurf, getSurf, drawSurf, drawSubBoxes, drawSubSpheres]];
globalClassList ← AppendClassToList[moClass, globalClassList];
};
RegisterMasterObject: PUBLIC PROC [mo: MasterObject] = {
globalMOList ← AppendToMasterObjects[mo, globalMOList];
};
Create Entities
CreateScene: PUBLIC PROC [name: Rope.ROPE] RETURNS [scene: Scene] = {
Creates scene and adds scene to database. Includes default coordinate systems (WORLD, CAMERA, and SCENE), one default light source, five default master objects (cube, sphere, cone, cylinder, and torus) and seven default cameras (Top, Bottom, Left, Right, Front, UpLeft, and UpRight).
worldCS: CoordSystem ← CoordSys.CreateRoot["WORLD"];
sceneAssemblyCS: CoordSystem;
sceneAssembly: Assembly;
defaultRedLight: LightSource ← CreateLightSource["RedLight",[200,200,400], Imager.red];
defaultGreenLight: LightSource ← CreateLightSource["GreenLight",[-200,200,400], Imager.green];
ambientLight: LightSource ← CreateAmbientLightSource["Ambient", ImagerColor.ColorFromRGB[[0.2,0.2,0.2]]];
defaultWhiteLight: LightSource ← CreateLightSource["WhiteLight",[800,800,1000], Imager.white];
cameras: FileCameraList ← DisplayList3d.InitialCameraList[];
sceneAssemblyCS ← CoordSys.CreateCoordSysInTree["sceneAssembly", Matrix3d.Identity[], worldCS, worldCS];
sceneAssembly ← CreateSceneAssembly["sceneAssembly", union, sceneAssemblyCS, FALSE, NIL];
scene ← NEW[SceneObj ← [
name: name,
coordSysRoot: worldCS,
lightSources: CONS[ambientLight, CONS[defaultWhiteLight, NIL]],
masterObjects: DisplayList3dPrivate.CopyMasterObjectList[globalMOList], -- Copies the list structure but not the objects.
assembly: sceneAssembly,
cameras: cameras,
cameraOrder: LIST["Front"],
backgroundColor: Imager.white,
shadows: FALSE,
dirty: FALSE]];
globalDatabase ← AppendToDatabase[scene, globalDatabase];
};
CreateEmptyScene: PUBLIC PROC [name: Rope.ROPE] RETURNS [scene: Scene] = {
Creates scene and adds scene to database.
scene ← NEW[SceneObj ← [name: name,
coordSysRoot: NIL,
lightSources: NIL,
masterObjects: NIL,
assembly: NIL,
cameras: NIL,
cameraOrder: NIL,
backgroundColor: Imager.white,
shadows: FALSE,
dirty: FALSE]];
globalDatabase ← AppendToDatabase[scene, globalDatabase];
};
CreateMasterObject: PUBLIC PROC [
name: Rope.ROPE,
class: MasterObjectClass,
mainBody: REF ANY,
lineBody: REF ANY,
shadeBody: REF ANY,
rayCastBody: REF ANY] RETURNS [mo: MasterObject] = {
mo ← NEW[MasterObjectRec ←
[name, class, mainBody, lineBody, shadeBody, rayCastBody]];
};
CopyMasterObject: PUBLIC PROC [mo: MasterObject] RETURNS [copy: MasterObject] = {
copy ← NEW[MasterObjectRec];
copy.name ← mo.name;
copy.class ← mo.class;
copy.mainBody ← mo.mainBody;
copy.lineBody ← mo.lineBody;
copy.shadeBody ← mo.shadeBody;
copy.rayCastBody ← mo.rayCastBody;
};
NameWithSuffix: PROC [oldName: Rope.ROPE, suffix: Rope.ROPE, root: CoordSystem] RETURNS [probablyUnique: Rope.ROPE] = {
Used in place of CoordSys.UniqueNameWithSuffix, which takes too long. We just split up oldName into its base and number and splice in the suffix. We assume that if oldName is unique, probablyUnique will be as well.
base: Rope.ROPE;
num: NAT;
[base, num] ← CoordSys.BaseAndNumber[oldName];
probablyUnique ← IO.PutFR["%g%g.%g", [rope[base]], [rope[suffix]], [integer[num]]];
};
CreateAndAddPrimitiveAssembly: PUBLIC PROC [name: Rope.ROPE, object: Rope.ROPE, size: Vector, scene: Scene, parent: Assembly, mat: Matrix4by4, artwork: Artwork ← NIL, isTool: BOOLFALSE, toolData: ToolData ← NIL] RETURNS [assembly: Assembly, masterObjectFound: BOOL, success: BOOL] = {
masterObject: MasterObject;
toolMasterObject: MasterObject;
shape: Shape;
toolName: Rope.ROPE;
scalarName: Rope.ROPE;
success ← FALSE;
IF AssemblyNameIsPresent[name, scene] THEN {
SVError.Append[Rope.Cat["Assembly ", name, " already present."], TRUE, TRUE];
SVError.Blink[];
RETURN[NIL, TRUE, FALSE];
};
IF toolData = NIL THEN toolMasterObject ← NIL
ELSE {
toolName ← NameWithSuffix[name, "$$tool", scene.coordSysRoot];
toolMasterObject ← SVToolObject.ToolMakeMasterObject[toolName, toolData];
};
[masterObject, masterObjectFound] ← FindObjectFromName[object, scene];
IF NOT masterObjectFound THEN RETURN;
IF artwork = NIL THEN artwork ←
SVArtwork.CreateColorArtwork[ImagerColor.ColorFromRGB[[.6,.6,.8]], plastic]; -- light blue
shape ← NEW[ShapeObj];
shape.mo ← masterObject;
We will wire up the shape to a scalars coordinate frame below.
assembly ← NEW[AssemblyObj
[name: name, coordSys: NIL, artwork: artwork, showAs: normal, isTool: isTool, toolMasterObject: toolMasterObject, shape: shape]];
Now wire up the assembly to its parent.
IF ISTYPE[parent.shape, AssemblyList] THEN { -- add to old AssemblyList
alist: AssemblyList ← NARROW[parent.shape];
cs: CoordSystem;
scalarCS: CoordSystem;
cs ← CoordSys.CreateCoordSysInTree[assembly.name, mat, parent.coordSys, scene.coordSysRoot
!CoordSys.NameAlreadyExists => ERROR];
assembly.coordSys ← cs;
scalarName ← NameWithSuffix[assembly.name, "$$Scalars", scene.coordSysRoot];
scalarCS ← CoordSys.CreateScalarsOnlyCoordSysInTree[scalarName, size, cs, scene.coordSysRoot
!CoordSys.NameAlreadyExists => ERROR];
shape.coordSys ← scalarCS;
parent.shape ← AppendToAssemblyList[assembly, alist];
success ← TRUE;
}
ELSE {
SVError.Append["Attempt to add subassembly to primitive.", TRUE, TRUE];
SVError.Blink[];
RETURN[NIL, TRUE, FALSE];
};
};
ConnectAssemblyToParent: PUBLIC PROC [assembly: Assembly, parent: Assembly] = {
IF IsComposite[parent] THEN { -- add to old AssemblyList
alist: AssemblyList ← NARROW[parent.shape];
parent.shape ← AppendToAssemblyList[assembly, alist];
}
ELSE SIGNAL AttemptToAddSubassemblyToPrimitive;
};
CreatePrimitiveAtExistingCoordSys: PUBLIC PROC [name: Rope.ROPE, object: Rope.ROPE, size: Vector, scene: Scene, coordSys: CoordSystem, artwork: Artwork ← NIL, isTool: BOOLFALSE, toolData: ToolData ← NIL] RETURNS [assembly: Assembly, masterObjectFound: BOOL] = {
masterObject: MasterObject;
toolMasterObject: MasterObject;
shape: Shape;
scalarCS: CoordSystem;
toolName, scalarName: Rope.ROPE;
IF toolData = NIL THEN toolMasterObject ← NIL
ELSE {
toolName ← NameWithSuffix[name, "$$tool", scene.coordSysRoot];
toolMasterObject ← SVToolObject.ToolMakeMasterObject[toolName, toolData];
};
[masterObject, masterObjectFound] ← FindObjectFromName[object, scene];
IF NOT masterObjectFound THEN {
SVError.Append[Rope.Cat["Couldn't add assembly ", name, ". Master object ", object, " not found."], TRUE, TRUE];
SVError.Blink[];
};
IF artwork = NIL THEN artwork ←
SVArtwork.CreateColorArtwork[ImagerColor.ColorFromRGB[[.6,.6,.8]], plastic]; -- light blue
shape ← NEW[ShapeObj];
shape.mo ← masterObject;
We will wire up the shape to a scalars coordinate frame below.
assembly ← NEW[AssemblyObj
[name: name, coordSys: NIL, artwork: artwork, showAs: normal, isTool: isTool, toolMasterObject: toolMasterObject, shape: shape]];
Now wire up the assembly to its parent.
assembly.coordSys ← coordSys;
scalarName ← NameWithSuffix[assembly.name, "$$Scalars", scene.coordSysRoot];
scalarCS ← CoordSys.CreateScalarsOnlyCoordSysInTree[scalarName, size, coordSys, scene.coordSysRoot];
shape.coordSys ← scalarCS;
};
CreateAndAddClusterAssembly: PUBLIC PROC [name: Rope.ROPE, pointSetOp: PointSetOp ← union, scene: Scene, parent: Assembly, mat: Matrix4by4, isTool: BOOLFALSE, toolData: ToolData ← NIL] RETURNS [assembly: Assembly, success: BOOL] = {
artwork: Artwork ← SVArtwork.CreateColorArtwork[Imager.white, plastic]; -- white
toolMasterObject: MasterObject;
toolName: Rope.ROPE;
success ← FALSE;
IF AssemblyNameIsPresent[name, scene] THEN {
SVError.Append[Rope.Cat["Composite name ", name, " is already registered. Try another."], TRUE, TRUE];
SVError.Blink[];
RETURN[NIL, FALSE];
};
IF toolData = NIL THEN toolMasterObject ← NIL
ELSE {
toolName ← NameWithSuffix[name, "$$tool", scene.coordSysRoot];
toolMasterObject ← SVToolObject.ToolMakeMasterObject[toolName, toolData];
};
assembly ← NEW[AssemblyObj
[name: name, coordSys: NIL, artwork: artwork, showAs: normal, isTool: isTool,
toolMasterObject: toolMasterObject, shape: NEW[AssemblyListObj ← [NIL, pointSetOp]] ]];
Now wire up the assembly to its parent.
IF IsComposite[parent] THEN{ -- add to old AssemblyList
alist: AssemblyList ← NARROW[parent.shape];
cs: CoordSystem ← CoordSys.CreateCoordSysInTree[assembly.name, mat, parent.coordSys, scene.coordSysRoot];
assembly.coordSys ← cs;
parent.shape ← AppendToAssemblyList[assembly, alist];
}
ELSE {
SVError.Append["Attempt to add subassembly to primitive.", TRUE, TRUE];
SVError.Blink[];
RETURN[NIL, FALSE];
};
};
CreateSceneAssembly: PUBLIC PROC [name: Rope.ROPE, pointSetOp: PointSetOp, coordSys: CoordSystem, isTool: BOOLFALSE, toolData: ToolData ← NIL] RETURNS [assembly: Assembly] = {
artwork: Artwork ← SVArtwork.CreateColorArtwork[Imager.white, plastic]; -- white
toolMasterObject: MasterObject;
toolName, base: Rope.ROPE;
num: NAT;
IF toolData = NIL THEN toolMasterObject ← NIL
ELSE {
[base, num] ← CoordSys.BaseAndNumber[name];
IF num > 0 THEN toolName ← Rope.Cat[base, "$$tool.", IO.PutFR["%g", [integer[num]]]]
ELSE toolName ← Rope.Concat[base, "$$tool"];
toolMasterObject ← SVToolObject.ToolMakeMasterObject[toolName, toolData];
};
assembly ← NEW[AssemblyObj ←
[name: name, coordSys: NIL, artwork: artwork, showAs: normal, isTool: isTool,
toolMasterObject: toolMasterObject, shape: NEW[AssemblyListObj ← [NIL, pointSetOp]] ]];
assembly.coordSys ← coordSys;
};
CreateClusterAssemblyAtExistingCoordSys: PUBLIC PROC [name: Rope.ROPE, pointSetOp: PointSetOp, scene: Scene, coordSys: CoordSystem, isTool: BOOLFALSE, toolData: ToolData ← NIL] RETURNS [assembly: Assembly] = {
artwork: Artwork ← SVArtwork.CreateColorArtwork[Imager.white, plastic]; -- white
toolMasterObject: MasterObject;
toolName: Rope.ROPE;
IF toolData = NIL THEN toolMasterObject ← NIL
ELSE {
toolName ← NameWithSuffix[name, "$$tool", scene.coordSysRoot];
toolMasterObject ← SVToolObject.ToolMakeMasterObject[toolName, toolData];
};
assembly ← NEW[AssemblyObj ←
[name: name, coordSys: NIL, artwork: artwork, showAs: normal,
shape: NEW[AssemblyListObj ← [NIL, pointSetOp] ], isTool: isTool, toolMasterObject: toolMasterObject]];
assembly.coordSys ← coordSys;
};
AttemptToAddSubassemblyToPrimitive: PUBLIC SIGNAL = CODE;
CreateToolData: PUBLIC PROC [loX, hiX, loY, hiY, loZ, hiZ: REAL, plane: NAT, infinite: BOOLFALSE, clientData: REF ANYNIL] RETURNS [toolData: ToolData] = {
plane = 1, 2, 3 corresponds to the x=0, y=0, and z=0 planes respectively. plane = 4 means all three of them. ToolDatas are needed by CreatePrimitiveAssembly and CreateClusterAssembly above if the assembly is to be a tool.
block: FrameBlock ← NEW[FrameBlockObj ← [loX, hiX, loY, hiY, loZ, hiZ]];
toolData ← NEW[ToolDataObj ← [block, infinite, plane, clientData]];
};
CreateAmbientLightSource: PUBLIC PROC [name: Rope.ROPE, color: Color] RETURNS [ls: LightSource] = {
ls ← NEW[LightSourceObj ← [name, [0,0,0], color, ambient]];
};
CreateLightSource: PUBLIC PROC [name: Rope.ROPE, position: Point3d, color: Color] RETURNS [ls: LightSource] = {
ls ← NEW[LightSourceObj ← [name, position, color, point]];
};
CreateFileCamera: PUBLIC PROC [name: Rope.ROPE, origin: Point3d, focusPoint: Point3d, slant: REAL, resolution: REAL, focalLength: REAL, projection: Projection, frame: FrameBox, clippingPlanes: LIST OF Plane, visibleAssemblies: LIST OF Rope.ROPE] RETURNS [fileCamera: FileCamera] = {
fileCamera ← NEW[FileCameraObj ← [name, origin, focusPoint, slant, resolution, focalLength, projection, frame, clippingPlanes, visibleAssemblies]];
};
CreateCamera: PUBLIC PROC [worldCS: CoordSystem, screenCS: CoordSystem] RETURNS [camera: Camera] = {
Must be done whenever a new scene is to be viewed (including whenever a solidviewer is created. Adding the camera to the scene tree is probably one of the first acts after creating a new coordinate system tree.
cameraName: Rope.ROPE ← CoordSys.UniqueNameFrom["Camera", worldCS];
coordSys: CoordSystem ← CoordSys.CreateCoordSysInTree[name: cameraName, mat: Matrix3d.Identity[], parent: worldCS, root: worldCS]; -- to start with
resolution: REAL ← 72.0;
focalLength: REAL ← 1800.0;
projection: Projection ← perspective;
frame: FrameBox ← NIL;
clippingPlanes: LIST OF Plane ← NIL;
visibleAssemblies: LIST OF Rope.ROPENIL;
style: DrawStyle ← wire;
colorFilm: BOOLTRUE;
useBoundBoxes: BOOLTRUE;
useBoundSpheresForShadows: BOOLTRUE;
camera ← CSGGraphics.CreateCamera["NoPlace", coordSys, screenCS, resolution, focalLength, projection, frame, clippingPlanes, visibleAssemblies, style, colorFilm, useBoundBoxes, useBoundSpheresForShadows];
};
StuffCameraFromFileCamera: PUBLIC PROC [camera: Camera, fileCamera: FileCamera, style: DrawStyle] = {
A conversion from the viewer-independent to the viewer-dependent type of camera. Must be done whenever camera name (Front, Top, etc) or changes (and thus whenever the scene changes).
camera.viewName ← fileCamera.name;
camera.resolution ← fileCamera.resolution;
camera.focalLength ← fileCamera.focalLength;
camera.projection ← fileCamera.projection;
camera.frame ← fileCamera.frame;
camera.clippingPlanes ← fileCamera.clippingPlanes;
camera.visibleAssemblies ← fileCamera.visibleAssemblies;
camera.style ← style;
CSGGraphics.PlaceCamera[camera, fileCamera.focusPoint, fileCamera.origin, fileCamera.slant];
};
InitialCameraList: PUBLIC PROC [] RETURNS [cameras: FileCameraList] = {
An initial list of cameras provided with a new scene (or an old scene which was made before named file cameras were introduced).
topMat, bottomMat, leftMat, rightMat, frontMat, upLeftMat, upRightMat: Matrix4by4;
top, bottom, left, right, front, upLeft, upRight: FileCamera;
defaultFocalLength: REAL = 1800;
defaultResolution: REAL ← 72.0;
frame: FrameBox ← NEW[FrameBoxObj ← [[0,0], [0,0], TRUE]];
hither: Plane ← SVPolygon3d.PlaneFromPointAndNormal[[0,0,0], [0,0,1]];
sAList: LIST OF Rope.ROPELIST["sceneAssembly"];
topMat ← Matrix3d.MatMult[Matrix3d.MakeRotateXMat[90], Matrix3d.MakeTranslateMat[0,0,1800]];
bottomMat ← Matrix3d.MatMult[Matrix3d.MakeRotateXMat[-90], Matrix3d.MakeTranslateMat[0,0,1800]];
leftMat ← Matrix3d.MatMult[Matrix3d.MakeRotateYMat[-90], Matrix3d.MakeTranslateMat[0,0,1800]];
rightMat ← Matrix3d.MatMult[Matrix3d.MakeRotateYMat[90], Matrix3d.MakeTranslateMat[0,0,1800]];
frontMat ← Matrix3d.MakeTranslateMat[0,0,1800];
upLeftMat ← Matrix3d.MatMult[Matrix3d.MakeRotateYMat[-20], Matrix3d.MakeTranslateMat[0,0,1800]];
upLeftMat ← Matrix3d.MatMult[Matrix3d.MakeRotateXMat[20], upLeftMat];
upRightMat ← Matrix3d.MatMult[Matrix3d.MakeRotateYMat[20], Matrix3d.MakeTranslateMat[0,0,1800]];
upRightMat ← Matrix3d.MatMult[Matrix3d.MakeRotateXMat[20], upRightMat];
top ← CreateFileCamera[name: "Top", origin: [0,1800,0], focusPoint: [0,0,0], slant: 0, resolution: defaultResolution, focalLength: defaultFocalLength, projection: perspective, frame: frame, clippingPlanes: LIST[hither], visibleAssemblies: sAList];
bottom ← CreateFileCamera[name: "Bottom", origin: [0,-1800,0], focusPoint: [0,0,0], slant: 0, resolution: defaultResolution, focalLength: defaultFocalLength, projection: perspective, frame: frame, clippingPlanes: LIST[hither], visibleAssemblies: sAList];
left ← CreateFileCamera[name: "Left", origin: [-1800,0,0], focusPoint: [0,0,0], slant: 0, resolution: defaultResolution, focalLength: defaultFocalLength, projection: perspective, frame: frame, clippingPlanes: LIST[hither], visibleAssemblies: sAList];
right ← CreateFileCamera[name: "Right", origin: [1800,0,0], focusPoint: [0,0,0], slant: 0, resolution: defaultResolution, focalLength: defaultFocalLength, projection: perspective, frame: frame, clippingPlanes: LIST[hither], visibleAssemblies: sAList];
front ← CreateFileCamera[name: "Front", origin: [0,0,1800], focusPoint: [0,0,0], slant: 0, resolution: defaultResolution, focalLength: defaultFocalLength, projection: perspective, frame: frame, clippingPlanes: LIST[hither], visibleAssemblies: sAList];
upLeft ← CreateFileCamera[name: "UpLeft", origin: [-600,1200,1800], focusPoint: [0,0,0], slant: 0, resolution: defaultResolution, focalLength: defaultFocalLength, projection: perspective, frame: frame, clippingPlanes: LIST[hither], visibleAssemblies: sAList];
upRight ← CreateFileCamera[name: "UpRight", origin: [600,1200,1800], focusPoint: [0,0,0], slant: 0, resolution: defaultResolution, focalLength: defaultFocalLength, projection: perspective, frame: frame, clippingPlanes: LIST[hither], visibleAssemblies: sAList];
cameras ← LIST[top, bottom, left, right, front, upLeft, upRight];
};
Build the Scene Tree
NameAlreadyPresent: PUBLIC SAFE SIGNAL = CODE;
AddMasterObjectToScene: PUBLIC PROC [mo: MasterObject, scene: Scene] = {
IF ObjectNameIsPresent[mo.name, scene] THEN SIGNAL NameAlreadyPresent;
scene.masterObjects ←
AppendToMasterObjects[mo, scene.masterObjects];
};
AddLightSourceToScene: PUBLIC PROC [ls: LightSource, scene: Scene] = {
IF LightSourceNameIsPresent[ls.name, scene] THEN SIGNAL NameAlreadyPresent;
scene.lightSources ← AppendToLightSourceList[ls, scene.lightSources];
};
AddCameraToScene: PUBLIC PROC [fileCamera: FileCamera, scene: Scene] = {
IF FileCameraNameIsPresent[fileCamera.name, scene] THEN SIGNAL NameAlreadyPresent;
scene.cameras ← AppendToFileCameraList[fileCamera, scene.cameras];
};
AddCameraOrderNameToScene: PUBLIC PROC [name: Rope.ROPE, scene: Scene] = {
The names of those cameras which should open automatically with the pic file is loaded are added to the scene in order.
IF CameraOrderNameIsPresent[name, scene] THEN SIGNAL NameAlreadyPresent;
scene.cameraOrder ← AppendToCameraOrderList[name, scene.cameraOrder];
};
AddOrResizeToolToAssembly: PUBLIC PROC [assembly: Assembly, scene: Scene] = {
toolMasterObject: MasterObject;
toolData: SVToolObject.ToolData;
toolName: Rope.ROPE;
IF assembly.toolMasterObject = NIL THEN {
toolData ← DisplayList3d.CreateToolData[-100, 100, -100, 100, -100, 100, 3, FALSE];
This is just a default size. It is resized below.
toolName ← NameWithSuffix[assembly.name, "$$tool", scene.coordSysRoot];
toolMasterObject ← SVToolObject.ToolMakeMasterObject[toolName, toolData];
assembly.toolMasterObject ← toolMasterObject;
};
toolData ← NARROW[assembly.toolMasterObject.mainBody];
SVToolObject.SizeToFit[toolData, assembly];
};
List Append Auxiliaries For the Add Procedures
AppendToDatabase: PROC [scene: Scene, database: Database] RETURNS [Database] = {
A copy of List.Nconc1 for LIST OF Scene instead of LIST OF REF ANY
z: LIST OF Scene ← database.scenes;
IF z = NIL THEN {database.scenes ← CONS[scene,NIL]; RETURN[database]};
UNTIL z.rest = NIL DO z ← z.rest; ENDLOOP;
z.rest ← CONS[scene,NIL];
RETURN[database];
};
AppendToAssemblyList: PROC [assembly: Assembly, list: AssemblyList] RETURNS [AssemblyList] = {
A copy of List.Nconc1 for LIST OF Assembly instead of LIST OF REF ANY
z: LIST OF Assembly ← list.list;
IF z = NIL THEN {list.list ← CONS[assembly, NIL]; RETURN[list]};
UNTIL z.rest = NIL DO z ← z.rest; ENDLOOP;
z.rest ← CONS[assembly,NIL];
RETURN[list];
};
AppendToLightSourceList: PROC [ls: LightSource, list: LightSourceList] RETURNS [LightSourceList] = {
A copy of List.Nconc1 for LightSourceList instead of LIST OF REF ANY
z: LightSourceList ← list;
IF z = NIL THEN RETURN[CONS[ls,NIL]];
UNTIL z.rest = NIL DO z ← z.rest; ENDLOOP;
z.rest ← CONS[ls,NIL];
RETURN[list];
};
AppendToFileCameraList: PROC [fileCamera: FileCamera, list: FileCameraList] RETURNS [FileCameraList] = {
A copy of List.Nconc1 for CoordSysList instead of LIST OF REF ANY
z: FileCameraList ← list;
IF z = NIL THEN RETURN[CONS[fileCamera,NIL]];
UNTIL z.rest = NIL DO z ← z.rest; ENDLOOP;
z.rest ← CONS[fileCamera,NIL];
RETURN[list];
};
AppendToCameraOrderList: PROC [name: Rope.ROPE, list: LIST OF Rope.ROPE] RETURNS [LIST OF Rope.ROPE] = {
A copy of List.Nconc1 for LIST OF Rope.ROPE instead of LIST OF REF ANY
z: LIST OF Rope.ROPE ← 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];
};
AppendToMasterObjects: PUBLIC PROC [mo: MasterObject, list: MasterObjectList] RETURNS [MasterObjectList] = {
A copy of List.Nconc1 for MasterObjectList instead of LIST OF REF ANY
z: MasterObjectList ← list;
IF z = NIL THEN RETURN[CONS[mo,NIL]];
UNTIL z.rest = NIL DO z ← z.rest; ENDLOOP;
z.rest ← CONS[mo,NIL];
RETURN[list];
};
AppendClassToList: PROC [moc: MasterObjectClass, list: MasterObjectClassList] RETURNS [MasterObjectClassList] = {
A copy of List.Nconc1 for MasterObjectClassList instead of LIST OF REF ANY
z: MasterObjectClassList ← list;
IF z = NIL THEN RETURN[CONS[moc,NIL]];
UNTIL z.rest = NIL DO z ← z.rest; ENDLOOP;
z.rest ← CONS[moc,NIL];
RETURN[list];
};
Restructure the Tree
RenameAssembly: PUBLIC PROC [assem: Assembly, newName: Rope.ROPE, scene: Scene] = {
Rename this assembly and its coordinate system.
assem.name ← newName;
assem.coordSys.name ← newName;
};
IsComposite: PROC [assem: Assembly] RETURNS [BOOL] = {
RETURN[ISTYPE [assem.shape, AssemblyList] OR assem.shape = NIL];
};
MoveSubassembly: PUBLIC PROC [assem: Assembly, to: Assembly, scene: Scene] = {
Find assem's parent. Remove links from parent to assem. Create links from 'to' to assem. Likewise, assem's coordsys must now refer to the new parent's coordsys. Alter assem's coordinate system matrix so its doesn't actually move at all.
assemWithSameName, parent: Assembly;
parentList: AssemblyList;
found: BOOL;
toCS: CoordSystem ← to.coordSys;
[assemWithSameName, parent] ← FindAssemblyFromName[assem.name, scene];
IF assemWithSameName # assem THEN ERROR;
IF NOT IsComposite[to] THEN SIGNAL AttemptToAddSubassemblyToPrimitive;
Remove links from parent to assembly.
parentList ← NARROW[parent.shape];
[parent.shape, found] ← DisplayList3dPrivate.TemporaryRemoveFromAssemblyList[assem, parentList, scene];
IF NOT found THEN ERROR;-- it was found just a few lines ago. What happened?
Remove links from assem's coordsys to parent by pointing to new parent's CS. And update assem's coordsys's matrix so it doesn't actually move.
[] ← CoordSys.PutAInTermsOfB[assem.coordSys, to.coordSys];
Create link from 'to' to assem.
to.shape ← AppendToAssemblyList[assem, NARROW[to.shape]]
}; -- end of MoveSubassembly
MoveToFrontOfAssembly: PUBLIC PROC [subassembly: Assembly, assembly: Assembly, scene: Scene] = {
Moves subassembly to the first position of assembly's assemblylist.
Make sure "subassembly" is a subassembly of "assembly".
aList: AssemblyList ← NARROW[assembly.shape];
success: BOOLFALSE;
FOR list: LIST OF Assembly ← aList.list, list.rest UNTIL list = NIL DO
IF list.first = subassembly THEN success←TRUE;
ENDLOOP;
IF NOT success THEN ERROR SubassemblyNotFound;
[aList, success] ← DisplayList3dPrivate.TemporaryRemoveFromAssemblyList[subassembly, aList, scene];
IF NOT success THEN ERROR SubassemblyNotFound;
aList.list ← CONS[subassembly, aList.list];
};
SubassemblyNotFound: PUBLIC ERROR = CODE;
MergeAssemblyIntoScene: PUBLIC PROC [originalAssembly: Assembly, fromScene: Scene, parentAssembly: Assembly, toScene: Scene] RETURNS [copyAssembly: Assembly] = {
Copies over any master objects which toScene will need to support newAssembly. Makes a copy of the newAssembly tree, adding suffix numbers to make the names unique in the new scene. Wires up the new assembly to its parent.
copyAssembly ← DisplayList3d.CopyAssemblyAndSonsUniqueNames [assembly: originalAssembly, oldScene: fromScene, newScene: toScene, parent: parentAssembly];
};
MergeSceneIntoScene: PUBLIC PROC [fromScene: Scene, toScene: Scene] RETURNS [success: BOOL] = {
Takes all of the assemblies from fromScene which are directly under sceneAssembly and adds them to the sceneAssembly of toScene. Makes sure that all assemblies in fromScene have names unique in toScene first.
fromList: AssemblyList ← NARROW[fromScene.assembly.shape];
toSceneAssembly: Assembly ← toScene.assembly;
FOR list: LIST OF Assembly ← fromList.list, list.rest UNTIL list = NIL DO
[] ← MergeAssemblyIntoScene[list.first, fromScene, toSceneAssembly, toScene];
ENDLOOP;
};
AddCoordSystemsInAssemblyToScene: PRIVATE PROC [assembly: Assembly, scene: Scene] = {
WITH assembly.object SELECT FROM
alist: AssemblyList => {
AddCoordSysToScene[assembly.coordSys, scene];
AddCoordSystemsInAssemblyListToScene[alist, scene];
};
mo: MasterObject =>
AddCoordSysToScene[assembly.coordSys, scene];
ENDCASE => ERROR;
};
AddCoordSystemsInAssemblyListToScene: PRIVATE PROC [assemblyList: AssemblyList, scene: Scene] = {
FOR list: LIST OF Assembly ← assemblyList.list, list.rest UNTIL list = NIL DO
AddCoordSystemsInAssemblyToScene[list.first, scene];
ENDLOOP;
};
SetArtworkAssembly: PUBLIC PROC [assembly: Assembly, artwork: Artwork, scene: Scene] = {
FOR list: LIST OF Assembly ← ListOfPrimAssemblies[assembly, scene], list.rest
UNTIL list = NIL DO
list.first.artwork ← artwork;
ENDLOOP;
};
Find Scene Entities from their Names
FindSceneFromName: PUBLIC PROC [name: Rope.ROPE] RETURNS [scene: Scene] = {
l: LIST OF Scene ← globalDatabase.scenes;
IF l = NIL THEN ERROR DatabaseEmpty;
UNTIL l = NIL DO
IF Rope.Equal[l.first.name, name, FALSE] THEN BEGIN scene ← l.first; RETURN END;
l ← l.rest;
ENDLOOP;
SIGNAL SceneNotFound;
};
DatabaseEmpty: PUBLIC SIGNAL = CODE;
SceneNotFound: PUBLIC SIGNAL = CODE;
FindAssemblyFromName: PUBLIC PROC [name: Rope.ROPE, scene: Scene] RETURNS [assembly: Assembly, superAssembly: Assembly] = {
Finds the named assembly and its immediate superior. superAssembly is NIL if assembly is top level.
t: Assembly ← scene.assembly;
success: BOOL;
[assembly, superAssembly, success] ← FindAssemblyInTree[name, t, NIL];
IF success = FALSE THEN SIGNAL AssemblyNotFound;
};
AssemblyNotFound: PUBLIC SIGNAL = CODE;
AssemblyNameIsPresent: PUBLIC PROC [name: Rope.ROPE, scene: Scene] RETURNS [BOOL] = {
dummy1, dummy2: Assembly;
isPresent: BOOL;
[dummy1, dummy2, isPresent] ← FindAssemblyInTree[name, scene.assembly, NIL];
RETURN[isPresent];
};
FindAssemblyInTree: PRIVATE PROC [name: Rope.ROPE, t: Assembly, super: Assembly] RETURNS [assembly: Assembly, superAssembly: Assembly, success: BOOL] = {
IF t = NIL THEN RETURN[NIL,NIL,FALSE];
IF Rope.Equal[t.name, name] THEN RETURN[t, super, TRUE];
WITH t.shape SELECT FROM
as: AssemblyList => {
FOR l: LIST OF Assembly ← as.list, l.rest UNTIL l = NIL DO
[assembly, superAssembly, success] ← FindAssemblyInTree[name, l.first, t];
IF success THEN RETURN;
ENDLOOP;
RETURN [NIL, NIL, FALSE];
};
ENDCASE => -- t is a primitive assembly with the wrong name
RETURN[NIL,NIL,FALSE];
};
AnyNamesAlreadyPresent: PUBLIC PROC [assembly: Assembly, scene: Scene] RETURNS [BOOL] = {
IF AssemblyNameIsPresent[assembly.name, scene] THEN RETURN [TRUE];
WITH assembly.shape SELECT FROM
shape: Shape => RETURN[FALSE];
aList: AssemblyList => RETURN[AnyNamesAlreadyPresentInList[aList, scene]];
ENDCASE => RETURN[FALSE];
};
AnyNamesAlreadyPresentInList: PRIVATE PROC [assemblyList: AssemblyList, scene: Scene] RETURNS [BOOL] = {
FOR list: LIST OF Assembly ← assemblyList.list, list.rest UNTIL list = NIL DO
IF AnyNamesAlreadyPresent[list.first, scene] THEN RETURN [TRUE];
ENDLOOP;
RETURN [FALSE];
};
FindClassFromName: PUBLIC PROC [name: Rope.ROPE] RETURNS [moClass: MasterObjectClass, success: BOOL] = {
FOR moClassList: MasterObjectClassList ← globalClassList, moClassList.rest
UNTIL moClassList = NIL DO
IF Rope.Equal[moClassList.first.name, name, TRUE] THEN RETURN [moClassList.first, TRUE];
ENDLOOP;
RETURN[NIL, FALSE];
};
FindObjectFromName: PUBLIC PROC [name: Rope.ROPE, scene: Scene] RETURNS [object: MasterObject, success: BOOL] = {
FOR ol: MasterObjectList ← scene.masterObjects, ol.rest UNTIL ol = NIL DO
IF Rope.Equal[ol.first.name, name, TRUE] THEN RETURN [ol.first, TRUE];
ENDLOOP;
RETURN[NIL, FALSE];
};
ObjectNameIsPresent: PUBLIC PROC [name: Rope.ROPE, scene: Scene] RETURNS [BOOL] = {
FOR ol: MasterObjectList ← scene.masterObjects, ol.rest UNTIL ol = NIL DO
IF Rope.Equal[ol.first.name, name, TRUE] THEN RETURN [TRUE];
ENDLOOP;
RETURN[FALSE];
};
CoordSysNameIsPresent: PUBLIC PROC [name: Rope.ROPE, scene: Scene] RETURNS [BOOL] = {
RETURN[CoordSys.CoordSysNameIsPresent[name, scene.coordSysRoot]];
};
FindLightFromName: PUBLIC PROC [name: Rope.ROPE, scene: Scene] RETURNS [light: LightSource, success: BOOL] = {
FOR list: LightSourceList ← scene.lightSources, list.rest UNTIL list = NIL DO
IF Rope.Equal[list.first.name, name, TRUE] THEN RETURN [list.first, TRUE];
ENDLOOP;
RETURN [NIL, FALSE];
};
LightSourceNameIsPresent: PUBLIC PROC [name: Rope.ROPE, scene: Scene] RETURNS [BOOL] = {
FOR ll: LightSourceList ← scene.lightSources, ll.rest UNTIL ll = NIL DO
IF Rope.Equal[ll.first.name, name, TRUE] THEN RETURN [TRUE];
ENDLOOP;
RETURN[FALSE];
};
FindFileCameraFromName: PUBLIC PROC [name: Rope.ROPE, scene: Scene] RETURNS [fileCamera: FileCamera, success: BOOL] = {
FOR list: FileCameraList ← scene.cameras, list.rest UNTIL list = NIL DO
IF Rope.Equal[list.first.name, name, TRUE] THEN RETURN [list.first, TRUE];
ENDLOOP;
RETURN [NIL, FALSE];
};
FileCameraNameIsPresent: PUBLIC PROC [name: Rope.ROPE, scene: Scene] RETURNS [BOOL] = {
FOR list: FileCameraList ← scene.cameras, list.rest UNTIL list = NIL DO
IF Rope.Equal[list.first.name, name, TRUE] THEN RETURN [TRUE];
ENDLOOP;
RETURN[FALSE];
};
CameraOrderNameIsPresent: PUBLIC PROC [name: Rope.ROPE, scene: Scene] RETURNS [BOOL] = {
FOR list: LIST OF Rope.ROPE ← scene.cameraOrder, list.rest UNTIL list = NIL DO
IF Rope.Equal[list.first, name, TRUE] THEN RETURN [TRUE];
ENDLOOP;
RETURN[FALSE];
};
UniqueObjectNameFrom: PUBLIC PROC [name: Rope.ROPE, scene: Scene] RETURNS [unique: Rope.ROPE] = {
Finds any digits on the end of the name. Looks through the scene extracting a digit and base name from each name. Finds the maximum number, adds one, reconcatenates and returns.
maxNum: NAT ← 0;
targetBase, base: Rope.ROPE;
targetNum, num: NAT;
[targetBase, targetNum] ← CoordSys.BaseAndNumber[name];
FOR ol: MasterObjectList ← scene.masterObjects, ol.rest UNTIL ol = NIL DO
[base, num] ← CoordSys.BaseAndNumber[ol.first.name];
IF Rope.Equal[base, targetBase, TRUE] THEN maxNum ← MAX[num, maxNum];
ENDLOOP;
unique ← IO.PutFR["%g.%g",[rope[targetBase]], [integer[maxNum+1]]];
};
UniqueAssemblyNameFrom: PUBLIC PROC [name: Rope.ROPE, scene: Scene] RETURNS [unique: Rope.ROPE] = {
Finds any digits on the end of the name. Looks through the scene extracting a digit and base name from each name. Finds the maximum number, adds one, reconcatenates and returns.
maxNum: NAT ← 0;
targetBase, base: Rope.ROPE;
g: AssemblyGenerator ← GetAssemblyGenerator[scene];
targetNum, num: NAT;
[targetBase, targetNum] ← BaseAndNumber[name];
FOR assem: Assembly ← NextAssembly[g], NextAssembly[g] UNTIL assem = NIL DO
[base, num] ← BaseAndNumber[assem.name];
IF Rope.Equal[base, targetBase, TRUE] THEN maxNum ← MAX[num, maxNum];
ENDLOOP;
unique ← IO.PutFR["%g.%g",[rope[targetBase]], [integer[maxNum+1]]];
};
FindMasterObjectAndNeighborsFromName: PUBLIC PROC [moName: Rope.ROPE, moList: MasterObjectList] RETURNS [beforeMo, mo, afterMo: MasterObjectList, found: BOOL] = {
returns found = FALSE if that is the case.
lastL: MasterObjectList ← NIL;
l: MasterObjectList ← moList;
found ← TRUE;
IF l = NIL THEN RETURN[NIL, NIL, NIL, FALSE];
UNTIL l = NIL DO
IF Rope.Equal[l.first.name, moName, TRUE] THEN {
beforeMo ← lastL; mo ← l; afterMo ← l.rest; RETURN};
lastL ← l;
l ← l.rest;
ENDLOOP;
RETURN[NIL, NIL, NIL, FALSE];
};
FindLightSourceAndNeighborsFromName: PUBLIC PROC [lsName: Rope.ROPE, lsList: LightSourceList] RETURNS [beforeLS, ls, afterLS: LightSourceList] = {
Signals LightSourceNotFound if that is the case.
lastL: LightSourceList ← NIL;
l: LightSourceList ← lsList;
IF l = NIL THEN ERROR LightSourceNotFound;
UNTIL l = NIL DO
IF Rope.Equal[l.first.name, lsName] THEN {
beforeLS ← lastL; ls ← l; afterLS ← l.rest; RETURN};
lastL ← l;
l ← l.rest;
ENDLOOP;
SIGNAL LightSourceNotFound;
};
LightSourceNotFound: PUBLIC SIGNAL = CODE;
Get Generators of Scene Entities
Scene Generator
GetSceneGenerator: PUBLIC PROC RETURNS [g: SceneGenerator] = {
g ← NEW[SceneGeneratorObj ← [currentPtr: globalDatabase.scenes]];
};
SceneGenerator: TYPE = REF SceneGeneratorObj;
SceneGeneratorObj: TYPE = DisplayList3d.SceneGeneratorObj;
NextScene: PUBLIC PROC [g: SceneGenerator] RETURNS [scene: Scene] = {
IF g.currentPtr = NIL THEN RETURN[NIL];
scene ← g.currentPtr.first;
g.currentPtr ← g.currentPtr.rest;
};
CoordSystem Generator
GetCoordSysGenerator: PUBLIC PROC [scene: Scene] RETURNS [g: CoordSysGenerator] = {
g ← NEW[CoordSysGeneratorObj ← [currentPtr: CoordSys.MakeListFromTree[scene.coordSysRoot]]];
};
CoordSysGenerator: TYPE = REF CoordSysGeneratorObj;
CoordSysGeneratorObj: TYPE = DisplayList3d.CoordSysGeneratorObj;
NextCoordSys: PUBLIC PROC [g: CoordSysGenerator] RETURNS [cs: CoordSystem] = {
IF g.currentPtr = NIL THEN RETURN[NIL];
cs ← g.currentPtr.first;
g.currentPtr ← g.currentPtr.rest;
};
Assembly Generator
GetListOfAssembliesFromScene: PRIVATE PROC [scene: Scene] RETURNS [aList: LIST OF Assembly] = {
aList ← GetListOfAssembliesFromAssembly[scene.assembly];
};
GetListOfAssembliesFromAssembly: PRIVATE PROC [assem: Assembly] RETURNS [aList: LIST OF Assembly] = {
aList ← NIL;
WITH assem.shape SELECT FROM
al: AssemblyList => aList ← CONS[assem, GetListOfAssembliesFromAssemblyList[al]];
ENDCASE => aList ← CONS[assem, NIL];
};
GetListOfAssembliesFromAssemblyList: PRIVATE PROC [al: AssemblyList] RETURNS [aList: LIST OF Assembly] = {
aList ← NIL;
FOR list: LIST OF Assembly ← al.list, list.rest UNTIL list = NIL DO
aList ← AppendDestructiveAssemblies[aList, GetListOfAssembliesFromAssembly[list.first]];
ENDLOOP;
};
AppendDestructiveAssemblies: PRIVATE PROC [list1, list2: LIST OF Assembly] RETURNS [LIST OF Assembly] = {
list: LIST OF Assembly;
IF list1 = NIL THEN RETURN [list2];
list ← list1;
UNTIL list.rest = NIL DO
list ← list.rest;
ENDLOOP;
list.rest ← list2;
RETURN[list1];
}; -- end of AppendDestructiveAssemblies
GetAssemblyGenerator: PUBLIC PROC [scene: Scene] RETURNS [g: AssemblyGenerator] = {
A pretty dumb generator. Walks the tree, makes the whole list and then feeds it to you one item at a time.
aList: LIST OF Assembly ← GetListOfAssembliesFromScene[scene];
g ← NEW[AssemblyGeneratorObj ← [currentPtr: aList]];
};
AssemblyGenerator: TYPE = REF AssemblyGeneratorObj;
AssemblyGeneratorObj: TYPE = DisplayList3d.AssemblyGeneratorObj;
NextAssembly: PUBLIC PROC [g: AssemblyGenerator] RETURNS [a: Assembly] = {
IF g.currentPtr = NIL THEN RETURN[NIL];
a ← g.currentPtr.first;
g.currentPtr ← g.currentPtr.rest;
};
LightSource Generator
GetLightSourceGenerator: PUBLIC PROC [scene: Scene] RETURNS [g: LightSourceGenerator] = {
g ← NEW[LightSourceGeneratorObj ← [currentPtr: scene.lightSources]];
};
LightSourceGenerator: TYPE = REF LightSourceGeneratorObj;
LightSourceGeneratorObj: TYPE = DisplayList3d.LightSourceGeneratorObj;
NextLight: PUBLIC PROC [g: LightSourceGenerator] RETURNS [ls: LightSource] = {
IF g.currentPtr = NIL THEN RETURN[NIL];
ls ← g.currentPtr.first;
g.currentPtr ← g.currentPtr.rest;
};
MasterObject Generator
MasterObjectsOfScene: PUBLIC PROC [scene: Scene] RETURNS [l: MasterObjectList] = {
l ← scene.masterObjects;
};
MasterObjectsOfAssembly: PUBLIC PROC [assembly: Assembly, scene: Scene] RETURNS [l: MasterObjectList] = {
Get a list of the leaves of the tree and extract a master object from each. Remove duplicates.
primList: LIST OF Assembly ← ListOfPrimAssemblies[assembly, scene];
thisMO: MasterObject;
thisShape: Shape;
l ← NIL;
FOR list: LIST OF Assembly ← primList, list.rest UNTIL list = NIL DO
thisShape ← NARROW[list.first.shape];
thisMO ← thisShape.mo;
l ← CONS[thisMO, l];
ENDLOOP;
l ← DisplayList3dPrivate.RemoveDuplicateMOs[l];
};
List of Primitive Assemblies
ListOfPrimAssemblies: PUBLIC PROC [assembly: Assembly, scene: Scene] RETURNS [primList: LIST OF Assembly] = {
IF assembly = NIL THEN RETURN[NIL];
WITH assembly.shape SELECT FROM
aList: AssemblyList => primList ← ListOfPrimAssembliesFromAssemblyList[aList.list, scene];
shape: Shape => primList ← CONS[assembly, NIL];
ENDCASE => ERROR;
};
ListOfPrimAssembliesFromAssemblyList: PRIVATE PROC [aList: LIST OF Assembly, scene: Scene] RETURNS [primList: LIST OF Assembly] = {
thisList: LIST OF Assembly;
IF aList = NIL THEN RETURN[NIL];
thisList ← ListOfPrimAssemblies[aList.first, scene];
IF thisList = NIL THEN primList ← ListOfPrimAssembliesFromAssemblyList[aList.rest, scene]
ELSE primList ← AppendDestructiveAssemblies[thisList,
ListOfPrimAssembliesFromAssemblyList[aList.rest, scene]];
};
Initialization
Init: PROC = {
Create a database.
globalDatabase ← NEW[DatabaseObj ← [scenes: NIL]];
};
Init[];
END.