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;
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], GraphicsColor.red];
defaultGreenLight: LightSource ← CreateLightSource["GreenLight",[-200,200,400], GraphicsColor.green];
ambientLight: LightSource ← CreateAmbientLightSource["Ambient", GraphicsColor.RGBToColor[0.2,0.2,0.2]];
defaultWhiteLight: LightSource ← CreateLightSource["WhiteLight",[800,800,1000],GraphicsColor.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: GraphicsColor.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: GraphicsColor.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:
BOOL ←
FALSE, 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[GraphicsColor.RGBToColor[.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:
BOOL ←
FALSE, 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[GraphicsColor.RGBToColor[.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:
BOOL ←
FALSE, toolData: ToolData ←
NIL]
RETURNS [assembly: Assembly, success:
BOOL] = {
artwork: Artwork ← SVArtwork.CreateColorArtwork[GraphicsColor.IntensityToColor[1], 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:
BOOL ←
FALSE, toolData: ToolData ←
NIL]
RETURNS [assembly: Assembly] = {
artwork: Artwork ← SVArtwork.CreateColorArtwork[GraphicsColor.IntensityToColor[1], 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:
BOOL ←
FALSE, toolData: ToolData ←
NIL]
RETURNS [assembly: Assembly] = {
artwork: Artwork ← SVArtwork.CreateColorArtwork[GraphicsColor.IntensityToColor[1], 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:
BOOL ←
FALSE, clientData:
REF
ANY ←
NIL]
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.ROPE ← NIL;
style: DrawStyle ← wire;
colorFilm: BOOL ← TRUE;
useBoundBoxes: BOOL ← TRUE;
useBoundSpheresForShadows: BOOL ← TRUE;
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.ROPE ← LIST["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];
};
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]];
};