<> <> <> <> <> <<>> DIRECTORY CastRays, CoordSys, CSG, CSGGraphics, DisplayList3d, Imager, IO, Rope, SV2d, SV3d, SVBoundBox, SVModelTypes, SVPolygon3d, SVRayTypes, SVSceneTypes, SVToolObject, TFI3d; SVToolObjectImpl: CEDAR PROGRAM IMPORTS CastRays, CoordSys, CSG, CSGGraphics, DisplayList3d, IO, SVBoundBox, SVPolygon3d, TFI3d EXPORTS SVToolObject = BEGIN Assembly: TYPE = SVSceneTypes.Assembly; AssemblyList: TYPE = SVSceneTypes.AssemblyList; BoundHedron: TYPE = SVModelTypes.BoundHedron; Camera: TYPE = SVModelTypes.Camera; Classification: TYPE = SVRayTypes.Classification; CoordSystem: TYPE = SVModelTypes.CoordSystem; FrameBlock: TYPE = REF FrameBlockObj; FrameBlockObj: TYPE = SVSceneTypes.FrameBlockObj; LightSourceList: TYPE = SVModelTypes.LightSourceList; MasterObject: TYPE = SVSceneTypes.MasterObject; MasterObjectClass: TYPE = SVSceneTypes.MasterObjectClass; PlanarSurface: TYPE = REF PlanarSurfaceObj; PlanarSurfaceObj: TYPE = SVSceneTypes.PlanarSurfaceObj; PlanarSurfaceList: TYPE = SVSceneTypes.PlanarSurfaceList; Point2d: TYPE = SV2d.Point2d; Point3d: TYPE = SV3d.Point3d; Poly3d: TYPE = SV3d.Poly3d; Primitive: TYPE = SVRayTypes.Primitive; Ray: TYPE = SVRayTypes.Ray; Shape: TYPE = SVSceneTypes.Shape; ToolData: TYPE = SVSceneTypes.ToolData; Vector: TYPE = SV3d.Vector; toolClass: MasterObjectClass; jackClass: MasterObjectClass; ToolMakeMasterObject: PUBLIC PROC [name: Rope.ROPE, toolData: ToolData] RETURNS [mo: MasterObject] = TRUSTED { mainBody: REF ANY _ toolData; lineBody: REF ANY _ toolData; shadeBody: REF ANY _ toolData; rayCastBody: REF ANY _ toolData; mo _ DisplayList3d.CreateMasterObject[name, toolClass, mainBody, lineBody, shadeBody, rayCastBody]; }; SizeToFit: PUBLIC PROC [toolData: ToolData, assembly: Assembly] = { <> block: FrameBlock; loX, hiX, loY, hiY, loZ, hiZ: REAL; dataFound: BOOL; [loX, hiX, loY, hiY, loZ, hiZ, dataFound] _ BoundBlockOfAssembly[assembly, assembly]; IF dataFound THEN block _ NEW[FrameBlockObj _ [loX, hiX, loY, hiY, loZ, hiZ]] ELSE block _ NEW[FrameBlockObj _ [-400, 400, -400, 400, -400, 400]]; toolData.block _ block; toolData.infinite _ FALSE; }; BoundBlockOfAssembly: PROC [assembly: Assembly, wrt: Assembly] RETURNS [loX, hiX, loY, hiY, loZ, hiZ: REAL, dataFound: BOOL] = TRUSTED { <> localDataFound: BOOL; lX, hX, lY, hY, lZ, hZ: REAL; dataFound _ FALSE; WITH assembly.shape SELECT FROM assems: AssemblyList => { FOR subassemblies: LIST OF Assembly _ assems.list, subassemblies.rest UNTIL subassemblies = NIL DO [lX, hX, lY, hY, lZ, hZ, localDataFound] _ BoundBlockOfAssembly[subassemblies.first, wrt]; IF localDataFound THEN { IF (NOT dataFound) THEN { loX _ lX; hiX _ hX; loY _ lY; hiY _ hY; loZ _ lZ; hiZ _ hZ; } ELSE { loX _ MIN[loX, lX]; hiX _ MAX[hiX, hX]; loY _ MIN[loY, lY]; hiY _ MAX[hiY, hY]; loZ _ MIN[loZ, lZ]; hiZ _ MAX[hiZ, hZ]; }; }; dataFound _ dataFound OR localDataFound; ENDLOOP; }; shape: Shape => { bh: BoundHedron _ shape.mo.class.getHedron[shape.mo]; dataFound _ TRUE; IF bh = NIL THEN {dataFound _ FALSE; RETURN}; [loX, hiX, loY, hiY, loZ, hiZ] _ BoundBlockOfBoundHedron[bh, shape.coordSys, wrt.coordSys]; }; ENDCASE => ERROR; }; BoundBlockOfBoundHedron: PROC [bh: BoundHedron, currentCS: CoordSystem, newCS: CoordSystem] RETURNS [loX, hiX, loY, hiY, loZ, hiZ: REAL] = TRUSTED { thisPt: Point3d; thisPt _ CoordSys.FromCSToCS[bh[0], currentCS, newCS]; loX _ hiX _ thisPt[1]; loY _ hiY _ thisPt[2]; loZ _ hiZ _ thisPt[3]; FOR i: NAT IN [1..bh.len) DO thisPt _ CoordSys.FromCSToCS[bh[i], currentCS, newCS]; loX _ MIN[loX, thisPt[1]]; hiX _ MAX[hiX, thisPt[1]]; loY _ MIN[loY, thisPt[2]]; hiY _ MAX[hiY, thisPt[2]]; loZ _ MIN[loZ, thisPt[3]]; hiZ _ MAX[hiZ, thisPt[3]]; ENDLOOP; }; NoOpToolFilein: DisplayList3d.FileinProc = { mo _ NIL; }; NoOpToolFileout: DisplayList3d.FileoutProc = {}; ToolRayCast: PROC [cameraPoint: Point2d, localRay: Ray, masterObject: REF ANY, prim: Primitive] RETURNS [class: Classification] = { mo: MasterObject _ NARROW[masterObject]; RETURN[ToolRayCastAux[localRay, NARROW[mo.rayCastBody], prim]]; }; ToolRayCastAux: PROC [localRay: Ray, td: ToolData, prim: Primitive] RETURNS [class: Classification] = TRUSTED { hitPoint: Point3d; almostZero: REAL _ 1.0e-12; p: Point3d; d: Vector; t: REAL; class _ CastRays.GetClassFromPool[]; [p, d] _ CSG.GetLocalRay[localRay]; SELECT td.plane FROM 1 => { -- x = 0 plane only IF ABS[d[1]] < almostZero THEN CastRays.MakeClassAMiss[class] ELSE { t _ (- p[1])/d[1]; hitPoint[1] _ 0.0; hitPoint[2] _ p[2] + t*d[2]; hitPoint[3] _ p[3] + t*d[3]; IF hitPoint[2] > td.block.hiY OR hitPoint[2] < td.block.loY OR hitPoint[3] > td.block.hiZ OR hitPoint[3] < td.block.loZ THEN CastRays.MakeClassAMiss[class] ELSE { class.count _ 2; <> IF p[1] < 0.0 THEN { class.normals[1] _ [-1,0,0]; class.normals[2] _ [1,0,0]} ELSE { class.normals[1] _ [1,0,0]; class.normals[2] _ [-1,0,0]}; class.params[1] _ t; class.params[2] _ t; class.surfaces[1] _ NIL; class.surfaces[2] _ NIL; } }; }; 2 => { -- y = 0 plane only IF ABS[d[2]] < almostZero THEN CastRays.MakeClassAMiss[class] ELSE { t _ (- p[2])/d[2]; hitPoint[1] _ p[1] + t*d[1]; hitPoint[2] _ 0.0; hitPoint[3] _ p[3] + t*d[3]; IF hitPoint[1] > td.block.hiX OR hitPoint[1] < td.block.loX OR hitPoint[3] > td.block.hiZ OR hitPoint[3] < td.block.loZ THEN CastRays.MakeClassAMiss[class] ELSE { class.count _ 2; <> IF p[2] < 0.0 THEN { class.normals[1] _ [0,-1,0]; class.normals[2] _ [0,1,0]} ELSE { class.normals[1] _ [0,1,0]; class.normals[2] _ [0,-1,0]}; class.params[1] _ t; class.params[2] _ t; class.surfaces[1] _ NIL; class.surfaces[2] _ NIL; } }; }; 3 => { -- z = 0 plane only IF ABS[d[3]] < almostZero THEN CastRays.MakeClassAMiss[class] ELSE { t _ (- p[3])/d[3]; hitPoint[1] _ p[1] + t*d[1]; hitPoint[2] _ p[2] + t*d[2]; hitPoint[3] _ 0.0; IF hitPoint[1] > td.block.hiX OR hitPoint[1] < td.block.loX OR hitPoint[2] > td.block.hiY OR hitPoint[2] < td.block.loY THEN CastRays.MakeClassAMiss[class] ELSE { <> IF p[3] < 0 THEN { class.normals[1] _ [0,0,-1]; class.normals[2] _ [0,0,1]} ELSE { class.normals[1] _ [0,0,1]; class.normals[2] _ [0,0,-1]}; class.count _ 2; class.params[1] _ t; class.params[2] _ t; class.surfaces[1] _ NIL; class.surfaces[2] _ NIL; } }; }; 4 => ERROR; ENDCASE => ERROR; }; ToolRayCastNoBBoxes: PROC [localRay: Ray, masterObject: REF ANY, prim: Primitive] RETURNS [class: Classification] = { mo: MasterObject _ NARROW[masterObject]; RETURN[ToolRayCastAux[localRay, NARROW[mo.rayCastBody], prim]]; }; ToolRayCastBoundingSpheres: PROC [localRay: Ray, masterObject: REF ANY, prim: Primitive] RETURNS [class: Classification] = { mo: MasterObject _ NARROW[masterObject]; RETURN[ToolRayCastAux[localRay, NARROW[mo.rayCastBody], prim]]; }; ToolBoundHedron: PROC [mo: MasterObject] RETURNS [hedron: BoundHedron] = TRUSTED { toolData: ToolData _ NARROW[mo.mainBody]; block: FrameBlock _ toolData.block; hedron _ SVBoundBox.RectangularBoundHedron2[block.loX, block.hiX, block.loY, block.hiY, block.loZ, block.hiZ]; }; ToolLineDraw: PROC[dc: Imager.Context, data: REF ANY, camera: Camera, localCS: CoordSystem] = TRUSTED { td: ToolData _ NARROW[data]; f: FrameBlock _ td.block; SELECT td.plane FROM 1 => DrawHitPadX[dc, f.hiZ, f.loZ, f.loY, f.hiY, camera, localCS]; 2 => DrawHitPadY[dc, f.loX, f.hiX, f.loZ, f.hiZ, camera, localCS]; 3 => DrawHitPadZ[dc, f.loX, f.hiX, f.loY, f.hiY, camera, localCS]; 4 => { DrawHitPadX[dc, f.hiZ, f.loZ, f.loY, f.hiY, camera, localCS]; DrawHitPadY[dc, f.loX, f.hiX, f.loZ, f.hiZ, camera, localCS]; DrawHitPadZ[dc, f.loX, f.hiX, f.loY, f.hiY, camera, localCS]; }; ENDCASE => ERROR; }; DrawHitPadX: PRIVATE PROC [dc: Imager.Context, left, right, down, up: REAL, camera: Camera, cs: CoordSystem] = TRUSTED { CSGGraphics.SetCP[dc, [0, up, left], camera, cs]; -- up left CSGGraphics.DrawTo[dc, [0, up, right], camera, cs]; --up right CSGGraphics.DrawTo[dc, [0, down, right], camera, cs]; -- down right CSGGraphics.DrawTo[dc, [0, down, left], camera, cs]; -- down left CSGGraphics.DrawTo[dc, [0, up, left], camera, cs]; -- up left }; DrawHitPadY: PRIVATE PROC [dc: Imager.Context, left, right, down, up: REAL, camera: Camera, cs: CoordSystem] = TRUSTED { CSGGraphics.SetCP[dc, [left, 0, up], camera, cs]; -- up left CSGGraphics.DrawTo[dc, [right, 0, up], camera, cs]; --up right CSGGraphics.DrawTo[dc, [right, 0, down], camera, cs]; -- down right CSGGraphics.DrawTo[dc, [left, 0, down], camera, cs]; -- down left CSGGraphics.DrawTo[dc, [left, 0, up], camera, cs]; -- up left }; DrawHitPadZ: PRIVATE PROC [dc: Imager.Context, left, right, down, up: REAL, camera: Camera, cs: CoordSystem] = TRUSTED { CSGGraphics.SetCP[dc, [left, up, 0], camera, cs]; -- up left CSGGraphics.DrawTo[dc, [right, up, 0], camera, cs]; --up right CSGGraphics.DrawTo[dc, [right, down, 0], camera, cs]; -- down right CSGGraphics.DrawTo[dc, [left, down, 0], camera, cs]; -- down left CSGGraphics.DrawTo[dc, [left, up, 0], camera, cs]; -- up left }; ToolCountSurf: PROC [masterObject: MasterObject] RETURNS [len: NAT] = { toolData: ToolData _ NARROW[masterObject.mainBody]; IF toolData.plane < 4 THEN len _ 1 ELSE len _ 12; }; SortedToolSurface: TYPE = REF SortedToolSurfaceObj; SortedToolSurfaceObj: TYPE = RECORD [ plane: NAT, f: FrameBlock, left: BOOL, down: BOOL ]; ToolGetSurf: PROC [assembly: Assembly, camera: CoordSystem] RETURNS [psl: PlanarSurfaceList] = TRUSTED { <> <> <> <> mo: MasterObject _ assembly.toolMasterObject; localCS: CoordSystem _ assembly.coordSys; thisSortedSurface: PlanarSurface; poly: Poly3d _ SVPolygon3d.CreatePoly[4]; toolData: ToolData _ NARROW[mo.mainBody]; avgDepth: REAL; f: FrameBlock _ toolData.block; psl _ NIL; SELECT toolData.plane FROM 1,2,3,4 => { -- z = 0 plane poly _ SVPolygon3d.AddPolyPoint[poly, [f.loX, f.loY, 0]]; poly _ SVPolygon3d.AddPolyPoint[poly, [f.loX, f.hiY, 0]]; poly _ SVPolygon3d.AddPolyPoint[poly, [f.hiX, f.hiY, 0]]; poly _ SVPolygon3d.AddPolyPoint[poly, [f.hiX, f.loY, 0]]; avgDepth _ AverageDepth[poly, localCS, camera]; thisSortedSurface _ NEW[PlanarSurfaceObj _ [ whichSurface: NEW[SortedToolSurfaceObj _ [toolData.plane, f, FALSE, FALSE]], assembly: assembly, normal: [0,0,1], mo: mo, depth: avgDepth]]; psl _ CONS[thisSortedSurface, psl]; <> }; ENDCASE => ERROR; }; AverageDepth: PROC [poly: Poly3d, localCS, camera: CoordSystem] RETURNS [avgDepth: REAL] = TRUSTED { sum: REAL _ 0; realLen: REAL _ poly.len; localPoint: Point3d; FOR i: NAT IN[0..poly.len) DO localPoint _ poly[i]; localPoint _ CSGGraphics.LocalToCamera[localPoint, localCS]; sum _ sum + localPoint[3]; ENDLOOP; avgDepth _ sum/realLen; }; ToolDrawSurf: PROC [dc: Imager.Context, ps: PlanarSurface, lightSources: LightSourceList, camera: Camera] = TRUSTED { whichSurface: SortedToolSurface _ NARROW[ps.whichSurface]; poly3d: Poly3d _ SVPolygon3d.CreatePoly[4]; f: FrameBlock _ whichSurface.f; poly3d _ SVPolygon3d.AddPolyPoint[poly3d, [f.loX, f.loY, 0]]; poly3d _ SVPolygon3d.AddPolyPoint[poly3d, [f.loX, f.hiY, 0]]; poly3d _ SVPolygon3d.AddPolyPoint[poly3d, [f.hiX, f.hiY, 0]]; poly3d _ SVPolygon3d.AddPolyPoint[poly3d, [f.hiX, f.loY, 0]]; CSGGraphics.DrawAreaNormalAbsolute[dc, ps.normal, poly3d, ps.assembly.artwork, lightSources, camera, ps.assembly.coordSys]; }; <> JackMakeMasterObject: PUBLIC PROC [name: Rope.ROPE] RETURNS [mo: MasterObject] = TRUSTED { mainBody: REF ANY _ NIL; lineBody: REF ANY _ NIL; shadeBody: REF ANY _ NIL; rayCastBody: REF ANY _ NIL; mo _ DisplayList3d.CreateMasterObject[name, jackClass, mainBody, lineBody, shadeBody, rayCastBody]; }; JackBoundHedron: PUBLIC PROC [mo: MasterObject] RETURNS [hedron: BoundHedron] = TRUSTED { hedron _ SVBoundBox.RectangularBoundHedron[2.0, 2.0, 2.0]; }; JackLineDraw: PUBLIC PROC[dc: Imager.Context, data: REF ANY, camera: Camera, localCS: CoordSystem] = TRUSTED { CSGGraphics.SetCP[dc, [-1.0,0.0,0.0], camera, localCS]; CSGGraphics.DrawTo[dc, [1.0,0.0,0.0], camera, localCS]; CSGGraphics.SetCP[dc, [0.0,-1.0,0.0], camera, localCS]; CSGGraphics.DrawTo[dc, [0.0,1.0,0.0], camera, localCS]; CSGGraphics.SetCP[dc, [0.0,0.0,-1.0], camera, localCS]; CSGGraphics.DrawTo[dc, [0.0,0.0,1.0], camera, localCS]; }; JackCountSurf: PUBLIC PROC [masterObject: MasterObject] RETURNS [len: NAT] = { len _ 6; }; JackGetSurf: PUBLIC PROC [assembly: Assembly, camera: CoordSystem] RETURNS [psl: PlanarSurfaceList] = { shape: Shape _ NARROW[assembly.shape]; masterObject: MasterObject _ shape.mo; psl _ NIL; }; JackDrawSurf: PUBLIC PROC [dc: Imager.Context, ps: PlanarSurface, lightSources: LightSourceList, camera: Camera] = { }; JackFileout: PUBLIC PROC [f: IO.STREAM, mo: MasterObject] = { <> f.PutChar[IO.TAB]; f.PutF["data: procedural\n"]; }; JackFilein: PUBLIC PROC [f: IO.STREAM, name: Rope.ROPE] RETURNS [mo: MasterObject] = TRUSTED { TFI3d.ReadRope[f, "data: procedural"]; TFI3d.ReadBlank[f]; mo _ JackMakeMasterObject[name]; }; Init: PROC = TRUSTED { jack: MasterObject; toolClass _ DisplayList3d.RegisterMasterObjectClass[ "tool", NoOpToolFilein, NoOpToolFileout, DisplayList3d.NoOpFileoutPoly, ToolRayCast, ToolRayCastNoBBoxes, ToolRayCastBoundingSpheres, ToolBoundHedron, DisplayList3d.NoOpPreprocess, ToolLineDraw, DisplayList3d.NoOpNormalsDraw, ToolCountSurf, ToolGetSurf, ToolDrawSurf, DisplayList3d.NoOpDrawSubBoxes, DisplayList3d.NoOpDrawSubSpheres]; jackClass _ DisplayList3d.RegisterMasterObjectClass[ "jack", JackFilein, JackFileout, DisplayList3d.NoOpFileoutPoly, DisplayList3d.NoOpRayCast, DisplayList3d.NoOpRayCastNoBBoxes, DisplayList3d.NoOpRayCastBoundingSpheres, JackBoundHedron, DisplayList3d.NoOpPreprocess, JackLineDraw, DisplayList3d.NoOpNormalsDraw, JackCountSurf, JackGetSurf, JackDrawSurf, DisplayList3d.NoOpDrawSubBoxes, DisplayList3d.NoOpDrawSubSpheres]; jack _ JackMakeMasterObject["jack"]; DisplayList3d.RegisterMasterObject[jack]; }; Init[]; END.