<> <> <> <<>> DIRECTORY Atom USING [PutPropOnList], Basics USING [Comparison], CADTypes USING [Scad, ScadSequence, VariableRec, VisibleMask, VisibleMaskSequence], Convert USING [CardFromRope, Error], Geometry3dBasics USING [Triple, TripleSequence, TripleSequenceRep], Geometry3dVector USING [Add, Cross, Mul], Imager USING [Rectangle], ImagerColor USING [RGB], IO USING [BreakProc, Error, GetRope, GetTokenRope, int, PutFR, RIS, STREAM], LightingModels USING [Model, PointSourceSequence], MessageWindow USING [Append], Rope USING [Compare, IsPrefix, ROPE], SceneUtilities USING [AddShape, AddShapeAt, CreateDefaultContext, DeleteShape, Hide, NameBackgroundColor, NewShape, PlaceShape, ReadShape, Reveal, SetColor, SetFaceted, SetLight, SetViewPort, ShapeInstance], ShadingModels USING [ShadingSequence], SurfaceRender USING [MakeFrame], SurfaceTracer, SurfaceViewer, ThreeDBasics USING [Context, SetView], ThreeDHacks USING [RegisterNewClasses, MakeFatPoint, MakeFatSeg, MakeTwoCell], ThreeDViewer USING [ButtonDesc, MakeViewer], ViewerClasses USING [Column, Viewer], ViewerOps USING [ChangeColumn, OpenIcon]; SurfaceViewerImpl: CEDAR PROGRAM IMPORTS Atom, Convert, IO, MessageWindow, Rope, SurfaceRender, SurfaceTracer, ThreeDBasics, ThreeDHacks, ThreeDViewer, SceneUtilities, Geometry3dVector, ViewerOps EXPORTS SurfaceViewer ~ BEGIN <> initialPosition: Geometry3dBasics.Triple _ [2.0, -10.0, 3.0]; initialForward: Geometry3dBasics.Triple _ [-2.0, 10.0, -3.0]; initialUp: Geometry3dBasics.Triple _ [0., 0., 1.]; maxNumberOfSurfaces: NAT ~ 3; Error: PUBLIC ERROR[why: ATOM] = CODE; CreateSurfaceViewer: PUBLIC PROC[] RETURNS[sviewer: REF SurfaceViewer.SurfaceViewer] ~ BEGIN <> workingDirectory: Rope.ROPE; <> sviewer _ NEW[SurfaceViewer.SurfaceViewer]; sviewer.surfaces _ NEW[SurfaceViewer.SurfaceSeq[maxNumberOfSurfaces]]; sviewer.numberOfSurfaces _ 0; sviewer.nextID _ 0; sviewer.context3d _ SceneUtilities.CreateDefaultContext[]; <<>> <> SceneUtilities.NameBackgroundColor[sviewer.context3d, "Darkish Blue"]; SceneUtilities.SetLight [sviewer.context3d, "Initial", initialPosition]; ThreeDBasics.SetView [ context: sviewer.context3d, eyePoint: initialPosition, ptOfInterest: Geometry3dVector.Add[initialPosition, initialForward], upDirection: initialUp]; <> ThreeDHacks.RegisterNewClasses[sviewer.context3d]; <> sviewer.context3d.props _ Atom.PutPropOnList[sviewer.context3d.props, $WDir, workingDirectory]; <> ThreeDViewer.MakeViewer[ context: sviewer.context3d, bannerName: "ThreeDWorld -- Algebraic Surface Viewer", menu: NIL, mouseAction: NIL]; IF sviewer.context3d.viewer.column # color THEN ViewerOps.ChangeColumn[sviewer.context3d.viewer, color]; IF sviewer.context3d.viewer.iconic THEN ViewerOps.OpenIcon[icon: sviewer.context3d.viewer]; <> DrawFrame[sviewer]; END; <<>> <> <ThreeDWorld>ChampagneGlass.shape"];>> <> <> <<>> <> <> <<>> GetThreeDContext: PUBLIC PROC[sviewer: REF SurfaceViewer.SurfaceViewer] RETURNS[context3d: REF ThreeDBasics.Context] ~ BEGIN context3d _ sviewer.context3d; END; LoadSurface: PUBLIC PROC[surface: CADTypes.Scad, sviewer: REF SurfaceViewer.SurfaceViewer] RETURNS[id: NAT] ~ BEGIN index, newID: NAT; <> IF sviewer.numberOfSurfaces >= maxNumberOfSurfaces THEN ERROR Error[$AllFilledUp]; index _ sviewer.numberOfSurfaces; sviewer.numberOfSurfaces _ sviewer.numberOfSurfaces + 1; <> newID _ sviewer.nextID; sviewer.nextID _ sviewer.nextID + 1; <> sviewer.surfaces[index] _ [ scad: surface, id: newID, mask: NEW[CADTypes.VisibleMask[surface.cells.nCells]] ]; FOR i: NAT IN [0..surface.cells.nCells) DO sviewer.surfaces[index].mask[i] _ TRUE; ENDLOOP; <<>> <> FOR cell: NAT IN [0..surface.cells.nCells) DO newCell: REF SceneUtilities.ShapeInstance; cellName: Rope.ROPE _ MakeShapeName[ newID, surface.cells[cell].indexX, surface.cells[cell].indexY, surface.cells[cell].indexZ]; MessageWindow.Append[IO.PutFR["SurfaceViewer loading cell %g of %g.", IO.int[cell + 1], IO.int[surface.cells.nCells]], TRUE]; SELECT surface.cells[cell].dimension FROM <> 0 => BEGIN newCell _ ThreeDHacks.MakeFatPoint[ name: cellName, position: surface.cells[cell].vertices[0]]; <> <> SceneUtilities.AddShape[sviewer.context3d, newCell]; SceneUtilities.PlaceShape[sviewer.context3d, cellName, [0, 0, 0]]; <> SceneUtilities.SetColor[sviewer.context3d, cellName, [0, 0.1, 0]]; SceneUtilities.SetFaceted[sviewer.context3d, cellName]; END; <> 1 => BEGIN vertexSequence: Geometry3dBasics.TripleSequence _ NEW[Geometry3dBasics.TripleSequenceRep[surface.cells[cell].vertices.nVertices]]; vertexSequence.length _ surface.cells[cell].vertices.nVertices; FOR i: NAT IN [0..surface.cells[cell].vertices.nVertices) DO vertexSequence[i] _ surface.cells[cell].vertices[i] ENDLOOP; newCell _ ThreeDHacks.MakeFatSeg[ name: cellName, points: vertexSequence]; SceneUtilities.AddShape[sviewer.context3d, newCell]; SceneUtilities.PlaceShape[sviewer.context3d, cellName, [0, 0, 0]]; SceneUtilities.SetColor[sviewer.context3d, cellName, [0, 0.1, 0]]; SceneUtilities.SetFaceted[sviewer.context3d, cellName]; <<9/22/86 - check for empty shape>> IF surface.cells[cell].vertices.nVertices < 2 THEN SceneUtilities.Hide[sviewer.context3d, cellName]; END; <> 2 => BEGIN newCell _ ThreeDHacks.MakeTwoCell[ name: cellName, vertices: surface.cells[cell].vertices, triangles: surface.cells[cell].polygons]; SceneUtilities.AddShape[sviewer.context3d, newCell]; SceneUtilities.PlaceShape[sviewer.context3d, cellName, [0, 0, 0]]; SceneUtilities.SetColor[sviewer.context3d, cellName, [0.8, 0.2, 0.2]]; SceneUtilities.SetFaceted[sviewer.context3d, cellName]; <<9/22/86 - check for empty shape>> IF surface.cells[cell].polygons.nTriangles = 0 THEN SceneUtilities.Hide[sviewer.context3d, cellName]; END; ENDCASE; <> ENDLOOP; MessageWindow.Append["Surface loaded.", TRUE]; DrawFrame[sviewer]; RETURN[newID]; END; <<>> MaskSurface: PUBLIC PROC[id: NAT, mask: REF CADTypes.VisibleMask, sviewer: REF SurfaceViewer.SurfaceViewer] ~ BEGIN index: NAT _ IndexFromID[id, sviewer]; --verify ID FOR i: NAT IN [0..sviewer.surfaces[index].scad.cells.nCells) DO nameToMask: Rope.ROPE _ MakeShapeName[ id, sviewer.surfaces[index].scad.cells[i].indexX, sviewer.surfaces[index].scad.cells[i].indexY, sviewer.surfaces[index].scad.cells[i].indexZ ]; IF mask[i] THEN SceneUtilities.Reveal[sviewer.context3d, nameToMask] ELSE SceneUtilities.Hide[sviewer.context3d, nameToMask]; ENDLOOP; sviewer.surfaces[index].mask _ mask; DrawFrame[sviewer]; END; HideSurface: PUBLIC PROC[id: NAT, sviewer: REF SurfaceViewer.SurfaceViewer] ~ BEGIN index: NAT _ IndexFromID[id, sviewer]; --verify ID namesToHide: LIST OF Rope.ROPE _ ShapesMatchingID[id, sviewer]; UNTIL namesToHide = NIL DO SceneUtilities.Hide[sviewer.context3d, namesToHide.first]; namesToHide _ namesToHide.rest; ENDLOOP; DrawFrame[sviewer]; END; UnHideSurface: PUBLIC PROC[id: NAT, sviewer: REF SurfaceViewer.SurfaceViewer] ~ BEGIN index: NAT _ IndexFromID[id, sviewer]; --verify ID namesToHide: LIST OF Rope.ROPE _ ShapesMatchingID[id, sviewer]; UNTIL namesToHide = NIL DO SceneUtilities.Reveal[sviewer.context3d, namesToHide.first]; namesToHide _ namesToHide.rest; ENDLOOP; DrawFrame[sviewer]; END; DeleteSurface: PUBLIC PROC[id: NAT, sviewer: REF SurfaceViewer.SurfaceViewer] ~ BEGIN index: NAT _ IndexFromID[id, sviewer]; namesToDelete: LIST OF Rope.ROPE _ ShapesMatchingID[id, sviewer]; FOR i: NAT IN [index..sviewer.numberOfSurfaces - 1) DO sviewer.surfaces[i] _ sviewer.surfaces[i + 1]; ENDLOOP; sviewer.numberOfSurfaces _ sviewer.numberOfSurfaces - 1; UNTIL namesToDelete = NIL DO SceneUtilities.DeleteShape[sviewer.context3d, namesToDelete.first]; namesToDelete _ namesToDelete.rest; ENDLOOP; DrawFrame[sviewer]; END; FlushSurfaces: PUBLIC PROC[sviewer: REF SurfaceViewer.SurfaceViewer] ~ BEGIN sviewer.numberOfSurfaces _ 0; DrawFrame[sviewer]; END; IndexFromID: PROC [id: NAT, sviewer: REF SurfaceViewer.SurfaceViewer] RETURNS [index: NAT] ~ BEGIN <> found: BOOLEAN _ FALSE; FOR i: NAT IN [0..sviewer.numberOfSurfaces) DO IF sviewer.surfaces[i].id = id THEN {index _ i; found _ TRUE}; ENDLOOP; IF ~found THEN ERROR Error[$InvalidID]; END; ShapesMatchingID: PROC [id: NAT, sviewer: REF SurfaceViewer.SurfaceViewer] RETURNS [shapes: LIST OF Rope.ROPE] ~ BEGIN <> names: LIST OF Rope.ROPE _ NIL; FOR i: NAT IN [0..sviewer.context3d.shapes.length) DO name: Rope.ROPE _ sviewer.context3d.shapes[i].name; IF Rope.IsPrefix["Cell", name] THEN BEGIN surfaceID: NAT; [id: surfaceID] _ ParseShapeName[name]; IF surfaceID = id THEN names _ CONS[name, names]; END; ENDLOOP; RETURN[names]; END; MakeShapeName: PROC [id, indexX, indexY, indexZ: NAT] RETURNS [name: Rope.ROPE] ~ BEGIN name _ IO.PutFR [ "CellS%gX%gY%gZ%g", IO.int[id], IO.int[indexX], IO.int[indexY], IO.int[indexZ]]; RETURN; END; ParseError: ERROR = CODE; ParseShapeName: PROC [name: Rope.ROPE] RETURNS [id, indexX, indexY, indexZ: NAT] ~ BEGIN BreakProc: IO.BreakProc ~ BEGIN RETURN [SELECT char FROM IN ['0..'9] => other, ENDCASE => break]; END; inStream: IO.STREAM _ IO.RIS[name]; token: Rope.ROPE; token _ IO.GetRope[inStream, 4, FALSE]; IF Rope.Compare[token, "Cell"] # equal THEN ERROR ParseError; [token: token] _ IO.GetTokenRope[inStream, BreakProc ! IO.Error => ERROR ParseError]; IF Rope.Compare[token, "S"] # equal THEN ERROR ParseError; [token: token] _ IO.GetTokenRope[inStream, BreakProc ! IO.Error => ERROR ParseError]; id _ Convert.CardFromRope[token ! Convert.Error => ERROR ParseError]; [token: token] _ IO.GetTokenRope[inStream, BreakProc ! IO.Error => ERROR ParseError]; IF Rope.Compare[token, "X"] # equal THEN ERROR ParseError; [token: token] _ IO.GetTokenRope[inStream, BreakProc ! IO.Error => ERROR ParseError]; indexX _ Convert.CardFromRope[token ! Convert.Error => ERROR ParseError]; [token: token] _ IO.GetTokenRope[inStream, BreakProc ! IO.Error => ERROR ParseError]; IF Rope.Compare[token, "Y"] # equal THEN ERROR ParseError; [token: token] _ IO.GetTokenRope[inStream, BreakProc ! IO.Error => ERROR ParseError]; indexY _ Convert.CardFromRope[token ! Convert.Error => ERROR ParseError]; [token: token] _ IO.GetTokenRope[inStream, BreakProc ! IO.Error => ERROR ParseError]; IF Rope.Compare[token, "Z"] # equal THEN ERROR ParseError; [token: token] _ IO.GetTokenRope[inStream, BreakProc ! IO.Error => ERROR ParseError]; indexZ _ Convert.CardFromRope[token ! Convert.Error => ERROR ParseError]; END; <> <> <> <> <> <> <> <> <> <<>> <> <> <> <> <> <> <> <> <> <> <<>> <> <> <> <<>> <> <> <> <> <<>> InvokeRayTracer: PUBLIC PROC[variables: CADTypes.VariableRec, filename: Rope.ROPE, pixelsU, pixelsV: NAT, sviewer: REF SurfaceViewer.SurfaceViewer] ~ BEGIN <<>> <> scads: REF CADTypes.ScadSequence; colors: REF ShadingModels.ShadingSequence; masks: REF CADTypes.VisibleMaskSequence; behind, right, behindAndRight, above, pointSourcePosition: Geometry3dBasics.Triple; pointSources: REF LightingModels.PointSourceSequence; lighting: LightingModels.Model; <<>> <> n: NAT _ sviewer.numberOfSurfaces; scads _ NEW[CADTypes.ScadSequence[n]]; colors _ NEW[ShadingModels.ShadingSequence[n]]; masks _ NEW[CADTypes.VisibleMaskSequence[n]]; FOR i: NAT IN [0..n) DO scads[i] _ sviewer.surfaces[i].scad; colors[i] _ [ surfaceColor: sviewer.surfaces[i].scad.color, ambientReflectionCoefficient: 1.0, diffuseReflectionCoefficient: 0.4, specularReflectionCoefficient: 0.8]; masks[i] _ sviewer.surfaces[i].mask; ENDLOOP; <> <> <> <> <> <> <> <> <> <<>> <> <> <> <> <> <> <> <> <> <> <> <> <> <<>> END; <> <> <> <<>> <> <> <> <> <> <> <> <<>> <> <> <> <> <> <> <<>> <> <<>> DrawFrame: PUBLIC PROC [sviewer: REF SurfaceViewer.SurfaceViewer] ~ BEGIN <> ThreeDBasics.SetView[ -- get new screen dimensions into transformations context: sviewer.context3d, eyePoint: sviewer.context3d.eyePoint, ptOfInterest: sviewer.context3d.ptOfInterest, fieldOfView: sviewer.context3d.fieldOfView, rollAngle: sviewer.context3d.rollAngle, upDirection: sviewer.context3d.upDirection, hitherLimit: sviewer.context3d.hitherLimit, yonLimit: sviewer.context3d.yonLimit ]; SceneUtilities.SetLight[ context: sviewer.context3d, name: "Torch", position: sviewer.context3d.eyePoint, color: [1, 1, 1] ]; SurfaceRender.MakeFrame[sviewer.context3d]; END; <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <<];>> <> <<>> END.