<> <> <> <> <> <<>> DIRECTORY SVCastRays, CoordSys, SVRay, SVGraphics, Imager, IO, Rope, SV2d, SV3d, SVAssembly, SVBasicTypes, SVBoundBox, SVMasterObject, SVModelTypes, SVPolygon3d, SVScene, SVSceneTypes, SVToolObject, TFI3d; SVToolObjectImpl: CEDAR PROGRAM IMPORTS SVCastRays, CoordSys, SVRay, SVGraphics, IO, SVAssembly, SVBoundBox, SVMasterObject, SVPolygon3d, SVScene, TFI3d EXPORTS SVToolObject = BEGIN Matrix4by4: TYPE = SV3d.Matrix4by4; Slice: TYPE = SVSceneTypes.Slice; SliceList: TYPE = SVSceneTypes.SliceList; BoundHedron: TYPE = SVBasicTypes.BoundHedron; Camera: TYPE = SVModelTypes.Camera; Classification: TYPE = SVSceneTypes.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; MasterObjectClassObj: TYPE = SVSceneTypes.MasterObjectClassObj; 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 = SVSceneTypes.Primitive; Ray: TYPE = SVSceneTypes.Ray; Shape: TYPE = SVSceneTypes.Shape; SelectMode: TYPE = SVSceneTypes.SelectMode; SliceDescriptor: TYPE = SVSceneTypes.SliceDescriptor; ToolData: TYPE = SVSceneTypes.ToolData; Vector3d: TYPE = SV3d.Vector3d; toolClass: MasterObjectClass; jackClass: MasterObjectClass; ToolMakeMasterObject: PUBLIC PROC [name: Rope.ROPE, toolData: ToolData] RETURNS [mo: MasterObject] = { mainBody: REF ANY _ toolData; lineBody: REF ANY _ toolData; shadeBody: REF ANY _ toolData; rayCastBody: REF ANY _ toolData; mo _ SVScene.CreateMasterObject[name, toolClass, mainBody, lineBody, shadeBody, rayCastBody]; }; SizeToFit: PUBLIC PROC [toolData: ToolData, assembly: Slice] = { <> 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: Slice, wrt: Slice] RETURNS [loX, hiX, loY, hiY, loZ, hiZ: REAL, dataFound: BOOL] = { <> localDataFound: BOOL; lX, hX, lY, hY, lZ, hZ: REAL; dataFound _ FALSE; WITH assembly.shape SELECT FROM assems: SliceList => { FOR subassemblies: LIST OF Slice _ 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] = { 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; }; ToolRayCast: PROC [cameraPoint: Point2d, localRay: Ray, sliceD: SliceDescriptor, prim: Primitive] RETURNS [class: Classification] = { mo: MasterObject _ prim.mo; RETURN[ToolRayCastAux[localRay, NARROW[mo.rayCastBody], prim]]; }; ToolRayCastAux: PROC [localRay: Ray, td: ToolData, prim: Primitive] RETURNS [class: Classification] = { hitPoint: Point3d; almostZero: REAL _ 1.0e-12; p: Point3d; d: Vector3d; t: REAL; class _ SVCastRays.GetClassFromPool[]; [p, d] _ SVRay.GetLocalRay[localRay]; SELECT td.plane FROM 1 => { -- x = 0 plane only IF ABS[d[1]] < almostZero THEN SVCastRays.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 SVCastRays.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 SVCastRays.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 SVCastRays.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 SVCastRays.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 SVCastRays.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, sliceD: SliceDescriptor, prim: Primitive] RETURNS [class: Classification] = { mo: MasterObject _ prim.mo; RETURN[ToolRayCastAux[localRay, NARROW[mo.rayCastBody], prim]]; }; ToolRayCastBoundingSpheres: PROC [localRay: Ray, sliceD: SliceDescriptor, prim: Primitive] RETURNS [class: Classification] = { mo: MasterObject _ prim.mo; RETURN[ToolRayCastAux[localRay, NARROW[mo.rayCastBody], prim]]; }; ToolBoundHedron: PROC [mo: MasterObject] RETURNS [hedron: BoundHedron] = { 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[slice: Slice, dc: Imager.Context, camera: Camera] = { mo: MasterObject _ slice.toolMasterObject; td: ToolData _ NARROW[mo.lineBody]; f: FrameBlock _ td.block; localCS: CoordSystem _ slice.coordSys; 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] = { localCamera: Matrix4by4 _ CoordSys.WRTCamera[cs, camera.coordSys]; SVGraphics.SetCP[dc, [0, up, left], camera, localCamera]; -- up left SVGraphics.DrawTo[dc, [0, up, right], camera, localCamera]; --up right SVGraphics.DrawTo[dc, [0, down, right], camera, localCamera]; -- down right SVGraphics.DrawTo[dc, [0, down, left], camera, localCamera]; -- down left SVGraphics.DrawTo[dc, [0, up, left], camera, localCamera]; -- up left }; DrawHitPadY: PRIVATE PROC [dc: Imager.Context, left, right, down, up: REAL, camera: Camera, cs: CoordSystem] = { localCamera: Matrix4by4 _ CoordSys.WRTCamera[cs, camera.coordSys]; SVGraphics.SetCP[dc, [left, 0, up], camera, localCamera]; -- up left SVGraphics.DrawTo[dc, [right, 0, up], camera, localCamera]; --up right SVGraphics.DrawTo[dc, [right, 0, down], camera, localCamera]; -- down right SVGraphics.DrawTo[dc, [left, 0, down], camera, localCamera]; -- down left SVGraphics.DrawTo[dc, [left, 0, up], camera, localCamera]; -- up left }; DrawHitPadZ: PRIVATE PROC [dc: Imager.Context, left, right, down, up: REAL, camera: Camera, cs: CoordSystem] = { localCamera: Matrix4by4 _ CoordSys.WRTCamera[cs, camera.coordSys]; SVGraphics.SetCP[dc, [left, up, 0], camera, localCamera]; -- up left SVGraphics.DrawTo[dc, [right, up, 0], camera, localCamera]; --up right SVGraphics.DrawTo[dc, [right, down, 0], camera, localCamera]; -- down right SVGraphics.DrawTo[dc, [left, down, 0], camera, localCamera]; -- down left SVGraphics.DrawTo[dc, [left, up, 0], camera, localCamera]; -- 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 [slice: Slice, camera: CoordSystem] RETURNS [psl: PlanarSurfaceList] = { <> <> <> <> mo: MasterObject _ slice.toolMasterObject; localCS: CoordSystem _ slice.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: slice, normal: [0,0,1], mo: mo, depth: avgDepth]]; psl _ CONS[thisSortedSurface, psl]; <> }; ENDCASE => ERROR; }; AverageDepth: PROC [poly: Poly3d, localCS, cameraCS: CoordSystem] RETURNS [avgDepth: REAL] = { sum: REAL _ 0; realLen: REAL _ poly.len; localPoint: Point3d; FOR i: NAT IN[0..poly.len) DO localPoint _ poly[i]; localPoint _ SVGraphics.LocalToCamera[localPoint, localCS, cameraCS]; sum _ sum + localPoint[3]; ENDLOOP; avgDepth _ sum/realLen; }; ToolDrawSurf: PROC [dc: Imager.Context, ps: PlanarSurface, lightSources: LightSourceList, camera: Camera] = { 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]]; SVGraphics.DrawAreaNormalAbsolute[dc, ps.normal, poly3d, ps.assembly.artwork, lightSources, camera, CoordSys.WRTWorld[ps.assembly.coordSys], CoordSys.WRTCamera[ps.assembly.coordSys, camera.coordSys]]; }; <> JackMakeMasterObject: PUBLIC PROC [name: Rope.ROPE] RETURNS [mo: MasterObject] = { mainBody: REF ANY _ NIL; lineBody: REF ANY _ NIL; shadeBody: REF ANY _ NIL; rayCastBody: REF ANY _ NIL; mo _ SVScene.CreateMasterObject[name, jackClass, mainBody, lineBody, shadeBody, rayCastBody]; }; JackUpdate: PUBLIC PROC [mo: MasterObject, updateData: REF ANY] = { }; JackBoundHedron: PUBLIC PROC [mo: MasterObject] RETURNS [hedron: BoundHedron] = { hedron _ SVBoundBox.RectangularBoundHedron[2.0, 2.0, 2.0]; }; JackLineDraw: PUBLIC PROC[slice: Slice, dc: Imager.Context, camera: Camera] = { localCS: CoordSystem _ slice.coordSys; localCamera: Matrix4by4 _ CoordSys.WRTCamera[localCS, camera.coordSys]; SVGraphics.SetCP[dc, [-1.0,0.0,0.0], camera, localCamera]; SVGraphics.DrawTo[dc, [1.0,0.0,0.0], camera, localCamera]; SVGraphics.SetCP[dc, [0.0,-1.0,0.0], camera, localCamera]; SVGraphics.DrawTo[dc, [0.0,1.0,0.0], camera, localCamera]; SVGraphics.SetCP[dc, [0.0,0.0,-1.0], camera, localCamera]; SVGraphics.DrawTo[dc, [0.0,0.0,1.0], camera, localCamera]; }; JackCountSurf: PUBLIC PROC [masterObject: MasterObject] RETURNS [len: NAT] = { len _ 6; }; JackGetSurf: PUBLIC PROC [slice: Slice, camera: CoordSystem] RETURNS [psl: PlanarSurfaceList] = { shape: Shape _ NARROW[slice.shape]; masterObject: MasterObject _ shape.mo; psl _ NIL; }; JackNewParts: PUBLIC PROC [slice: Slice, hitData: REF ANY, mode: SelectMode] RETURNS [sliceD: SliceDescriptor] = { sliceD _ SVAssembly.DescriptorFromParts[slice, 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, version: REAL] RETURNS [mo: MasterObject] = { TFI3d.ReadRope[f, "data: procedural"]; TFI3d.ReadBlank[f]; mo _ JackMakeMasterObject[name]; }; Init: PROC = { jack: MasterObject; toolClass _ NEW[MasterObjectClassObj _ [ name: "tool", update: SVMasterObject.NoOpUpdate, filein: SVMasterObject.NoOpFilein, fileout: SVMasterObject.NoOpFileout, fileoutPoly: SVMasterObject.NoOpFileoutPoly, rayCast: ToolRayCast, rayCastNoBBoxes: ToolRayCastNoBBoxes, rayCastBoundingSpheres: ToolRayCastBoundingSpheres, getHedron: ToolBoundHedron, preprocess: SVMasterObject.NoOpPreprocess, lineDraw: ToolLineDraw, normalsDraw: SVMasterObject.NoOpNormalsDraw, countSurf: ToolCountSurf, getSurf: ToolGetSurf, pointsInDescriptor: SVMasterObject.NoOpPointsInDescriptor, nextPoint: SVMasterObject.NoOpNextPoint, drawSurf: ToolDrawSurf, drawSubBoxes: SVMasterObject.NoOpDrawSubBoxes, drawSubSpheres: SVMasterObject.NoOpDrawSubSpheres]]; jackClass _ NEW[MasterObjectClassObj _ [ name: "jack", update: JackUpdate, filein: JackFilein, fileout: JackFileout, fileoutPoly: SVMasterObject.NoOpFileoutPoly, rayCast: SVMasterObject.NoOpRayCast, rayCastNoBBoxes: SVMasterObject.NoOpRayCastNoBBoxes, rayCastBoundingSpheres: SVMasterObject.NoOpRayCastBoundingSpheres, getHedron: JackBoundHedron, preprocess: SVMasterObject.NoOpPreprocess, lineDraw: JackLineDraw, normalsDraw: SVMasterObject.NoOpNormalsDraw, countSurf: JackCountSurf, getSurf: JackGetSurf, pointsInDescriptor: SVMasterObject.NoOpPointsInDescriptor, nextPoint: SVMasterObject.NoOpNextPoint, drawSurf: JackDrawSurf, drawSubBoxes: SVMasterObject.NoOpDrawSubBoxes, drawSubSpheres: SVMasterObject.NoOpDrawSubSpheres]]; SVMasterObject.RegisterMasterObjectClass[toolClass]; SVMasterObject.RegisterMasterObjectClass[jackClass]; jack _ JackMakeMasterObject["jack"]; SVMasterObject.RegisterMasterObject[jack]; }; Init[]; END.