DisplayList3dImplB.mesa
Last edited by Bier on December 22, 1982 12:01 am
Author: Eric Bier on July 3, 1983 2:13 pm (when DisplayList3dImpl overflowed)
DIRECTORY
 CastRays,
 CoordSys,
CSG,
 CSGGraphics,
 DisplayList3d,
 Graphics,
 GraphicsColor,
 Matrix3d,
 PriorityQueue,
 Shading,
 SV2d,
 SVPolygon3d,
 SVTransforms,
 SVVector3d;

DisplayList3dImplB: PROGRAM
IMPORTS CastRays, CSGGraphics, Graphics, GraphicsColor, Matrix3d, PriorityQueue, SVTransforms
EXPORTS DisplayList3d =
BEGIN
Imported Types
Camera: TYPE = CSGGraphics.Camera;
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;
Matrix4by4: TYPE = Matrix3d.Matrix4by4;
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;
DisplayList Types
Databases, Scenes, Assemblies, and Lightsources
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;
Master Object Class Types
MasterObjectClass: TYPE = REF MasterObjectClassObj;
MasterObjectClassObj: TYPE = DisplayList3d.MasterObjectClassObj;
MasterObjectClassList: TYPE = DisplayList3d.MasterObjectClassList;
FileoutProc: TYPE = DisplayList3d.FileoutProc;
FileinProc: TYPE = DisplayList3d.FileinProc;
Master Object Types
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;
Noop Procedures
A master object can use these entries if it doesn't implement one of these procedures
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]};
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
Draw Parts of the Scene Tree
DrawScene: PUBLIC PROC [dc: Graphics.Context, scene: Scene, camera: Camera] = {
mark: Graphics.Mark;
SVTransforms.TellAboutCameraAndWorld[scene.assembly, camera, scene];
Clip the picture to the camera's frame
mark ← Graphics.Save[dc];
CSGGraphics.Clip[dc, camera];
SELECT camera.style FROM
wire => DrawWireAssembly[dc, scene.assembly, scene, camera];
shaded => DrawShadedAssembly[dc, scene.assembly, scene, camera];
normals => DrawNormalsAssembly[dc, scene.assembly, scene, camera];
ENDCASE => SIGNAL NotYetImplemented;
Graphics.Restore[dc, mark];
};
NotYetImplemented: PUBLIC SIGNAL = CODE;
DrawAssembly: PUBLIC PROC [dc: Graphics.Context, assembly: Assembly, scene: Scene, camera: Camera] = {
SVTransforms.TellAboutCameraAndWorld[assembly, camera, scene];
Clip the picture to the camera's frame
CSGGraphics.Clip[dc, camera];
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];
 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 => {
  -- Graphics.SetColor[dc, assembly.color];
  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;
   -- 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;
 }; -- end of PutAssemblyOnQueue
DeeperPlanarSurface: SAFE PROC [x,y: PriorityQueue.Item, data: REFNIL] 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] = {
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;
box: Graphics.Box;
mark: Graphics.Mark ← Graphics.Save[dc];
Now put the surfaces on the queue
PutAssemblyOnQueue[assembly, surfaceQueue, camera.coordSys];
Draw a background color
box ← Graphics.GetBounds[dc];
SetColor[dc, camera, scene.backgroundColor];
Graphics.DrawBox[dc, box];
Take them off the queue in order and draw them
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];
 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 => {
  -- Graphics.SetColor[dc, assembly.color];
  mo.class.normalsDraw[dc, mo.shadeBody, camera, assembly.coordSys];
  -- surfList: PlanarSurfaceList ← mo.class.getSurf[assembly, camera.coordSys];
  -- FOR list: PlanarSurfaceList ← surfList, list.rest UNTIL list = NIL DO
  };
ENDCASE => ERROR;
 };
END.