Imported Types
Camera: TYPE = SVModelTypes.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;
FileCamera: TYPE = REF FileCameraObj;
FileCameraObj: TYPE = SVSceneTypes.FileCameraObj;
FileCameraList: TYPE = SVSceneTypes.FileCameraList;
FrameBox: TYPE = SVSceneTypes.FrameBox;
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;
Ray: TYPE = SVRayTypes.Ray;
Shape: TYPE = SVSceneTypes.Shape;
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;
Artwork: TYPE = SVModelTypes.Artwork;
Assembly: TYPE = REF AssemblyObj;
AssemblyObj: TYPE = SVSceneTypes.AssemblyObj;
ToolData: TYPE = REF ToolDataObj;
ToolDataObj: TYPE = SVSceneTypes.ToolDataObj;
AssemblyList: TYPE = REF AssemblyListObj;
AssemblyListObj: TYPE = SVSceneTypes.AssemblyListObj;
LightSource: TYPE = REF LightSourceObj;
LightSourceObj: TYPE = SVModelTypes.LightSourceObj;
LightSourceList: TYPE = SVModelTypes.LightSourceList;
Master Object Class Types
MasterObjectClass: TYPE = REF MasterObjectClassObj;
MasterObjectClassObj: TYPE = SVSceneTypes.MasterObjectClassObj;
MasterObjectClassList: TYPE = SVSceneTypes.MasterObjectClassList;
FileoutProc: TYPE = SVSceneTypes.FileoutProc;
FileinProc: TYPE = SVSceneTypes.FileinProc;
Master Object Types
MasterObject: TYPE = REF MasterObjectRec;
MasterObjectRec: TYPE = SVSceneTypes.MasterObjectRec;
MasterObjectList: TYPE = SVSceneTypes.MasterObjectList;
FileoutPolyProc: TYPE = SVSceneTypes.FileoutPolyProc;
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;
Noop Procedures
A master object can use these entries if it doesn't implement one of these procedures
NoOpFilein: PUBLIC FileinProc = {};
NoOpFileout: PUBLIC FileoutProc = {};
NoOpFileoutPoly: PUBLIC FileoutPolyProc = {};
NoOpRayCast:
PUBLIC RayCastProc = {
class ← CastRays.GetClassFromPool[];
CastRays.MakeClassAMiss[class];
};
NoOpRayCastNoBBoxes:
PUBLIC RayCastNoBBoxesProc = {
class ← CastRays.GetClassFromPool[];
CastRays.MakeClassAMiss[class];
};
NoOpRayCastBoundingSpheres:
PUBLIC RayCastBoundingSpheresProc = {
class ← CastRays.GetClassFromPool[];
CastRays.MakeClassAMiss[class];
};
NoOpBoundHedron: PUBLIC BoundHedronProc = {RETURN[NIL]};
NoOpPreprocess: PUBLIC PreprocessProc = {}; -- don't preprocess anything
NoOpLineDraw: PUBLIC LineDrawProc = {}; -- don't draw anything
NoOpNormalsDraw: PUBLIC NormalsDrawProc = {}; -- don't draw anything
NoOpCountPlanarSurfaces:
PUBLIC CountPlanarSurfacesProc = {
RETURN[0]};
Say you don't have any
NoOpGetPlanarSurfaces:
PUBLIC GetPlanarSurfacesProc = {
RETURN[
NIL]};
Return the empty list
NoOpDrawPlanarSurface: PUBLIC DrawPlanarSurfaceProc = {}; -- don't draw anything
NoOpDrawSubBoxes: PUBLIC DrawSubBoxesProc = {}; -- don't draw anything
NoOpDrawSubSpheres: PUBLIC DrawSubSpheresProc = {}; -- don't draw anything
Delete Parts of the Scene Tree
DeleteMasterObjectNamed:
PUBLIC
PROC [moName: Rope.
ROPE, scene: Scene]
RETURNS [found:
BOOL] = {
mo, beforeMo, afterMo: MasterObjectList;
[beforeMo, mo, afterMo, found] ← DisplayList3dPrivate.FindMasterObjectAndNeighborsFromName[moName, scene.masterObjects];
IF NOT found THEN RETURN;
IF beforeMo = NIL THEN scene.masterObjects ← afterMo
ELSE beforeMo.rest ← afterMo;
}; -- end of DeleteMasterObjectNamed
DeleteMasterObjectIfUnused:
PUBLIC
PROC [mo: MasterObject, scene: Scene]
RETURNS [found:
BOOL] = {
shape: Shape;
For now, we won't delete the built-in instances.
IF Rope.Equal[mo.class.name, "sphere"] OR Rope.Equal[mo.class.name, "block"] OR Rope.Equal[mo.class.name, "cylinder"] OR Rope.Equal[mo.class.name, "cone"] OR Rope.Equal[mo.class.name, "halfSpace"] THEN
RETURN[TRUE];
FOR primitiveAssemblies:
LIST
OF Assembly ←
DisplayList3d.ListOfPrimAssemblies[scene.assembly, scene], primitiveAssemblies.rest
UNTIL primitiveAssemblies =
NIL
DO
shape ← NARROW[primitiveAssemblies.first.shape];
IF shape.mo = mo THEN RETURN[TRUE];
ENDLOOP;
found ← DeleteMasterObjectNamed[mo.name, scene];
}; -- end of DeleteMasterObjectIfUnused
DeleteCoordSysAndChildren:
PUBLIC
PROC [cs: CoordSystem, scene: Scene] = {
CoordSys.DeleteCoordSysAndChildren[cs, scene.coordSysRoot];
}; -- end of DeleteCoordSysNamed
DeleteLightSourceNamed:
PUBLIC
PROC [lsName: Rope.
ROPE, scene: Scene] = {
ls, beforeLS, afterLS: LightSourceList;
notFound: BOOL ← FALSE;
[beforeLS, ls, afterLS] ← DisplayList3dPrivate.FindLightSourceAndNeighborsFromName[lsName, scene.lightSources
!DisplayList3dPrivate.LightSourceNotFound => {notFound ← TRUE; CONTINUE}];
IF notFound THEN RETURN;
IF beforeLS = NIL THEN scene.lightSources ← afterLS
ELSE beforeLS.rest ← afterLS;
}; -- end of DeleteLightSourceNamed
ClearScene:
PUBLIC
PROC [scene: Scene] = {
scene.assembly.shape ← NEW[AssemblyListObj ← [NIL, union] ];
ClearCoordSystems[scene];
ClearMasterObjects[scene];
};
ClearCoordSystems:
PUBLIC
PROC [scene: Scene] = {
Removes all but WORLD, SCREEN and sceneAssembly.
Assumes for now that WORLD, and SCREEN are the first 2 coordsystems on the list.
world: CoordSystem ← scene.coordSysRoot;
DeleteCoordSysAndChildren[world.children.first, scene]; -- assumes this is sceneAssembly.
};
ClearMasterObjects:
PUBLIC
PROC [scene: Scene] = {
Removes all but "block", "sphere", "cone", and "cylinder" from current scene.
Assumes for now that "sphere","cone", and "cylinder", and "block" are the first five master objects.
z: MasterObjectList ← scene.masterObjects; -- "sphere"
z ← z.rest;-- "block"
z ← z.rest;-- "cone"
z ← z.rest;-- "cylinder"
z.rest ← NIL;-- cut off the rest
};
DeleteSubassemblyFromAssembly:
PUBLIC
PROC [subassembly: Assembly, assembly: Assembly, scene: Scene]
RETURNS [success:
BOOL] = {
IF ISTYPE[assembly.shape, AssemblyList] THEN
[assembly.shape, success] ← RemoveFromAssemblyList[subassembly,
NARROW[assembly.shape, AssemblyList], scene]
ELSE ERROR;
};
RemoveFromAssemblyList:
PRIVATE
PROC [a: Assembly, al: AssemblyList, scene: Scene]
RETURNS [newAl: AssemblyList, success:
BOOL] = {
Tree walk through the assembly deleting all of its coordinate systems. Then, cut the assembly loose and feed it to the garbage collector.
lastAssemblyList: LIST OF Assembly ← al.list;
DeleteAllAssembliesSittingOn[a, scene];
IF lastAssemblyList.first = a
THEN {-- first item on the list
DeleteAssemblyAndSons[a, scene];
al.list ← lastAssemblyList.rest;
RETURN[al, TRUE];
};
FOR l:
LIST
OF Assembly ← lastAssemblyList.rest, l.rest
UNTIL l =
NIL
DO
IF l.first = a
THEN {
DeleteAssemblyAndSons[a, scene];
success ← TRUE;
lastAssemblyList.rest ← l.rest; -- splice out a
newAl ← al;
RETURN;
}
ELSE lastAssemblyList ← lastAssemblyList.rest;
ENDLOOP;
success ← FALSE;
};
TemporaryRemoveFromAssemblyList:
PUBLIC
PROC [a: Assembly, al: AssemblyList, scene: Scene]
RETURNS [newAl: AssemblyList, success:
BOOL] = {
A simple list remove operation. Does not break up the assembly and its sons, nor does it delete their coordinate systems. This routine is called by MoveToFrontOfAssembly to splice an assembly out of an AssemblyList.
lastAssemblyList: LIST OF Assembly ← al.list;
IF lastAssemblyList.first = a
THEN {-- first item on the list
al.list ← lastAssemblyList.rest; RETURN[al, TRUE] };
FOR l:
LIST
OF Assembly ← lastAssemblyList.rest, l.rest
UNTIL l =
NIL
DO
IF l.first = a
THEN {
success ← TRUE;
lastAssemblyList.rest ← l.rest; -- splice out a
newAl ← al;
RETURN;
}
ELSE lastAssemblyList ← lastAssemblyList.rest;
ENDLOOP;
success ← FALSE;
};
DeleteAssemblyAndSons:
PRIVATE
PROC [a: Assembly, scene: Scene] = {
DeleteCoordSysAndChildren[a.coordSys, scene];
};
DeleteAllPrimitivesOfClass:
PUBLIC
PROC [className: Rope.
ROPE, scene: Scene] = {
className must be a master object class, e.g. "sphere" or "jack". All primitive (leaf) assemblies refering to shapes of this class will be deleted in subtree rooted at root.
moClass: MasterObjectClass;
success: BOOL;
[moClass, success] ← DisplayList3d.FindClassFromName[className];
IF
NOT success
THEN {
SVError.Append[Rope.Cat["DeleteAllPrimitivesOfClass: Couldn't find class ", className, "."], TRUE, TRUE];
SVError.Blink[];
};
DeleteAllOfClassAux[moClass, scene.assembly, scene];
};
DeleteAllOfClassAux:
PRIVATE
PROC [moClass: MasterObjectClass, root: Assembly, scene: Scene] = {
WITH root.shape SELECT FROM
shape: Shape => {
child, parent: Assembly;
success: BOOL;
IF shape.mo.class = moClass
THEN {
[child, parent] ← DisplayList3d.FindAssemblyFromName[root.name, scene];
IF child # root THEN ERROR;
success ← DisplayList3d.DeleteSubassemblyFromAssembly[child, parent, scene];
Removes assembly from the assemblyList of superAssembly and deletes the coordinate systems of all of its children.
IF NOT success THEN ERROR;
};
};
alist: AssemblyList => {
FOR list:
LIST
OF Assembly ← alist.list, list.rest
UNTIL list =
NIL
DO
DeleteAllOfClassAux[moClass, list.first, scene];
ENDLOOP;
};
ENDCASE => ERROR;
};
DeleteAllAssembliesSittingOn:
PUBLIC
PROC [chair: Assembly, scene: Scene] = {
All assemblies A such that A.sittingOn = chair.name will be deleted along with their children.
DeleteAllSittingOnAux[chair.name, scene.assembly, scene];
};
DeleteAllSittingOnAux:
PRIVATE
PROC [chairName: Rope.
ROPE, root: Assembly, scene: Scene] = {
child, parent: Assembly;
success: BOOL;
IF Rope.Equal[root.sittingOn, chairName,
TRUE]
THEN {
[child, parent] ← DisplayList3d.FindAssemblyFromName[root.name, scene];
IF child # root THEN ERROR;
success ← DisplayList3d.DeleteSubassemblyFromAssembly[child, parent, scene];
Removes assembly from the assemblyList of superAssembly and deletes the coordinate systems of all of its children.
IF NOT success THEN ERROR;
RETURN;
};
WITH root.shape SELECT FROM
shape: Shape => {};
alist: AssemblyList => {
FOR list:
LIST
OF Assembly ← alist.list, list.rest
UNTIL list =
NIL
DO
DeleteAllSittingOnAux[chairName, list.first, scene];
ENDLOOP;
};
ENDCASE => ERROR;
};
Copy Parts of the Scene Tree
CopyAssemblyAndSonsRename:
PUBLIC
PROC [assembly: Assembly, scene: Scene, prefix: Rope.
ROPE, parent: Assembly]
RETURNS [copy: Assembly] = {
For copying assemblies within the same scene. The copies can refer to the same master object records as other objects in this scene. The prefix rope is prepended to the names of each node as it is copied to distinguish it from the original. CreateClusterAssemblyAtExistingCoordSys is used for filing in, so it doesn't do all we would like. We must wire up parents to the children manually.
moFound: BOOL;
IF NewNamesAlreadyPresent[assembly, scene, prefix] THEN SIGNAL DisplayList3d.NameAlreadyPresent;
WITH assembly.shape SELECT FROM
alist: AssemblyList => {
-- assembly is a composite assembly.
copyCS: CoordSystem ← CoordSys.CreateCoordSysInTree[name: Rope.Concat[prefix, assembly.name], mat: assembly.coordSys.mat, parent: parent.coordSys, root: scene.coordSysRoot];
copy ← DisplayList3d.CreateClusterAssemblyAtExistingCoordSys[Rope.Concat[prefix, assembly.name], alist.pointSetOp, scene, copyCS];
FOR list:
LIST
OF Assembly ← alist.list, list.rest
UNTIL list =
NIL
DO
[] ← CopyAssemblyAndSonsRename[list.first, scene,
prefix, copy];
CopyAssemblyAndSonsRename returns an assembly which is complete and wired up to parent.
ENDLOOP;
};
shape: Shape => {
-- assembly is a primitive assembly
artworkCopy: Artwork ← SVArtwork.Copy[assembly.artwork];
copyCS: CoordSystem ← CoordSys.CreateCoordSysInTree[name: Rope.Concat[prefix, assembly.name], mat: assembly.coordSys.mat, parent: parent.coordSys, root: scene.coordSysRoot];
[copy, moFound] ← DisplayList3d.CreatePrimitiveAtExistingCoordSys[Rope.Concat[prefix, assembly.name], shape.mo.name, CoordSys.GetScalars[shape.coordSys], scene, copyCS, artworkCopy, assembly.isTool];
IF NOT moFound THEN ERROR; -- for some reason the master object which assembly refers to is not registered in the scene (report this to SolidviewsSupport).
};
ENDCASE => ERROR;
DisplayList3d.ConnectAssemblyToParent[copy, parent];
}; -- end of CopyAssemblyAndSons
CopyAssemblyAndSonsNoRename:
PUBLIC
PROC [assembly: Assembly, newScene: Scene, parent: Assembly]
RETURNS [copy: Assembly] = {
For copying an assembly from one scene to another. This presents problems since the needed masterobject may not be already present in the target scene. We assume that procedure MergeAssemblyIntoScene has already added the necessary master objects. No prefix is added. We just pray that there are no name conflicts. CreateClusterAssemblyAtExistingCoordSys is used for filing in, so it doesn't do all we would like. We must wire up parents to the children manually.
moFound: BOOL;
IF DisplayList3d.AnyNamesAlreadyPresent[assembly, newScene] THEN SIGNAL DisplayList3d.NameAlreadyPresent;
WITH assembly.shape SELECT FROM
alist: AssemblyList => {
-- assembly is a composite assembly.
copyCS: CoordSystem ← CoordSys.CreateCoordSysInTree[name: assembly.name, mat: assembly.coordSys.mat, parent: parent.coordSys, root: newScene.coordSysRoot];
copy ← DisplayList3d.CreateClusterAssemblyAtExistingCoordSys[assembly.name, alist.pointSetOp, newScene, copyCS];
FOR list:
LIST
OF Assembly ← alist.list, list.rest
UNTIL list =
NIL
DO
[] ← CopyAssemblyAndSonsNoRename[list.first, newScene, copy];
CopyAssemblyAndSonsNoRename returns an assembly which is complete and wired up to parent.
ENDLOOP;
};
shape: Shape => {
-- assembly is a primitive assembly
artworkCopy: Artwork ← SVArtwork.Copy[assembly.artwork];
copyCS: CoordSystem ← CoordSys.CreateCoordSysInTree[name: assembly.name, mat: assembly.coordSys.mat, parent: parent.coordSys, root: newScene.coordSysRoot];
[copy, moFound] ← DisplayList3d.CreatePrimitiveAtExistingCoordSys[assembly.name, shape.mo.name, CoordSys.GetScalars[shape.coordSys], newScene, copyCS, artworkCopy, assembly.isTool];
IF NOT moFound THEN ERROR; -- for some reason the master object which assembly refers to is not registered in the scene (report this to SolidviewsSupport).
};
ENDCASE => ERROR;
DisplayList3d.ConnectAssemblyToParent[assembly, parent];
}; -- end of CopyAssemblyAndSonsNoRename
ReadAlpha:
PRIVATE
PROC [s:
IO.
STREAM]
RETURNS [base: Rope.
ROPE] = {
skip: INT;
[base, skip] ← IO.GetTokenRope[s, AlphaBreakProc];
};
AlphaBreakProc:
SAFE
PROC [char:
CHAR]
RETURNS [
IO.CharClass] =
TRUSTED {
RETURN[IF char = '. THEN break ELSE other]
};
FindUniqueAssemblyNum:
PRIVATE
PROC [scene: Scene]
RETURNS [num:
NAT] = {
num ← FindUniqueAssemblyNumAux[scene.assembly];
num ← num + 1;
};
FindUniqueAssemblyNumAux:
PRIVATE
PROC [assembly: Assembly]
RETURNS [num:
NAT] = {
Finds an integer such that "<name>.<num>" is unique in the scene of assembly for all strings <name>. i.e. Find the highest .num extension in the tree rooted at assembly.
thisNum: NAT;
WITH assembly.shape SELECT FROM
alist: AssemblyList => {
-- assembly is a composite assembly.
[----, num] ← CoordSys.BaseAndNumber[assembly.name];
FOR l:
LIST
OF Assembly ← alist.list, l.rest
UNTIL l =
NIL
DO
thisNum ← FindUniqueAssemblyNumAux[l.first];
num ← MAX[num, thisNum];
ENDLOOP;
};
shape: Shape => {
-- assembly is a primitive assembly
[----, num] ← CoordSys.BaseAndNumber[assembly.name];
};
ENDCASE => ERROR;
};
CopyAssemblyAndSonsUniqueNames:
PUBLIC
PROC [assembly: Assembly, oldScene: Scene, newScene: Scene, parent: Assembly]
RETURNS [copy: Assembly] = {
oldScene is the scene assembly belongs to. newScene is the scene copy will belong to. parent must be an assembly in the new scene.
num: NAT;
success: BOOL;
num ← FindUniqueAssemblyNum[newScene];
IF oldScene = newScene
THEN
copy ← CopyAssemblyAndSonsUniqueNamesAux[assembly, newScene, parent, num]
ELSE {
success ← CopyNeededMasterObjects[assembly, oldScene, newScene];
IF
NOT success
THEN {
SVError.Append[Rope.Cat["Masterobject name conflict scenes: ", oldScene.name, "/", newScene.name], TRUE, TRUE];
SVError.Blink[];
RETURN;
};
copy ← CopyAssemblyAndSonsUniqueNamesAux[assembly, newScene, parent, num];
};
};
CopyAssemblyAndSonsUniqueNamesAux:
PUBLIC
PROC [assembly: Assembly, newScene: Scene, parent: Assembly, num: NAT]
RETURNS [copy: Assembly] = {
An attempt to do it right. For assembly and all of its successors, we find an integer a just high enough so that if name.# becomes name.a then all names will be unique. We copy the assembly and its successors and rename them this way.
thisBase, unique: Rope.ROPE;
thisNum: NAT;
moFound: BOOL;
WITH assembly.shape SELECT FROM
alist: AssemblyList => {
-- assembly is a composite assembly.
copyCS: CoordSystem;
[thisBase, thisNum] ← CoordSys.BaseAndNumber[assembly.name];
unique ← IO.PutFR["%g.%g",[rope[thisBase]], [integer[num+thisNum]]];
copyCS ← CoordSys.CreateCoordSysInTree[name: unique, mat: assembly.coordSys.mat, parent: parent.coordSys, root: newScene.coordSysRoot];
copy ← DisplayList3d.CreateClusterAssemblyAtExistingCoordSys[unique, alist.pointSetOp, newScene, copyCS];
FOR list:
LIST
OF Assembly ← alist.list, list.rest
UNTIL list =
NIL
DO
[] ←
CopyAssemblyAndSonsUniqueNamesAux[list.first, newScene, copy, num];
CopyAssemblyAndSonsUniqueNamesAux returns an assembly which is complete and wired up to parent.
ENDLOOP;
};
shape: Shape => {
-- assembly is a primitive assembly
artworkCopy: Artwork ← SVArtwork.Copy[assembly.artwork];
copyCS: CoordSystem;
[thisBase, thisNum] ← CoordSys.BaseAndNumber[assembly.name];
unique ← IO.PutFR["%g.%g",[rope[thisBase]], [integer[num+thisNum]]];
copyCS ← CoordSys.CreateCoordSysInTree[name: unique, mat: assembly.coordSys.mat, parent: parent.coordSys, root: newScene.coordSysRoot];
[copy, moFound] ← DisplayList3d.CreatePrimitiveAtExistingCoordSys[unique, shape.mo.name, CoordSys.GetScalars[shape.coordSys], newScene, copyCS, artworkCopy, assembly.isTool];
IF NOT moFound THEN ERROR; -- for some reason the master object which assembly refers to is not registered in the scene (report this to SolidviewsSupport).
};
ENDCASE => ERROR;
DisplayList3d.ConnectAssemblyToParent[copy, parent];
};
AddMOsToScene:
PRIVATE
PROC [moList: MasterObjectList, scene: Scene] = {
We assume that none of the mo's in moList is already in scene
FOR list: MasterObjectList ← moList, list.rest
UNTIL list =
NIL
DO
scene.masterObjects ← DisplayList3dPrivate.AppendToMasterObjects[list.first, scene.masterObjects];
ENDLOOP;
};
CopyMOList:
PRIVATE
PROC [moList: MasterObjectList]
RETURNS [copyList: MasterObjectList] = {
copyList ← NIL;
FOR list: MasterObjectList ← moList, list.rest
UNTIL list =
NIL
DO
copyList ← DisplayList3dPrivate.AppendToMasterObjects[DisplayList3d.CopyMasterObject[list.first], copyList];
ENDLOOP;
};
CopyNeededMasterObjects:
PUBLIC
PROC [assembly: Assembly, fromScene, toScene: Scene]
RETURNS [success:
BOOL] = {
Makes a list of all of the masterobjects needed. Compares this list to the list of masterobjects available in the new scene, subtracting any that are available. Copies those that are still needed and adds them to the new scene. Assumes that if two master objects have the same name, they are the same.
moList: MasterObjectList;
toMoList: MasterObjectList;
neededList: MasterObjectList;
success ← TRUE;
moList ← DisplayList3d.MasterObjectsOfAssembly[assembly, fromScene];
toMoList ← DisplayList3d.MasterObjectsOfScene[toScene];
neededList ← DisplayList3dPrivate.MoListMinusMoList[moList, toMoList];
neededList ← CopyMOList[neededList];
AddMOsToScene[neededList, toScene];
};
Draw Parts of the Scene Tree
DrawScene:
PUBLIC
PROC [dc: Imager.Context, scene: Scene, camera: Camera] = {
DrawSceneAux:
SAFE PROC =
TRUSTED {
CSGGraphics.Clip[dc, camera];
SELECT camera.style FROM
wire => DrawWireAssemblies[dc, scene, camera];
shaded => DrawShadedAssemblies[dc, scene, camera];
normals => DrawNormalsAssemblies[dc, scene, camera];
ENDCASE => SIGNAL NotYetImplemented;
Draw the current bounding frame if there is one.
IF
NOT camera.frame.fullScreen
THEN {
SetColor[dc, camera, Imager.black];
CSGGraphics.DrawFrame[dc, camera];
};
};
Imager.DoSaveAll[dc, DrawSceneAux];
};
NotYetImplemented: PUBLIC SIGNAL = CODE;
DrawWireAssemblies:
PRIVATE
PROC [dc: Imager.Context, scene: Scene, camera: Camera] = {
assemblyName: Rope.ROPE;
found: BOOL;
assembly: Assembly;
FOR list:
LIST
OF Rope.
ROPE ← camera.visibleAssemblies, list.rest
UNTIL list =
NIL
DO
assemblyName ← list.first;
found ← TRUE;
[assembly, ----] ← DisplayList3d.FindAssemblyFromName[assemblyName, scene
!DisplayList3d.AssemblyNotFound => {found ← FALSE; CONTINUE}];
IF found
THEN {
SVTransforms.TellAboutCameraAndWorld[assembly.coordSys, camera, scene];
DrawWireAssembly[dc, assembly, scene, camera];
};
ENDLOOP;
};
DrawShadedAssemblies:
PRIVATE
PROC [dc: Imager.Context, scene: Scene, camera: Camera] = {
assemblyName: Rope.ROPE;
assembly: Assembly;
found: BOOL;
box: Imager.Rectangle;
Draw a background color.
box ← ImagerBackdoor.GetBounds[dc];
SetColor[dc, camera, scene.backgroundColor];
Imager.MaskRectangle[dc, box];
FOR list:
LIST
OF Rope.
ROPE ← camera.visibleAssemblies, list.rest
UNTIL list =
NIL
DO
assemblyName ← list.first;
found ← TRUE;
[assembly, ----] ← DisplayList3d.FindAssemblyFromName[assemblyName, scene
!DisplayList3d.AssemblyNotFound => {found ← FALSE; CONTINUE}];
IF found
THEN {
SVTransforms.TellAboutCameraAndWorld[assembly.coordSys, camera, scene];
DrawShadedAssembly[dc, assembly, scene, camera];
};
ENDLOOP;
};
DrawNormalsAssemblies:
PRIVATE
PROC [dc: Imager.Context, scene: Scene, camera: Camera] = {
assemblyName: Rope.ROPE;
assembly: Assembly;
found: BOOL;
FOR list:
LIST
OF Rope.
ROPE ← camera.visibleAssemblies, list.rest
UNTIL list =
NIL
DO
assemblyName ← list.first;
found ← TRUE;
[assembly, ----] ← DisplayList3d.FindAssemblyFromName[assemblyName, scene
!DisplayList3d.AssemblyNotFound => {found ← FALSE; CONTINUE}];
IF found
THEN {
SVTransforms.TellAboutCameraAndWorld[assembly.coordSys, camera, scene];
DrawNormalsAssembly[dc, assembly, scene, camera];
};
ENDLOOP;
};
DrawAssembly:
PUBLIC
PROC [dc: Imager.Context, assembly: Assembly, scene: Scene, camera: Camera] = {
SVTransforms.TellAboutCameraAndWorld[assembly.coordSys, camera, scene];
CSGGraphics.Clip[dc, camera]; -- clip picture to frame
SELECT camera.style FROM
wire => DrawWireAssembly[dc, assembly, scene, camera];
shaded => DrawShadedAssembly[dc, assembly, scene, camera];
normals => DrawNormalsAssembly[dc, assembly, scene, camera];
ENDCASE => SIGNAL NotYetImplemented;
};
SetColor:
PRIVATE
PROC [dc: Imager.Context, camera: Camera, color: Color] = {
currentColor: Imager.Color ← ImagerBackdoor.GetColor[dc];
IF currentColor = ImagerBackdoor.invert THEN RETURN;
IF camera.colorFilm THEN Imager.SetColor[dc, color]
ELSE {
intensity: REAL ← ImagerColorPrivate.ComponentFromColor[NARROW[color], $Intensity];
Imager.SetColor[dc, ImagerColor.ColorFromGray[1.0-intensity]]};
};
DrawWireAssembly:
PRIVATE
PROC [dc: Imager.Context, assembly: Assembly, scene: Scene, camera: Camera] = {
SetColor[dc, camera, Imager.black];
DrawWireAssembly2[dc, assembly, camera];
};
DrawWireAssembly2:
PRIVATE
PROC [dc: Imager.Context, assembly: Assembly, camera: Camera] = {
SELECT assembly.showAs FROM
tool => {
toolMasterObject: MasterObject ← assembly.toolMasterObject;
IF toolMasterObject =
NIL
THEN {
SVError.Append[Rope.Cat["Assembly ", assembly.name, " is a tool but has no tool data. Contact implementor."], TRUE, TRUE];
RETURN;
};
toolMasterObject.class.lineDraw[dc, toolMasterObject.lineBody, camera, assembly.coordSys];
RETURN;
};
normal => {
WITH assembly.shape SELECT FROM
assems: AssemblyList => {
FOR subassemblies: LIST OF Assembly ← assems.list, subassemblies.rest
UNTIL subassemblies =
NIL
DO
DrawWireAssembly2[dc: dc, assembly: subassemblies.first, camera: camera];
ENDLOOP;
};
shape: Shape => {
Imager.SetColor[dc, assembly.color];
shape.mo.class.lineDraw[dc, shape.mo.lineBody, camera, shape.coordSys];
};
ENDCASE => ERROR;
};
invisible => {};
both => ERROR SVError.NotYetImplemented;
ENDCASE => ERROR;
};
DrawShadedAssembly:
PRIVATE
PROC [dc: Imager.Context, assembly: Assembly, scene: Scene, camera: Camera] = {
Get a list of surfaces from each subassembly of "assembly" and draw them with the Painter's Algorithm (back to front)
Count the total number of surfaces and make a priority queue of the appropriate size.
predictedQueueSize: NAT ← CountSurfacesInAssembly[assembly];
surfaceQueue: PriorityQueue.Ref ←
PriorityQueue.Predict[predictedQueueSize, DeeperPlanarSurface];
mo: MasterObject;
thisPlanarSurf: PlanarSurface;
DrawShadedAssemblyAux:
SAFE PROC =
TRUSTED {
Now put the surfaces on the queue
PutAssemblyOnQueue[assembly, surfaceQueue, camera.coordSys];
Take the surfaces off the queue in order and draw them
FOR i:
INT
IN[1..PriorityQueue.Size[surfaceQueue]]
DO
thisPlanarSurf ← NARROW[PriorityQueue.Remove[surfaceQueue]];
mo ← thisPlanarSurf.mo;
mo.class.drawSurf[dc, thisPlanarSurf, scene.lightSources, camera];
ENDLOOP;
};
Imager.DoSaveAll[dc, DrawShadedAssemblyAux];
};
CountSurfacesInAssembly:
PRIVATE
PROC [assembly: Assembly]
RETURNS [surfCount:
NAT] = {
WITH assembly.shape
SELECT
FROM
assems: AssemblyList => surfCount ← CountSurfacesInAssemblyList[assems];
shape: Shape => surfCount ← shape.mo.class.countSurf[shape.mo];
ENDCASE => ERROR;
};
CountSurfacesInAssemblyList:
PRIVATE
PROC [asl: AssemblyList]
RETURNS [surfCount:
NAT] = {
surfCount ← 0;
FOR list:
LIST
OF Assembly ← asl.list, list.rest
UNTIL list =
NIL
DO
surfCount ← surfCount + CountSurfacesInAssembly[list.first];
ENDLOOP;
};
PutAssemblyOnQueue:
PRIVATE
PROC [assembly: Assembly, q: PriorityQueue.Ref, cameraCS: CoordSystem] = {
thisSurf: PlanarSurface;
cameraNormal: Vector;
surfList: PlanarSurfaceList;
SELECT assembly.showAs FROM
tool => {
toolMasterObject: MasterObject ← assembly.toolMasterObject;
surfList ← toolMasterObject.class.getSurf[assembly, cameraCS];
FOR surfList ← surfList, surfList.rest
UNTIL surfList =
NIL
DO
thisSurf ← surfList.first;
cameraNormal ← Matrix3d.UpdateVectorWithInverse[assembly.coordSys.cameraWRTlocal, thisSurf.normal];
thisSurf.normal ← cameraNormal;
PriorityQueue.Insert[q, thisSurf];
ENDLOOP;
};
normal => {
WITH assembly.shape SELECT FROM
assems: AssemblyList => PutAssemblyListOnQueue[assems, q, cameraCS];
shape: Shape => {
surfList ← shape.mo.class.getSurf[assembly, cameraCS];
FOR surfList ← surfList, surfList.rest
UNTIL surfList =
NIL
DO
thisSurf ← surfList.first;
cameraNormal ← Matrix3d.UpdateVectorWithInverse[shape.coordSys.cameraWRTlocal, thisSurf.normal];
thisSurf.normal ← cameraNormal;
Eliminate most back-facing surfaces at this point by a simple test.
IF thisSurf.normal[3] >0 THEN PriorityQueue.Insert[q,thisSurf];
ENDLOOP;
};
ENDCASE => ERROR;
};
invisible => {};
both => ERROR SVError.NotYetImplemented;
ENDCASE => ERROR;
}; -- end of PutAssemblyOnQueue
PutAssemblyListOnQueue:
PRIVATE
PROC [asl: AssemblyList, q: PriorityQueue.Ref, cameraCS: CoordSystem] = {
FOR list:
LIST
OF Assembly ← asl.list, list.rest
UNTIL list =
NIL
DO
PutAssemblyOnQueue[list.first, q, cameraCS];
ENDLOOP;
};
DeeperPlanarSurface:
SAFE
PROC [x,y: PriorityQueue.Item, data:
REF ←
NIL]
RETURNS [
BOOL] =
TRUSTED {
xS: PlanarSurface ← NARROW[x];
yS: PlanarSurface ← NARROW[y];
RETURN[xS.depth < yS.depth];
};
DrawNormalsAssembly:
PROC [dc: Imager.Context, assembly: Assembly, scene: Scene, camera: Camera] = {
SetColor[dc, camera, Imager.black];
DrawNormalsAssembly2[dc, assembly, scene, camera];
};
DrawNormalsAssembly2:
PROC [dc: Imager.Context, assembly: Assembly, scene: Scene, camera: Camera] = {
lightSources: LightSourceList ← scene.lightSources;
WITH assembly.shape SELECT FROM
assems: AssemblyList => {
FOR subassemblies: LIST OF Assembly ← assems.list, subassemblies.rest
UNTIL subassemblies = NIL DO
DrawNormalsAssembly2[dc: dc, assembly: subassemblies.first, scene: scene, camera: camera];
ENDLOOP;
};
shape: Shape => {
Imager.SetColor[dc, assembly.color];
shape.mo.class.normalsDraw[dc, shape.mo.shadeBody, camera, shape.coordSys];
};
ENDCASE => ERROR;
};