<> <> <> DIRECTORY CastRays, CoordSys, CSG, CSGGraphics, DisplayList3d, DisplayList3dPrivate, Graphics, GraphicsColor, Matrix3d, PriorityQueue, Rope, Shading, SV2d, SVPolygon3d, SVTransforms, SVVector3d; DisplayList3dImplB: PROGRAM IMPORTS CastRays, CoordSys, CSGGraphics, Graphics, GraphicsColor, DisplayList3d, DisplayList3dPrivate, Matrix3d, PriorityQueue, Rope, SVTransforms EXPORTS DisplayList3d, DisplayList3dPrivate = BEGIN <> Camera: TYPE = REF CameraObj; CameraObj: TYPE = CSGGraphics.CameraObj; Classification: TYPE = REF ClassificationObj; ClassificationObj: TYPE = CSG.ClassificationObj; Color: TYPE = GraphicsColor.Color; CoordSysList: TYPE = CoordSys.CoordSysList; CoordSysObj: TYPE = CoordSys.CoordSysObj; CoordSystem: TYPE = REF CoordSysObj; CSGTree: TYPE = REF CSGTreeObj; CSGTreeObj: TYPE = CSG.CSGTreeObj; DrawStyle: TYPE = CSGGraphics.DrawStyle; FileCamera: TYPE = REF FileCameraObj; FileCameraObj: TYPE = DisplayList3d.FileCameraObj; FileCameraList: TYPE = DisplayList3d.FileCameraList; FrameBox: TYPE = REF FrameBoxObj; FrameBoxObj: TYPE = CSGGraphics.FrameBoxObj; Matrix4by4: TYPE = Matrix3d.Matrix4by4; Plane: TYPE = SVPolygon3d.Plane; Point2d: TYPE = SV2d.Point2d; Point3d: TYPE = Matrix3d.Point3d; PointSetOp: TYPE = CSG.PointSetOp; -- {union, intersection, difference} Poly3d: TYPE = SVPolygon3d.Poly3d; Primitive: TYPE = REF PrimitiveObj; PrimitiveObj: TYPE = CSG.PrimitiveObj; Ray: TYPE = REF RayObj; RayObj: TYPE = CSG.RayObj; Vector: TYPE = SVVector3d.Vector; <> <> Database: TYPE = REF DatabaseObj; DatabaseObj: TYPE = DisplayList3d.DatabaseObj; Scene: TYPE = REF SceneObj; SceneObj: TYPE = DisplayList3d.SceneObj; Assembly: TYPE = REF AssemblyObj; AssemblyObj: TYPE = DisplayList3d.AssemblyObj; AssemblyList: TYPE = REF AssemblyListObj; AssemblyListObj: TYPE = DisplayList3d.AssemblyListObj; LightSource: TYPE = REF LightSourceObj; LightSourceObj: TYPE = Shading.LightSourceObj; LightSourceList: TYPE = Shading.LightSourceList; <> MasterObjectClass: TYPE = REF MasterObjectClassObj; MasterObjectClassObj: TYPE = DisplayList3d.MasterObjectClassObj; MasterObjectClassList: TYPE = DisplayList3d.MasterObjectClassList; FileoutProc: TYPE = DisplayList3d.FileoutProc; FileinProc: TYPE = DisplayList3d.FileinProc; <> MasterObject: TYPE = REF MasterObjectRec; MasterObjectRec: TYPE = DisplayList3d.MasterObjectRec; MasterObjectList: TYPE = DisplayList3d.MasterObjectList; RayCastProc: TYPE = CSG.RayCastProc; RayCastNoBBoxesProc: TYPE = CSG.RayCastNoBBoxesProc; PreprocessProc: TYPE = DisplayList3d.PreprocessProc; LineDrawProc: TYPE = DisplayList3d.LineDrawProc; NormalsDrawProc: TYPE = DisplayList3d.NormalsDrawProc; CountPlanarSurfacesProc: TYPE = DisplayList3d.CountPlanarSurfacesProc; GetPlanarSurfacesProc: TYPE = DisplayList3d.GetPlanarSurfacesProc; PlanarSurface: TYPE = REF PlanarSurfaceObj; PlanarSurfaceObj: TYPE = DisplayList3d.PlanarSurfaceObj; PlanarSurfaceList: TYPE = DisplayList3d.PlanarSurfaceList; DrawPlanarSurfaceProc: TYPE = DisplayList3d.DrawPlanarSurfaceProc; DrawSubBoxesProc: TYPE = DisplayList3d.DrawSubBoxesProc; <> <> NoOpRayCast: PUBLIC RayCastProc = { class _ CastRays.GetClassFromPool[]; CastRays.MakeClassAMiss[class]; }; NoOpRayCastNoBBoxes: PUBLIC RayCastNoBBoxesProc = { class _ CastRays.GetClassFromPool[]; CastRays.MakeClassAMiss[class]; }; 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]}; <> NoOpGetPlanarSurfaces: PUBLIC GetPlanarSurfacesProc = {RETURN[NIL]}; <> NoOpDrawPlanarSurface: PUBLIC DrawPlanarSurfaceProc = {}; -- don't draw anything NoOpDrawSubBoxes: PUBLIC DrawSubBoxesProc = {}; -- don't draw anything <> 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] = { 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"] THEN RETURN[TRUE]; <> FOR primitiveAssemblies: LIST OF Assembly _ DisplayList3d.ListOfPrimAssemblies[scene.assembly, scene], primitiveAssemblies.rest UNTIL primitiveAssemblies = NIL DO IF primitiveAssemblies.first.object = mo THEN RETURN[TRUE]; ENDLOOP; found _ DeleteMasterObjectNamed[mo.name, scene]; }; -- end of DeleteMasterObjectIfUnused DeleteCoordSysNamed: PUBLIC PROC [csName: Rope.ROPE, scene: Scene] = { cs, beforeCS, afterCS: CoordSysList; notFound: BOOL _ FALSE; [beforeCS, cs, afterCS] _ CoordSys.FindCoordSysAndNeighborsFromName[csName, scene.coordSystems !CoordSys.CoordSysNotFound => {notFound _ TRUE; CONTINUE}]; IF notFound THEN RETURN; IF beforeCS = NIL THEN scene.coordSystems _ afterCS ELSE beforeCS.rest _ afterCS; }; -- 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.object _ 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.>> z: CoordSysList _ scene.coordSystems; -- WORLD z _ z.rest;-- SCREEN z _ z.rest;-- sceneAssembly z.rest _ NIL;-- cut off the rest }; ClearMasterObjects: PUBLIC PROC [scene: Scene] = { <> <> 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.object,AssemblyList] THEN [assembly.object, success] _ RemoveFromAssemblyList[subassembly, NARROW[assembly.object,AssemblyList], scene] ELSE ERROR; }; RemoveFromAssemblyList: PRIVATE PROC [a: Assembly, al: AssemblyList, scene: Scene] RETURNS [newAl: AssemblyList, success: BOOL] = { <> lastAssemblyList: LIST OF Assembly _ al.list; 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] = { <> 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] = { DeleteCoordSysNamed[a.coordSys.name, scene]; WITH a.object SELECT FROM alist: AssemblyList => DeleteAssemblyListAndSons[alist, scene]; mo: MasterObject => RETURN; ENDCASE => ERROR; }; DeleteAssemblyListAndSons: PRIVATE PROC [alist: AssemblyList, scene: Scene] = { FOR list: LIST OF Assembly _ alist.list, list.rest UNTIL list = NIL DO DeleteAssemblyAndSons[list.first, scene]; ENDLOOP; }; <> <> RemoveDuplicateMOs: PUBLIC PROC [moList: MasterObjectList] RETURNS [uniqueList: MasterObjectList] = { <<**** Naive algorithm for now. Go through moList. Add anything to uniqueList which it doesn't already have>> thisMO: MasterObject; uniqueList _ NIL; FOR list: MasterObjectList _ moList, list.rest UNTIL list = NIL DO thisMO _ list.first; IF NOT ObjectNameInList[thisMO.name, uniqueList] THEN uniqueList _ CONS[thisMO, uniqueList]; ENDLOOP; }; ObjectNameInList: PRIVATE PROC [moName: Rope.ROPE, moList: MasterObjectList] RETURNS [BOOL]= { FOR list: MasterObjectList _ moList, list.rest UNTIL list = NIL DO IF Rope.Equal[list.first.name, moName, TRUE] THEN RETURN[TRUE]; ENDLOOP; RETURN[FALSE]; }; MoListMinusMoList: PUBLIC PROC [moList1, moList2: MasterObjectList] RETURNS [moList1MinusmoList2: MasterObjectList] = { <> moList1MinusmoList2 _ NIL; FOR list: MasterObjectList _ moList1, list.rest UNTIL list = NIL DO IF NOT ObjectNameInList[list.first.name, moList2] THEN moList1MinusmoList2 _ CONS[list.first, moList1MinusmoList2]; ENDLOOP; }; CopyMasterObjectList: PUBLIC PROC [moList: MasterObjectList] RETURNS [copy: MasterObjectList] = { <> copy _ NIL; FOR list: MasterObjectList _ moList, list.rest UNTIL list = NIL DO copy _ DisplayList3dPrivate.AppendToMasterObjects[list.first, copy]; ENDLOOP; }; <> DrawScene: PUBLIC PROC [dc: Graphics.Context, scene: Scene, camera: Camera] = { mark: Graphics.Mark; SVTransforms.TellAboutCameraAndWorld[scene.assembly, camera, scene]; <> mark _ Graphics.Save[dc]; <> <> IF NOT camera.frame.fullScreen THEN { SetColor[dc, camera, GraphicsColor.black]; CSGGraphics.DrawFrame[dc, camera]; }; SELECT camera.style FROM wire => DrawWireAssemblies[dc, scene, camera]; shaded => DrawShadedAssemblies[dc, scene, camera]; normals => DrawNormalsAssemblies[dc, scene, camera]; ENDCASE => SIGNAL NotYetImplemented; Graphics.Restore[dc, mark]; }; NotYetImplemented: PUBLIC SIGNAL = CODE; DrawWireAssemblies: PRIVATE PROC [dc: Graphics.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 DrawWireAssembly[dc, assembly, scene, camera]; ENDLOOP; }; DrawShadedAssemblies: PRIVATE PROC [dc: Graphics.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 DrawShadedAssembly[dc, assembly, scene, camera]; ENDLOOP; }; DrawNormalsAssemblies: PRIVATE PROC [dc: Graphics.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 DrawNormalsAssembly[dc, assembly, scene, camera]; ENDLOOP; }; DrawAssembly: PUBLIC PROC [dc: Graphics.Context, assembly: Assembly, scene: Scene, camera: Camera] = { SVTransforms.TellAboutCameraAndWorld[assembly, camera, scene]; <> <> 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: Graphics.Context, camera: Camera, color: Color] = { IF camera.colorFilm THEN Graphics.SetColor[dc, color] ELSE { intensity: REAL _ GraphicsColor.ColorToIntensity[color]; Graphics.SetColor[dc, GraphicsColor.IntensityToColor[intensity]]}; }; DrawWireAssembly: PRIVATE PROC [dc: Graphics.Context, assembly: Assembly, scene: Scene, camera: Camera] = { Graphics.SetColor[dc, GraphicsColor.black]; <> IF NOT camera.frame.fullScreen THEN { CSGGraphics.DrawFrame[dc, camera]; }; DrawWireAssembly2[dc, assembly, scene, camera]; }; DrawWireAssembly2: PRIVATE PROC [dc: Graphics.Context, assembly: Assembly, scene: Scene, camera: Camera] = { lightSources: LightSourceList _ scene.lightSources; WITH assembly.object SELECT FROM assems: AssemblyList => { FOR subassemblies: LIST OF Assembly _ assems.list, subassemblies.rest UNTIL subassemblies = NIL DO DrawWireAssembly2[dc: dc, assembly: subassemblies.first, scene: scene, camera: camera]; ENDLOOP; }; mo: MasterObject => { <> mo.class.lineDraw[dc, mo.lineBody, camera, assembly.coordSys]; }; 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; }; CountSurfacesInAssembly: PRIVATE PROC [assembly: Assembly] RETURNS [surfCount: NAT] = { WITH assembly.object SELECT FROM assems: AssemblyList => surfCount _ CountSurfacesInAssemblyList[assems]; mo: MasterObject => surfCount _ mo.class.countSurf[mo]; ENDCASE => ERROR; }; 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; }; PutAssemblyOnQueue: PRIVATE PROC [assembly: Assembly, q: PriorityQueue.Ref, cameraCS: CoordSystem] = { thisSurf: PlanarSurface; cameraNormal: Vector; WITH assembly.object SELECT FROM assems: AssemblyList => PutAssemblyListOnQueue[assems, q, cameraCS]; mo: MasterObject => { surfList: PlanarSurfaceList _ mo.class.getSurf[assembly, cameraCS]; FOR surfList _ surfList, surfList.rest UNTIL surfList = NIL DO thisSurf _ surfList.first; cameraNormal _ Matrix3d.UpdateVectorWithInverse[thisSurf.assembly.coordSys.cameraWRTlocal, thisSurf.normal]; thisSurf.normal _ cameraNormal; <> IF thisSurf.normal[3] >0 THEN PriorityQueue.Insert[q,thisSurf]; ENDLOOP; }; ENDCASE => ERROR; }; -- end of PutAssemblyOnQueue 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]; }; DrawShadedAssembly: PRIVATE PROC [dc: Graphics.Context, assembly: Assembly, scene: Scene, camera: Camera] = { <> <> predictedQueueSize: NAT _ CountSurfacesInAssembly[assembly]; surfaceQueue: PriorityQueue.Ref _ PriorityQueue.Predict[predictedQueueSize, DeeperPlanarSurface]; mo: MasterObject; thisPlanarSurf: PlanarSurface; box: Graphics.Box; mark: Graphics.Mark _ Graphics.Save[dc]; <> PutAssemblyOnQueue[assembly, surfaceQueue, camera.coordSys]; <> box _ Graphics.GetBounds[dc]; SetColor[dc, camera, scene.backgroundColor]; Graphics.DrawBox[dc, box]; <<>> <> IF NOT camera.frame.fullScreen THEN { SetColor[dc, camera, GraphicsColor.black]; CSGGraphics.DrawFrame[dc, camera]; }; <> FOR i: NAT IN[1..PriorityQueue.Size[surfaceQueue]] DO thisPlanarSurf _ NARROW[PriorityQueue.Remove[surfaceQueue]]; mo _ thisPlanarSurf.mo; mo.class.drawSurf[dc, thisPlanarSurf, scene.lightSources, camera]; ENDLOOP; Graphics.Restore[dc, mark]; }; DrawNormalsAssembly: PROC [dc: Graphics.Context, assembly: Assembly, scene: Scene, camera: Camera] = { Graphics.SetColor[dc, GraphicsColor.black]; <> IF NOT camera.frame.fullScreen THEN { CSGGraphics.DrawFrame[dc, camera]; }; DrawNormalsAssembly2[dc, assembly, scene, camera]; }; DrawNormalsAssembly2: PROC [dc: Graphics.Context, assembly: Assembly, scene: Scene, camera: Camera] = { lightSources: LightSourceList _ scene.lightSources; WITH assembly.object 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; }; mo: MasterObject => { <> mo.class.normalsDraw[dc, mo.shadeBody, camera, assembly.coordSys]; }; ENDCASE => ERROR; }; END.