-- File: BasicObject3dImpl.mesa
-- Last edited by Bier on December 18, 1982 1:35 am
-- Author: Eric Bier on July 3, 1983 2:01 pm
-- Contents: Defines a simple set of objects which can be display with ray casting, line drawing, or shaded planar-surface approximation

DIRECTORY
 BasicObject3d,
 CastRays,
 CoordSys,
CSG,
 CSGGraphics,
 DisplayList3d,
 Graphics,
IO,
 ObjectCast,
 PredefSweeps,
 Rope,
 Shading,
 SV2d,
 SVBoundBox,
 SVFaces,
 SVPolygon2d,
 SVPolygon3d,
 SweepCast,
 SweepGeometry,
 TFI3d,
 TFO3d;

BasicObject3dImpl: PROGRAM
IMPORTS DisplayList3d, IO, ObjectCast, PredefSweeps, SVBoundBox, SVPolygon2d, SVPolygon3d, SweepCast, SweepGeometry, TFI3d, TFO3d
EXPORTS BasicObject3d =
BEGIN


-- GENERAL TYPES

Cone: TYPE = SVFaces.Cone;
DiskRing: TYPE = SVFaces.DiskRing;
Cylinder: TYPE = SVFaces.Cylinder;

BoundHedron: TYPE = REF BoundHedronObj;
BoundHedronObj: TYPE = SVBoundBox.BoundHedronObj;
Camera: TYPE = CSGGraphics.Camera;
LinearMeshArray: TYPE = SweepGeometry.LinearMeshArray;
RevoluteMeshArray: TYPE = SweepGeometry.RevoluteMeshArray;
Path: TYPE = REF PathObj;
PathObj: TYPE = SV2d.PathObj;
Point2d: TYPE = SV2d.Point2d;
Poly3d: TYPE = REF Poly3dObj;
Poly3dObj: TYPE = SVPolygon3d.Poly3dObj;
Polygon: TYPE = REF PolygonObj;
PolygonObj: TYPE = SV2d.PolygonObj;
LinearMesh: TYPE = REF LinearMeshRecord;
LinearMeshRecord: TYPE = SweepGeometry.LinearMeshRecord;
RevoFace: TYPE = SweepCast.RevoFace;
RevoluteMesh: TYPE = REF RevoluteMeshRecord;
RevoluteMeshRecord: TYPE = SweepGeometry.RevoluteMeshRecord;
SubBoxesBody: TYPE = REF SubBoxesBodyObj;
SubBoxesBodyObj: TYPE = SweepCast.SubBoxesBodyObj;
ToroidalMesh: TYPE = REF ToroidalMeshRecord;
ToroidalMeshRecord: TYPE = SweepGeometry.ToroidalMeshRecord;


-- SHADING TYPES

BoundBox: TYPE = SVBoundBox.BoundBox;
CoordSystem: TYPE = REF CoordSysObj;
CoordSysObj: TYPE = CoordSys.CoordSysObj;
LightSourceList: TYPE = Shading.LightSourceList;
PlanarSurface: TYPE = REF PlanarSurfaceObj;
PlanarSurfaceObj: TYPE = DisplayList3d.PlanarSurfaceObj;
PlanarSurfaceList: TYPE = DisplayList3d.PlanarSurfaceList;


-- RAY CASTING TYPES

Classification: TYPE = REF ClassificationObj;
ClassificationObj: TYPE = CastRays.ClassificationObj;

Ray: TYPE = REF RayObj;
RayObj: TYPE = CSG.RayObj;


Assembly: TYPE = REF AssemblyObj;
AssemblyObj: TYPE = DisplayList3d.AssemblyObj;

MasterObject: TYPE = REF MasterObjectRec;
MasterObjectRec: TYPE = DisplayList3d.MasterObjectRec;

MasterObjectClass: TYPE = REF MasterObjectClassObj;
MasterObjectClassObj: TYPE = DisplayList3d.MasterObjectClassObj;
MasterObjectClassList: TYPE = DisplayList3d.MasterObjectClassList; -- LIST OF MasterObjectClass


RayCastProc: TYPE = CSG.RayCastProc;
PreprocessProc: TYPE = DisplayList3d.PreprocessProc;
LineDrawProc: TYPE = DisplayList3d.LineDrawProc;
NormalsDrawProc: TYPE = DisplayList3d.NormalsDrawProc;
CountPlanarSurfacesProc: TYPE = DisplayList3d.CountPlanarSurfacesProc;
GetPlanarSurfacesProc: TYPE = DisplayList3d.GetPlanarSurfacesProc;
DrawPlanarSurfaceProc: TYPE = DisplayList3d.DrawPlanarSurfaceProc;
DrawSubBoxesProc: TYPE = DisplayList3d.DrawSubBoxesProc;

SurfaceArray: TYPE = REF SurfaceArrayObj;
SurfaceArrayObj: TYPE = CSG.SurfaceArrayObj;

Primitive: TYPE = REF PrimitiveObj;
PrimitiveObj: TYPE = CSG.PrimitiveObj;

Composite: TYPE = REF CompositeObj;
CompositeObj: TYPE = CSG.CompositeObj;

RectSurface: TYPE = REF RectSurfaceObj;
RectSurfaceObj: TYPE = ObjectCast.RectSurfaceObj;
-- RECORD [prim: Primitive, rectType: RectType];
TubeSurface: TYPE = REF TubeSurfaceObj;
TubeSurfaceObj: TYPE = ObjectCast.TubeSurfaceObj;
-- RECORD [prim: Primitive];
DiskSurface: TYPE = REF DiskSurfaceObj;
DiskSurfaceObj: TYPE = ObjectCast.DiskSurfaceObj;
-- RECORD [prim: Primitive, diskType: DiskType];
ShellSurface: TYPE = REF ShellSurfaceObj;
ShellSurfaceObj: TYPE = ObjectCast.ShellSurfaceObj;
-- RECORD [prim: Primitive];
ConeSurface: TYPE = REF ConeSurfaceObj;
ConeSurfaceObj: TYPE = ObjectCast.ConeSurfaceObj;
-- RECORD [prim: Primitive];
ToroidalSurface: TYPE = REF ToroidalSurfaceObj;
ToroidalSurfaceObj: TYPE = ObjectCast.ToroidalSurfaceObj;
-- RECORD [prim: Primitive];

-- GLOBAL VARIABLES

-- Basic Shapes

SphereRec: TYPE = REF SphereRecObj;
SphereRecObj: TYPE = BasicObject3d.SphereRecObj;

BlockRec: TYPE = REF BlockRecObj;
BlockRecObj: TYPE = BasicObject3d.BlockRecObj;

CylinderRec: TYPE = REF CylinderRecObj;
CylinderRecObj: TYPE = BasicObject3d.CylinderRecObj;

ConeRec: TYPE = REF ConeRecObj;
ConeRecObj: TYPE = BasicObject3d.ConeRecObj;

TorusRec: TYPE = REF TorusRecObj;
TorusRecObj: TYPE = BasicObject3d.TorusRecObj;

sphereClass, blockClass, cylinderClass, coneClass, torusClass, linClass, revoClass: MasterObjectClass;

WrongTypeOfData: PUBLIC SIGNAL = CODE;

SphereBody: PRIVATE PROC RETURNS [sphereRec: SphereRec] = {
 sphereRec ← NEW[SphereRecObj];
 sphereRec.radius ← 1;
 };

SphereMakeMasterObject: PUBLIC PROC [name: Rope.ROPE] RETURNS [mo: MasterObject] = {
 mainBody: SphereRec ← SphereBody[];
 lineBody: REF ANY ← PredefSweeps.GetUnitSphere[];
 shadeBody: REF ANY ← lineBody;
 rayCastBody: REF ANY ← SphereGetRayCastBody[];
 mo ← DisplayList3d.CreateMasterObject[name, sphereClass, mainBody, lineBody, shadeBody, rayCastBody];
 };

SphereBoundHedron: PUBLIC PROC [mo: MasterObject] RETURNS [hedron: BoundHedron] = {
 hedron ← SVBoundBox.HexagonalBoundHedron[1, 1];
 };

SphereGetRayCastBody: PRIVATE PROC [] RETURNS [surfaceArray: SurfaceArray] = {
 shellS: ShellSurface;
 surfaceArray ← NEW[SurfaceArrayObj];
 shellS ← NEW[ShellSurfaceObj];
 surfaceArray[1] ← shellS;
 };

SphereRayCast: PUBLIC PROC [cameraPoint: Point2d, localRay: Ray, masterObject: REF ANY, prim: Primitive] RETURNS [class: Classification] = {
 mo: MasterObject ← NARROW[masterObject];
RETURN[ObjectCast.SphereCast[localRay, NARROW[mo.rayCastBody], prim]];
 };

SphereRayCastNoBBoxes: PUBLIC PROC [localRay: Ray, masterObject: REF ANY, prim: Primitive] RETURNS [class: Classification] = {
 mo: MasterObject ← NARROW[masterObject];
RETURN[ObjectCast.SphereCast[localRay, NARROW[mo.rayCastBody], prim]];
 };

SphereLineDraw: PUBLIC PROC[dc: Graphics.Context, data: REF ANY, camera: Camera, localCS: CoordSystem] = {
 revMesh: RevoluteMesh;
IF ISTYPE[data, RevoluteMesh]
  THEN revMesh ← NARROW[data]
  ELSE SIGNAL WrongTypeOfData;
 SweepGeometry.LineDrawRevoluteSweep[dc, revMesh, camera, localCS];
 };
SphereDrawNormals: PUBLIC PROC[dc: Graphics.Context, data: REF ANY, camera: Camera, localCS: CoordSystem] = {
 revMesh: RevoluteMesh;
IF ISTYPE[data, RevoluteMesh]
  THEN revMesh ← NARROW[data]
  ELSE SIGNAL WrongTypeOfData;
 SweepGeometry.DrawNormalsRevoluteSweep[dc, revMesh, camera, localCS];
 };
SphereCountSurf: PUBLIC PROC [masterObject: MasterObject] RETURNS [len: NAT] = {
 revMesh: RevoluteMesh ← NARROW[masterObject.shadeBody];
 len ← SweepGeometry.CountPlanarSurfacesRevoluteSweep[revMesh];
 };
SphereCountVert: PUBLIC PROC [masterObject: MasterObject] RETURNS [len: NAT] = {
 revMesh: RevoluteMesh ← NARROW[masterObject.shadeBody];
 len ← SweepGeometry.CountVerticesRevoluteSweep[revMesh];
 };
SphereGetSurf: PUBLIC PROC [assembly: Assembly, camera: CoordSystem] RETURNS [psl: PlanarSurfaceList] = {
 masterObject: MasterObject ← NARROW[assembly.object];
 revMesh: RevoluteMesh ← NARROW[masterObject.shadeBody];
 psl ← SweepGeometry.PlanarSurfacesRevoluteSweep[revMesh, assembly, camera];
 };
SphereDrawSurf: PUBLIC PROC [dc: Graphics.Context, ps: PlanarSurface, lightSources: LightSourceList, camera: Camera] = {
 SweepGeometry.DrawPlanarSurfaceRevoluteSweep[dc, ps, lightSources, camera];
 };

SphereFileout: PUBLIC PROC [f: IO.STREAM, mo: MasterObject] = {
-- spheres can be recovered from scratch.
 f.PutChar[IO.TAB];
 f.PutF["data: procedural\n"];
 };
SphereFilein: PUBLIC PROC [f: IO.STREAM, name: Rope.ROPE] RETURNS [mo: MasterObject] = {
 TFI3d.ReadChar[f, IO.TAB];
 TFI3d.ReadRope[f, "data: procedural"];
 TFI3d.ReadReturn[f];
 mo ← SphereMakeMasterObject[name];
 };

BlockBody: PRIVATE PROC RETURNS [blockRec: BlockRec] = {
 blockRec ← NEW[BlockRecObj];
 blockRec.x ← 2; blockRec.y ← 2; blockRec.z ← 2;
 };

BlockMakeMasterObject: PUBLIC PROC [name: Rope.ROPE] RETURNS [mo: MasterObject] = {
 mainBody: BlockRec ← BlockBody[];
 lineBody: REF ANY ← PredefSweeps.GetUnitCube[];
 shadeBody: REF ANY ← lineBody;
 rayCastBody: REF ANYBlockGetRayCastBody[];
 mo ← DisplayList3d.CreateMasterObject[name, blockClass, mainBody, lineBody, shadeBody, rayCastBody];
 };

BlockBoundHedron: PUBLIC PROC [mo: MasterObject] RETURNS [hedron: BoundHedron] = {
 hedron ← SVBoundBox.RectangularBoundHedron[2, 2, 2];
 };

BlockGetRayCastBody: PRIVATE PROC [] RETURNS [surfaceArray: SurfaceArray] = {
 upS, downS, frontS, backS, rightS, leftS: RectSurface;
 surfaceArray ← NEW[SurfaceArrayObj];
 upS ← NEW[RectSurfaceObj ← [up]];
 downS ← NEW[RectSurfaceObj ← [down]];
 frontS ← NEW[RectSurfaceObj ← [front]];
 backS ← NEW[RectSurfaceObj ← [back]];
 rightS ← NEW[RectSurfaceObj ← [right]];
 leftS ← NEW[RectSurfaceObj ← [left]];
 surfaceArray[1] ← upS;
 surfaceArray[2] ← downS;
 surfaceArray[3] ← frontS;
 surfaceArray[4] ← backS;
 surfaceArray[5] ← rightS;
 surfaceArray[6] ← leftS;
 }; -- end of BlockGetRayCastBody

BlockRayCast: PUBLIC PROC [cameraPoint: Point2d, localRay: Ray, masterObject: REF ANY, prim: Primitive] RETURNS [class: Classification] = {
 mo: MasterObject ← NARROW[masterObject];
RETURN[ObjectCast.BlockCast[localRay, NARROW[mo.rayCastBody], prim]];
 };

BlockRayCastNoBBoxes: PUBLIC PROC [localRay: Ray, masterObject: REF ANY, prim: Primitive] RETURNS [class: Classification] = {
 mo: MasterObject ← NARROW[masterObject];
RETURN[ObjectCast.BlockCast[localRay, NARROW[mo.rayCastBody], prim]];
 };

BlockLineDraw: PUBLIC PROC[dc: Graphics.Context, data: REF ANY, camera: Camera, localCS: CoordSystem] = {
 linMesh: LinearMesh;
IF ISTYPE[data, LinearMesh]
  THEN linMesh ← NARROW[data]
  ELSE SIGNAL WrongTypeOfData;
 SweepGeometry.LineDrawLinearSweep[dc, linMesh, camera, localCS];
 };
BlockDrawNormals: PUBLIC PROC[dc: Graphics.Context, data: REF ANY, camera: Camera, localCS: CoordSystem] = {
 linMesh: LinearMesh;
IF ISTYPE[data, LinearMesh]
  THEN linMesh ← NARROW[data]
  ELSE SIGNAL WrongTypeOfData;
 SweepGeometry.DrawNormalsLinearSweep[dc, linMesh, camera, localCS];
 };
BlockCountSurf: PUBLIC PROC [masterObject: MasterObject] RETURNS [len: NAT] = {
 linMesh: LinearMesh ← NARROW[masterObject.shadeBody];
 len ← SweepGeometry.CountPlanarSurfacesLinearSweep[linMesh];
 };
BlockCountVert: PUBLIC PROC [masterObject: MasterObject] RETURNS [len: NAT] = {
 linMesh: LinearMesh ← NARROW[masterObject.shadeBody];
 len ← SweepGeometry.CountVerticesLinearSweep[linMesh];
 };
BlockGetSurf: PUBLIC PROC [assembly: Assembly, camera: CoordSystem] RETURNS [psl: PlanarSurfaceList] = {
 masterObject: MasterObject ← NARROW[assembly.object];
 linMesh: LinearMesh ← NARROW[masterObject.shadeBody];
 psl ← SweepGeometry.PlanarSurfacesLinearSweep[linMesh, assembly, camera];
 };
BlockDrawSurf: PUBLIC PROC [dc: Graphics.Context, ps: PlanarSurface, lightSources: LightSourceList, camera: Camera] = {
 SweepGeometry.DrawPlanarSurfaceLinearSweep[dc, ps, lightSources, camera];
 };

BlockFilein: PUBLIC PROC [f: IO.STREAM, name: Rope.ROPE] RETURNS [mo: MasterObject] = {
 TFI3d.ReadRope[f, " data: procedural"];
 TFI3d.ReadReturn[f];
 mo ← BlockMakeMasterObject[name];
 };
BlockFileout: PUBLIC PROC [f: IO.STREAM, mo: MasterObject] = {
-- blocks can be recovered from scratch.
 f.PutF[" data: procedural\n"];
 };

CylinderBody: PRIVATE PROC RETURNS [cylinderRec: CylinderRec] = {
 cylinderRec ← NEW[CylinderRecObj];
 cylinderRec.radius ← 1; cylinderRec.height ← 2;
 };

CylinderMakeMasterObject: PUBLIC PROC [name: Rope.ROPE] RETURNS [mo: MasterObject] = {
 mainBody: CylinderRec ← CylinderBody[];
 lineBody: REF ANY ← PredefSweeps.GetUnitCylinder[];
 shadeBody: REF ANY ← lineBody;
 rayCastBody: REF ANY ← CylinderGetRayCastBody[];
 mo ← DisplayList3d.CreateMasterObject[name, cylinderClass, mainBody, lineBody, shadeBody, rayCastBody];
 };

CylinderBoundHedron: PUBLIC PROC [mo: MasterObject] RETURNS [hedron: BoundHedron] = {
 hedron ← SVBoundBox.HexagonalBoundHedron[1,1];
 };

CylinderGetRayCastBody: PRIVATE PROC [] RETURNS [surfaceArray: SurfaceArray] = {
 topS, bottomS: DiskSurface;
 tubeS: TubeSurface;
 surfaceArray ← NEW[SurfaceArrayObj];
 topS ← NEW[DiskSurfaceObj ← [top]];
 bottomS ← NEW[DiskSurfaceObj ← [bottom]];
 tubeS ← NEW[TubeSurfaceObj];
 surfaceArray[1] ← topS;
 surfaceArray[2] ← bottomS;
 surfaceArray[3] ← tubeS;
 }; -- end of CylinderGetRayCastBody
  
CylinderRayCast: PUBLIC PROC [cameraPoint: Point2d, localRay: Ray, masterObject: REF ANY, prim: Primitive] RETURNS [class: Classification] = {
 mo: MasterObject ← NARROW[masterObject];
RETURN[ObjectCast.CylinderCast[localRay, NARROW[mo.rayCastBody], prim]];
 };

CylinderRayCastNoBBoxes: PUBLIC PROC [localRay: Ray, masterObject: REF ANY, prim: Primitive] RETURNS [class: Classification] = {
 mo: MasterObject ← NARROW[masterObject];
RETURN[ObjectCast.CylinderCast[localRay, NARROW[mo.rayCastBody], prim]];
 };

CylinderLineDraw: PUBLIC PROC[dc: Graphics.Context, data: REF ANY, camera: Camera, localCS: CoordSystem] = {
 revMesh: RevoluteMesh;
IF ISTYPE[data, RevoluteMesh]
  THEN revMesh ← NARROW[data]
  ELSE SIGNAL WrongTypeOfData;
 SweepGeometry.LineDrawRevoluteSweep[dc, revMesh, camera, localCS];
 };
CylinderDrawNormals: PUBLIC PROC[dc: Graphics.Context, data: REF ANY, camera: Camera, localCS: CoordSystem] = {
 revMesh: RevoluteMesh;
IF ISTYPE[data, RevoluteMesh]
  THEN revMesh ← NARROW[data]
  ELSE SIGNAL WrongTypeOfData;
 SweepGeometry.DrawNormalsRevoluteSweep[dc, revMesh, camera, localCS];
 };
CylinderCountSurf: PUBLIC PROC [masterObject: MasterObject] RETURNS [len: NAT] = {
 revMesh: RevoluteMesh ← NARROW[masterObject.shadeBody];
 len ← SweepGeometry.CountPlanarSurfacesRevoluteSweep[revMesh];
 };
CylinderCountVert: PUBLIC PROC [masterObject: MasterObject] RETURNS [len: NAT] = {
 revMesh: RevoluteMesh ← NARROW[masterObject.shadeBody];
 len ← SweepGeometry.CountVerticesRevoluteSweep[revMesh];
 };
CylinderGetSurf: PUBLIC PROC [assembly: Assembly, camera: CoordSystem] RETURNS [psl: PlanarSurfaceList] = {
 masterObject: MasterObject ← NARROW[assembly.object];
 revMesh: RevoluteMesh ← NARROW[masterObject.shadeBody];
 psl ← SweepGeometry.PlanarSurfacesRevoluteSweep[revMesh, assembly, camera];
 };
CylinderDrawSurf: PUBLIC PROC [dc: Graphics.Context, ps: PlanarSurface, lightSources: LightSourceList, camera: Camera] = {
 SweepGeometry.DrawPlanarSurfaceRevoluteSweep[dc, ps, lightSources, camera];
 };

CylinderFilein: PUBLIC PROC [f: IO.STREAM, name: Rope.ROPE] RETURNS [mo: MasterObject] = {
 TFI3d.ReadRope[f, " data: procedural"];
 TFI3d.ReadReturn[f];
 mo ← CylinderMakeMasterObject[name];
 };
CylinderFileout: PUBLIC PROC [f: IO.STREAM, mo: MasterObject] = {
-- cylinder can be recovered from scratch.
 f.PutF[" data: procedural\n"];
 };

ConeBody: PRIVATE PROC RETURNS [coneRec: ConeRec] = {
 coneRec ← NEW[ConeRecObj];
 coneRec.radius ← 1; coneRec.height ← 1;
 };

ConeMakeMasterObject: PUBLIC PROC [name: Rope.ROPE] RETURNS [mo: MasterObject] = {
 mainBody: ConeRec ← ConeBody[];
 lineBody: REF ANY ← PredefSweeps.GetUnitCone[];
 shadeBody: REF ANY ← lineBody;
 rayCastBody: REF ANY ← ConeGetRayCastBody[];
 mo ← DisplayList3d.CreateMasterObject[name, coneClass, mainBody, lineBody, shadeBody, rayCastBody];
 };

ConeBoundHedron: PUBLIC PROC [mo: MasterObject] RETURNS [hedron: BoundHedron] = {
 hedron ← SVBoundBox.HexPyramidBoundHedron[1,1];
 };

ConeGetRayCastBody: PRIVATE PROC [] RETURNS [surfaceArray: SurfaceArray] = {
 coneS: ConeSurface;
 diskS: DiskSurface;
 surfaceArray ← NEW[SurfaceArrayObj];
 coneS ← NEW[ConeSurfaceObj];
 diskS ← NEW[DiskSurfaceObj];
 surfaceArray[1] ← coneS;
 surfaceArray[2] ← diskS;
 }; -- end of ConeGetRayCastBody
   
ConeRayCast: PUBLIC PROC [cameraPoint: Point2d, localRay: Ray, masterObject: REF ANY, prim: Primitive] RETURNS [class: Classification] = {
 mo: MasterObject ← NARROW[masterObject];
RETURN[ObjectCast.ConeCast[localRay, NARROW[mo.rayCastBody], prim]];};

ConeRayCastNoBBoxes: PUBLIC PROC [localRay: Ray, masterObject: REF ANY, prim: Primitive] RETURNS [class: Classification] = {
 mo: MasterObject ← NARROW[masterObject];
RETURN[ObjectCast.ConeCast[localRay, NARROW[mo.rayCastBody], prim]];};

ConeLineDraw: PUBLIC PROC[dc: Graphics.Context, data: REF ANY, camera: Camera, localCS: CoordSystem] = {
 revMesh: RevoluteMesh;
IF ISTYPE[data, RevoluteMesh]
  THEN revMesh ← NARROW[data]
  ELSE SIGNAL WrongTypeOfData;
 SweepGeometry.LineDrawRevoluteSweep[dc, revMesh, camera, localCS];
 };
ConeDrawNormals: PUBLIC PROC[dc: Graphics.Context, data: REF ANY, camera: Camera, localCS: CoordSystem] = {
 revMesh: RevoluteMesh;
IF ISTYPE[data, RevoluteMesh]
  THEN revMesh ← NARROW[data]
  ELSE SIGNAL WrongTypeOfData;
 SweepGeometry.DrawNormalsRevoluteSweep[dc, revMesh, camera, localCS];
 };
ConeCountSurf: PUBLIC PROC [masterObject: MasterObject] RETURNS [len: NAT] = {
 revMesh: RevoluteMesh ← NARROW[masterObject.shadeBody];
 len ← SweepGeometry.CountPlanarSurfacesRevoluteSweep[revMesh];
 };

ConeCountVert: PUBLIC PROC [masterObject: MasterObject] RETURNS [len: NAT] = {
 revMesh: RevoluteMesh ← NARROW[masterObject.shadeBody];
 len ← SweepGeometry.CountVerticesRevoluteSweep[revMesh];
 };

ConeGetSurf: PUBLIC PROC [assembly: Assembly, camera: CoordSystem] RETURNS [psl: PlanarSurfaceList] = {
 masterObject: MasterObject ← NARROW[assembly.object];
 revMesh: RevoluteMesh ← NARROW[masterObject.shadeBody];
 psl ← SweepGeometry.PlanarSurfacesRevoluteSweep[revMesh, assembly, camera];
 };
ConeDrawSurf: PUBLIC PROC [dc: Graphics.Context, ps: PlanarSurface, lightSources: LightSourceList, camera: Camera] = {
 SweepGeometry.DrawPlanarSurfaceRevoluteSweep[dc, ps, lightSources, camera];
 };

ConeFilein: PUBLIC PROC [f: IO.STREAM, name: Rope.ROPE] RETURNS [mo: MasterObject] = {
 TFI3d.ReadRope[f, " data: procedural"];
 TFI3d.ReadReturn[f];
 mo ← ConeMakeMasterObject[name];
 };
ConeFileout: PUBLIC PROC [f: IO.STREAM, mo: MasterObject] = {
-- cone can be recovered from scratch.
 f.PutF[" data: procedural\n"];
 };

TorusBody: PRIVATE PROC [bigRadius: REAL, sectionRadius: REAL] RETURNS [torusRec: TorusRec] = {
 torusRec ← NEW[TorusRecObj];
 torusRec.bigRadius ← bigRadius;
 torusRec.sectionRadius ← sectionRadius;
 };

TorusMakeMasterObject: PUBLIC PROC [name: Rope.ROPE, bigRadius: REAL, sectionRadius: REAL] RETURNS [mo: MasterObject] = {
 mainBody: TorusRec ← TorusBody[bigRadius, sectionRadius];
 lineBody: REF ANY ← PredefSweeps.CreateTorus[mainBody.bigRadius, mainBody.sectionRadius];
 shadeBody: REF ANY ← lineBody;
 rayCastBody: REF ANYTorusGetRayCastBody[];
 mo ← DisplayList3d.CreateMasterObject[name, torusClass, mainBody, lineBody, shadeBody, rayCastBody];
 };

TorusBoundHedron: PUBLIC PROC [mo: MasterObject] RETURNS [hedron: BoundHedron] = {
 torusRec: TorusRec ← NARROW[mo.mainBody];
 hedron ←
  SVBoundBox.HexagonalBoundHedron[torusRec.bigRadius + torusRec.sectionRadius,
   torusRec.sectionRadius];
 };

TorusGetRayCastBody
: PRIVATE PROC [] RETURNS [surfaceArray: SurfaceArray] = {
 torusS: ToroidalSurface;
 surfaceArray ← NEW[SurfaceArrayObj];
 torusS ← NEW[ToroidalSurfaceObj];
 surfaceArray[1] ← torusS;
 }; -- end of TorusGetRayCastBody
  
TorusRayCast: PUBLIC PROC [cameraPoint: Point2d, localRay: Ray, masterObject: REF ANY, prim: Primitive] RETURNS [class: Classification] = {
 mo: MasterObject ← NARROW[masterObject];
 surfaceArray: SurfaceArray ← NARROW[mo.rayCastBody];
RETURN[ObjectCast.ToroidCast[localRay, prim, mo.mainBody, surfaceArray[1]]];
 };

TorusRayCastNoBBoxes: PUBLIC PROC [localRay: Ray, masterObject: REF ANY, prim: Primitive] RETURNS [class: Classification] = {
 mo: MasterObject ← NARROW[masterObject];
 surfaceArray: SurfaceArray ← NARROW[mo.rayCastBody];
RETURN[ObjectCast.ToroidCast[localRay, prim, mo.mainBody, surfaceArray[1]]];
 };

TorusLineDraw: PUBLIC PROC[dc: Graphics.Context, data: REF ANY, camera: Camera, localCS: CoordSystem] = {
 torMesh: ToroidalMesh;
IF ISTYPE[data, ToroidalMesh]
  THEN torMesh ← NARROW[data]
  ELSE SIGNAL WrongTypeOfData;
 SweepGeometry.LineDrawToroidalSweep[dc, torMesh, camera, localCS];
 };
TorusDrawNormals: PUBLIC PROC[dc: Graphics.Context, data: REF ANY, camera: Camera, localCS: CoordSystem] = {
 torMesh: ToroidalMesh;
IF ISTYPE[data, ToroidalMesh]
  THEN torMesh ← NARROW[data]
  ELSE SIGNAL WrongTypeOfData;
 SweepGeometry.DrawNormalsToroidalSweep[dc, torMesh, camera, localCS];
 };

TorusCountSurf: PUBLIC PROC [masterObject: MasterObject] RETURNS [len: NAT] = {
 torMesh: ToroidalMesh ← NARROW[masterObject.shadeBody];
 len ← SweepGeometry.CountPlanarSurfacesToroidalSweep[torMesh];
 };
TorusCountVert: PUBLIC PROC [masterObject: MasterObject] RETURNS [len: NAT] = {
 torMesh: ToroidalMesh ← NARROW[masterObject.shadeBody];
 len ← SweepGeometry.CountVerticesToroidalSweep[torMesh];
 };
TorusGetSurf: PUBLIC PROC [assembly: Assembly, camera: CoordSystem] RETURNS [psl: PlanarSurfaceList] = {
 masterObject: MasterObject ← NARROW[assembly.object];
 torMesh: ToroidalMesh ← NARROW[masterObject.shadeBody];
 psl ← SweepGeometry.PlanarSurfacesToroidalSweep[torMesh, assembly, camera];
 };
TorusDrawSurf: PUBLIC PROC [dc: Graphics.Context, ps: PlanarSurface, lightSources: LightSourceList, camera: Camera] = {
 SweepGeometry.DrawPlanarSurfaceToroidalSweep[dc, ps, lightSources, camera];
 };

TorusFilein: PUBLIC PROC [f: IO.STREAM, name: Rope.ROPE] RETURNS [mo: MasterObject] = {
 bigRadius, sectionRadius: REAL;
 TFI3d.ReadBlankAndRope[f, "bigRadius:"];
 bigRadius ← TFI3d.ReadBlankAndReal[f];
 TFI3d.ReadBlankAndRope[f, ","];
 TFI3d.ReadBlankAndRope[f, "sectionRadius:"];
 sectionRadius ← TFI3d.ReadBlankAndReal[f];
 mo ← TorusMakeMasterObject[name, bigRadius, sectionRadius];
 };

TorusFileout: PUBLIC PROC [f: IO.STREAM, mo: MasterObject] = {
-- torus can be recovered from bigRadius and sectionRadius.
 torusRec: TorusRec ← NARROW[mo.mainBody];
 f.PutF[" bigRadius: %g, sectionRadius: %g\n", [real[torusRec.bigRadius]],
  [real[torusRec.sectionRadius]] ];
 }; -- end of TorusFileout

LinSweepMakeMasterObject: PUBLIC PROC [name: Rope.ROPE, linMesh: LinearMesh] RETURNS [mo: MasterObject] = {
 mainBody: REF ANYNIL;
 lineBody: REF ANY ← linMesh;
 shadeBody: REF ANY ← lineBody;
 rayCastBody: REF ANY ← LinSweepGetRayCastBody[linMesh];
 mo ← DisplayList3d.CreateMasterObject[name, linClass, mainBody, lineBody, shadeBody, rayCastBody];
 };

LinSweepBoundHedron: PUBLIC PROC [masterObject: MasterObject] RETURNS [hedron: BoundHedron] = {
 linMesh: LinearMesh ← NARROW[masterObject.lineBody];
 vertCount: NAT ← 2*linMesh.len;
 hedron ← SVBoundBox.CreateBoundHedron[vertCount];
FOR i: NAT IN[1..linMesh.len] DO
  FOR j: NAT IN[1..2] DO
   SVBoundBox.AddBoundHedronPoint[hedron, linMesh.array[i][j]];
  ENDLOOP;
ENDLOOP;
 };

LinSweepFaces: TYPE = SweepCast.LinSweepFaces;
LinSweepHint: TYPE = REF LinSweepHintObj;
LinSweepHintObj: TYPE = RECORD [linMesh: LinearMesh, faces: LinSweepFaces];

LinSweepGetRayCastBody: PRIVATE PROC [linMesh: LinearMesh] RETURNS [hint: LinSweepHint] = {
 hint ← NEW[LinSweepHintObj];
 hint.linMesh ← linMesh;
 hint.faces ← SweepCast.MakeLinSweepFaces[linMesh];
 };

GetLinSweepData: PUBLIC PROC RETURNS [linMesh: LinearMesh] = {
 linMesh ← PredefSweeps.GetUnitCube[]; -- for now.
 };

LinSweepRayCast: PUBLIC PROC [cameraPoint: Point2d, localRay: Ray, masterObject: REF ANY, prim: Primitive] RETURNS [class: Classification] = {
 mo: MasterObject ← NARROW[masterObject];
 rayCastBody: LinSweepHint ← NARROW[mo.rayCastBody];
 class ← SweepCast.LinCast[localRay, prim, rayCastBody.linMesh, rayCastBody.faces];
 };

LinSweepRayCastNoBBoxes: PUBLIC PROC [localRay: Ray, masterObject: REF ANY, prim: Primitive] RETURNS [class: Classification] = {
 mo: MasterObject ← NARROW[masterObject];
 rayCastBody: LinSweepHint ← NARROW[mo.rayCastBody];
 class ← SweepCast.LinCast[localRay, prim, rayCastBody.linMesh, rayCastBody.faces];
 };

LinSweepLineDraw: PUBLIC PROC[dc: Graphics.Context, data: REF ANY, camera: Camera, localCS: CoordSystem] = {
 linMesh: LinearMesh;
IF ISTYPE[data, LinearMesh]
  THEN linMesh ← NARROW[data]
  ELSE SIGNAL WrongTypeOfData;
 SweepGeometry.LineDrawLinearSweep[dc, linMesh, camera, localCS];
 };
LinSweepDrawNormals: PUBLIC PROC[dc: Graphics.Context, data: REF ANY, camera: Camera, localCS: CoordSystem] = {
 linMesh: LinearMesh;
IF ISTYPE[data, LinearMesh]
  THEN linMesh ← NARROW[data]
  ELSE SIGNAL WrongTypeOfData;
 SweepGeometry.DrawNormalsLinearSweep[dc, linMesh, camera, localCS];
 };
LinSweepCountSurf: PUBLIC PROC [masterObject: MasterObject] RETURNS [len: NAT] = {
 linMesh: LinearMesh ← NARROW[masterObject.shadeBody];
 len ← SweepGeometry.CountPlanarSurfacesLinearSweep[linMesh];
 };
LinSweepCountVert: PUBLIC PROC [masterObject: MasterObject] RETURNS [len: NAT] = {
 linMesh: LinearMesh ← NARROW[masterObject.shadeBody];
 len ← SweepGeometry.CountVerticesLinearSweep[linMesh];
 };
LinSweepGetSurf: PUBLIC PROC [assembly: Assembly, camera: CoordSystem] RETURNS [psl: PlanarSurfaceList] = {
 masterObject: MasterObject ← NARROW[assembly.object];
 linMesh: LinearMesh ← NARROW[masterObject.shadeBody];
 psl ← SweepGeometry.PlanarSurfacesLinearSweep[linMesh, assembly, camera];
 };
LinSweepDrawSurf: PUBLIC PROC [dc: Graphics.Context, ps: PlanarSurface, lightSources: LightSourceList, camera: Camera] = {
 SweepGeometry.DrawPlanarSurfaceLinearSweep[dc, ps, lightSources, camera];
 };

LinearFileout: PUBLIC PROC [f: IO.STREAM, mo: MasterObject] = {
 linMesh: LinearMesh ← NARROW[mo.lineBody];
 lma: LinearMeshArray ← linMesh.array;
 len: NAT ← linMesh.len;
 f.PutF["name: %g\n",[rope[mo.name]]];
-- assume that the defining contour has not been rotated. Output elements [i][1]
 f.PutF["frontDepth: %g, backDepth: %g\n",[real[lma[1][1][3]]],[real[lma[1][2][3]]]];
 f.PutF["DataPoints [%g]: ",[integer[len]]];
FOR i: NAT IN[1..len-1] DO
  TFO3d.FileoutPoint3dAsPoint2d[f, lma[i][1]];
  f.PutF[","];
ENDLOOP;
 TFO3d.FileoutPoint3dAsPoint2d[f, lma[len][1]];
 f.PutChar[IO.CR];
 };

LinearFilein: PUBLIC PROC [f: IO.STREAM, name: Rope.ROPE] RETURNS [mo: MasterObject] = {
 count: NAT;
 frontDepth, backDepth: REAL;
 poly: Polygon;
 instanceName: Rope.ROPE;
 linMesh: LinearMesh;
 TFI3d.ReadRope[f, "name: "];
 instanceName ← TFI3d.ReadWord[f];
 TFI3d.ReadReturn[f];
 TFI3d.ReadRope[f, "frontDepth: "];
 frontDepth ← TFI3d.ReadReal[f];
 TFI3d.ReadRope[f, ", backDepth: "];
 backDepth ← TFI3d.ReadReal[f];
 TFI3d.ReadReturn[f];
 TFI3d.ReadRope[f, "DataPoints ["];
 count ← TFI3d.ReadNAT[f];
 TFI3d.ReadRope[f, "]: "];
 poly ← SVPolygon2d.CreatePoly[count];
FOR i: NAT IN[1..count-1] DO
  poly ← SVPolygon2d.PutPolyPoint[poly, i-1, TFI3d.ReadPoint2d[f]];
  TFI3d.ReadRope[f, ","];
ENDLOOP;
 poly ← SVPolygon2d.PutPolyPoint[poly, count-1, TFI3d.ReadPoint2d[f]];
 TFI3d.ReadReturn[f];
 linMesh ← SweepGeometry.LinearSweep[poly, frontDepth, backDepth];
 mo ← LinSweepMakeMasterObject[name, linMesh];
 };

RevoSweepMakeMasterObject: PUBLIC PROC [name: Rope.ROPE, revMesh: RevoluteMesh] RETURNS [mo: MasterObject] = {
 mainBody: REF ANYNIL;
 lineBody: REF ANY ← revMesh;
 shadeBody: REF ANY ← lineBody;
 rayCastBody: REF ANY ← RevoSweepGetRayCastBody[revMesh];
 mo ← DisplayList3d.CreateMasterObject[name, revoClass, mainBody, lineBody, shadeBody, rayCastBody];
 };

RevoSweepBoundHedron: PUBLIC PROC [masterObject: MasterObject] RETURNS [hedron: BoundHedron] = {
 revMesh: RevoluteMesh ← NARROW[masterObject.shadeBody];
 vertCount: NAT ← revMesh.linesOfLatitude*6; -- hexagons*6
 hex: Poly3d;
 hedron ← SVBoundBox.CreateBoundHedron[vertCount];

FOR i: NAT IN[1..revMesh.linesOfLatitude] DO
  -- the radius at this line of latitude is revMesh.array[i][revMesh.linesOfLongitude][1];
  hex ← SVPolygon3d.CircumHexagon[revMesh.array[i][1][2],
     revMesh.array[i][revMesh.linesOfLongitude][1]];
  SVBoundBox.AddBoundHedronPoly[hedron, hex];   
ENDLOOP;
 };

RevoSweepHint: TYPE = REF RevoSweepHintObj;
RevoSweepHintObj: TYPE = RECORD [boxes: SubBoxesBody];
RevoSweepFaces: TYPE = SweepCast.RevoSweepFaces;
RevoSweepRayCastBody: TYPE = REF RevoSweepRayCastBodyObj;
RevoSweepRayCastBodyObj: TYPE = RECORD [faces: RevoSweepFaces];

RevoSweepGetRayCastBody: PRIVATE PROC [revMesh: RevoluteMesh] RETURNS [rayCastBody: RevoSweepRayCastBody] = {
 rayCastBody ← NEW[RevoSweepRayCastBodyObj];
 rayCastBody.faces ← SweepCast.MakeRevoSweepFaces[revMesh];
 };

RevoSweepRayCast: PUBLIC PROC [cameraPoint: Point2d, localRay: Ray, masterObject: REF ANY, prim: Primitive] RETURNS [class: Classification] = {
 mo: MasterObject ← NARROW[masterObject];
 rayCastBody: RevoSweepRayCastBody ← NARROW[mo.rayCastBody];
 revoHint: RevoSweepHint ← NARROW[prim.hints];
RETURN[SweepCast.RevoCast[cameraPoint, localRay, prim, rayCastBody.faces, revoHint.boxes]];
-- prim.hints is a set of bounding boxes
 };

RevoSweepRayCastNoBBoxes: PUBLIC PROC [localRay: Ray, masterObject: REF ANY, prim: Primitive] RETURNS [class: Classification] = {
 mo: MasterObject ← NARROW[masterObject];
 rayCastBody: RevoSweepRayCastBody ← NARROW[mo.rayCastBody];
RETURN[SweepCast.RevoCastNoBBoxes[localRay, prim, rayCastBody.faces]];
 };

RevoSweepPreprocess: PUBLIC PROC [prim: Primitive, camera: Camera] = {
 revoSweepHint: RevoSweepHint ← NEW[RevoSweepHintObj];
 mo: MasterObject ← NARROW[prim.mo];
 rayCastBody: RevoSweepRayCastBody ← NARROW[mo.rayCastBody];
 faces: RevoSweepFaces ← rayCastBody.faces;
 boxes: SubBoxesBody;
 revoSweepHint.boxes ← NEW[SubBoxesBodyObj[faces.len]];
 boxes ← revoSweepHint.boxes;
FOR i: NAT IN[0..faces.len) DO
  WITH faces[i] SELECT FROM
  cone: Cone => boxes[i] ← SVBoundBox.BoundBoxFromBoundHedron[cone.boundHedron, camera, prim.primWRTAssembly];
  ring: DiskRing=> boxes[i] ← SVBoundBox.BoundBoxFromBoundHedron[ring.boundHedron, camera, prim.primWRTAssembly];
  cyl: Cylinder=> boxes[i] ← SVBoundBox.BoundBoxFromBoundHedron[cyl.boundHedron, camera, prim.primWRTAssembly];
  ENDCASE => ERROR;
  boxes.len ← faces.len;
ENDLOOP;
 prim.hints ← revoSweepHint;
 };

RevoSweepLineDraw: PUBLIC PROC[dc: Graphics.Context, data: REF ANY, camera: Camera, localCS: CoordSystem] = {
 revMesh: RevoluteMesh;
IF ISTYPE[data, RevoluteMesh]
  THEN revMesh ← NARROW[data]
  ELSE SIGNAL WrongTypeOfData;
 SweepGeometry.LineDrawRevoluteSweep[dc, revMesh, camera, localCS];
 };
RevoSweepDrawNormals: PUBLIC PROC[dc: Graphics.Context, data: REF ANY, camera: Camera, localCS: CoordSystem] = {
 revMesh: RevoluteMesh;
IF ISTYPE[data, RevoluteMesh]
  THEN revMesh ← NARROW[data]
  ELSE SIGNAL WrongTypeOfData;
 SweepGeometry.DrawNormalsRevoluteSweep[dc, revMesh, camera, localCS];
 };

RevoSweepCountSurf: PUBLIC PROC [masterObject: MasterObject] RETURNS [len: NAT] = {
 revMesh: RevoluteMesh ← NARROW[masterObject.shadeBody];
 len ← SweepGeometry.CountPlanarSurfacesRevoluteSweep[revMesh];
 };
RevoSweepCountVert: PUBLIC PROC [masterObject: MasterObject] RETURNS [len: NAT] = {
 revMesh: RevoluteMesh ← NARROW[masterObject.shadeBody];
 len ← SweepGeometry.CountVerticesRevoluteSweep[revMesh];
 };
RevoSweepGetSurf: PUBLIC PROC [assembly: Assembly, camera: CoordSystem] RETURNS [psl: PlanarSurfaceList] = {
 masterObject: MasterObject ← NARROW[assembly.object];
 revMesh: RevoluteMesh ← NARROW[masterObject.shadeBody];
 psl ← SweepGeometry.PlanarSurfacesRevoluteSweep[revMesh, assembly, camera];
 };
RevoSweepDrawSurf: PUBLIC PROC [dc: Graphics.Context, ps: PlanarSurface, lightSources: LightSourceList, camera: Camera] = {
 SweepGeometry.DrawPlanarSurfaceRevoluteSweep[dc, ps, lightSources, camera];
 };
RevoSweepDrawSubBoxes: PUBLIC PROC [dc: Graphics.Context, prim: Primitive, screenCS: CoordSystem] = {
 revoHint: RevoSweepHint ← NARROW[prim.hints];
 boxes: SubBoxesBody ← revoHint.boxes;
FOR i: NAT IN [0..boxes.len) DO
  SVBoundBox.DrawBoundBox[dc, boxes[i], screenCS];
ENDLOOP;
 };

RevoluteFileout: PUBLIC PROC [f: IO.STREAM, mo: MasterObject] = {
 rma: RevoluteMeshArray;
 revMesh: RevoluteMesh ← NARROW[mo.lineBody];
 lat, long: NAT;
 rma ← revMesh.array;
 lat ← revMesh.linesOfLatitude;
 long ← revMesh.linesOfLongitude;
-- assume that the defining contour has not been rotated. Output the [i][long] points
 f.PutF[" lat: %g, long: %g\n points [%g]:\n ", -- TAB
  [integer[lat]],[integer[long]],[integer[lat]]];
FOR i: NAT IN[1..lat-1] DO
  TFO3d.FileoutPoint3dAsPoint2d[f, rma[i][long]];
  f.PutF[","];
  IF (i/3)*3 = i THEN f.PutF["\n "]; -- CR TAB
ENDLOOP;
 TFO3d.FileoutPoint3dAsPoint2d[f, rma[lat][long]];
 f.PutChar[IO.CR];
 };

RevoluteFilein: PUBLIC PROC [f: IO.STREAM, name: Rope.ROPE] RETURNS [mo: MasterObject] = {
 lat, long, count: NAT;
 revMesh: RevoluteMesh;
 path: Path;
 TFI3d.ReadRope[f, " lat: "];
 lat ← TFI3d.ReadNAT[f];
 TFI3d.ReadRope[f, ", long: "];
 long ← TFI3d.ReadNAT[f];
 TFI3d.ReadReturn[f];
 TFI3d.ReadRope[f, " points ["];
 count ← TFI3d.ReadNAT[f];
 TFI3d.ReadRope[f, "]:"];
 TFI3d.ReadReturn[f];
 TFI3d.ReadRope[f, " "]; -- read tab
 path ← SVPolygon2d.CreatePath[count];
FOR i: NAT IN[1..count-1] DO
  SVPolygon2d.PutPathPoint[path, i-1, TFI3d.ReadPoint2d[f]];
  TFI3d.ReadRope[f, ","];
  IF (i/3)*3 = i THEN {TFI3d.ReadReturn[f]; TFI3d.ReadChar[f, IO.TAB]};
ENDLOOP;
 SVPolygon2d.PutPathPoint[path, lat-1, TFI3d.ReadPoint2d[f]];
 TFI3d.ReadReturn[f];
 revMesh ← SweepGeometry.RevoluteSweep[path, long];
 mo ← RevoSweepMakeMasterObject[name, revMesh];
 };

Init: PROC = {
 sphere, block, cylinder, cone: MasterObject;

 sphereClass ← DisplayList3d.RegisterMasterObjectClass[
  "sphere",
  SphereFilein,
  SphereFileout,
  SphereRayCast,
  SphereRayCastNoBBoxes,
  SphereBoundHedron,
  DisplayList3d.NoOpPreprocess,
  SphereLineDraw,
  SphereDrawNormals,
  SphereCountSurf,
  SphereGetSurf,
  SphereDrawSurf,
  DisplayList3d.NoOpDrawSubBoxes];
  
 blockClass ← DisplayList3d.RegisterMasterObjectClass[
  "block",
  BlockFilein,
  BlockFileout,
  BlockRayCast,
  BlockRayCastNoBBoxes,
  BlockBoundHedron,
  DisplayList3d.NoOpPreprocess,
  BlockLineDraw,
  BlockDrawNormals,
  BlockCountSurf,
  BlockGetSurf,
  BlockDrawSurf,
  DisplayList3d.NoOpDrawSubBoxes];

 cylinderClass ← DisplayList3d.RegisterMasterObjectClass[
  "cylinder",
  CylinderFilein,
  CylinderFileout,
  CylinderRayCast,
  CylinderRayCastNoBBoxes,
  CylinderBoundHedron,
  DisplayList3d.NoOpPreprocess,
  CylinderLineDraw,
  CylinderDrawNormals,
  CylinderCountSurf,
  CylinderGetSurf,
  CylinderDrawSurf,
  DisplayList3d.NoOpDrawSubBoxes];

 coneClass ← DisplayList3d.RegisterMasterObjectClass[
  "cone",
  ConeFilein,
  ConeFileout,
  ConeRayCast,
  ConeRayCastNoBBoxes,
  ConeBoundHedron,
  DisplayList3d.NoOpPreprocess,
  ConeLineDraw,
  ConeDrawNormals,
  ConeCountSurf,
  ConeGetSurf,
  ConeDrawSurf,
  DisplayList3d.NoOpDrawSubBoxes];
  
 torusClass ← DisplayList3d.RegisterMasterObjectClass[
  "torus",
  TorusFilein,
  TorusFileout,
  TorusRayCast,
  TorusRayCastNoBBoxes,
  TorusBoundHedron,
  DisplayList3d.NoOpPreprocess,
  TorusLineDraw,
  TorusDrawNormals,
  TorusCountSurf,
  TorusGetSurf,
  TorusDrawSurf,
  DisplayList3d.NoOpDrawSubBoxes];
  
 linClass ← DisplayList3d.RegisterMasterObjectClass[
  "linearSweep",
  LinearFilein,
  LinearFileout,
  LinSweepRayCast,
  LinSweepRayCastNoBBoxes,
  LinSweepBoundHedron,
  DisplayList3d.NoOpPreprocess,
  LinSweepLineDraw,
  LinSweepDrawNormals,
  LinSweepCountSurf,
  LinSweepGetSurf,
  LinSweepDrawSurf,
  DisplayList3d.NoOpDrawSubBoxes
  ];
  
 revoClass ← DisplayList3d.RegisterMasterObjectClass[
  "revoluteSweep",
  RevoluteFilein,
  RevoluteFileout,
  RevoSweepRayCast,
  RevoSweepRayCastNoBBoxes,
  RevoSweepBoundHedron,
  RevoSweepPreprocess,
  RevoSweepLineDraw,
  RevoSweepDrawNormals,
  RevoSweepCountSurf,
  RevoSweepGetSurf,
  RevoSweepDrawSurf,
  RevoSweepDrawSubBoxes];


 sphere ← SphereMakeMasterObject["sphere"];
 block ← BlockMakeMasterObject["block"];
 cylinder ← CylinderMakeMasterObject["cylinder"];
 cone ← ConeMakeMasterObject["cone"];

 DisplayList3d.RegisterMasterObject[sphere];
 DisplayList3d.RegisterMasterObject[block];
 DisplayList3d.RegisterMasterObject[cylinder];
 DisplayList3d.RegisterMasterObject[cone];
 };

Init[];

END.