<> <> <<>> DIRECTORY Atom USING [PutPropOnList], Basics USING [Comparison], CADTypes USING [Scad, ScadSequence, VariableRec, VisibleMask, VisibleMaskSequence], Commander USING [CommandProc, Register], Convert USING [CardFromRope, Error], Imager USING [Context, Rectangle], ImagerColor USING [RGB], IO USING [BreakProc, Error, GetTokenRope, int, PutFR, RIS, STREAM], LightingModels USING [Model, PointSourceSequence], QuickViewer, <> Rope USING [Compare, ROPE], ShadingModels USING [ShadingSequence], SurfaceTracer, SurfaceViewer USING [], ThreeDBasics, ThreeDHacks USING [RegisterNewClasses, MakeFatPoint, MakeFatSeg, MakeTwoCell], ThreeDMisc, ThreeDScenes, ThreeDSurfaces, Vector3d USING [Add, Cross, Mul, Triple, TripleSequence, TripleSequenceRec], ViewerClasses USING [Viewer], ViewerOps USING [ChangeColumn]; SurfaceViewerImpl: CEDAR PROGRAM IMPORTS Atom, Commander, Convert, IO, QuickViewer, Rope, SurfaceTracer, ThreeDHacks, ThreeDMisc, ThreeDScenes, ThreeDSurfaces, Vector3d, ViewerOps EXPORTS SurfaceViewer ~ BEGIN <> SurfaceRec: TYPE ~ RECORD [ scad: CADTypes.Scad, id: NAT, mask: REF CADTypes.VisibleMask]; SurfaceSeq: TYPE ~ RECORD [ surfaces: SEQUENCE length: NAT OF SurfaceRec]; <> context3d: REF ThreeDBasics.Context; noReDraw: BOOLEAN; position: Vector3d.Triple; forward: Vector3d.Triple; up: Vector3d.Triple; viewHasChanged: BOOLEAN; surfaces: REF SurfaceSeq; numberOfSurfaces: NAT; maxNumberOfSurfaces: NAT ~ 3; nextID: NAT; Error: PUBLIC ERROR[why: ATOM] = CODE; CreateSurfaceViewer: PUBLIC PROC[] ~ BEGIN <> workingDirectory: Rope.ROPE; imagerContext: Imager.Context; viewer: ViewerClasses.Viewer; <> <> surfaces _ NEW[SurfaceSeq[maxNumberOfSurfaces]]; numberOfSurfaces _ 0; nextID _ 0; <> noReDraw _ TRUE; <> imagerContext _ QuickViewer.BuildViewer[ menuLabels: NIL, ReDrawProc: Redraw, QuitProc: ShutDown, ButtonProc: MenuHit, viewerTitle: "Algebraic Surface Viewer", noScroll: TRUE]; <<9/12/86 - hook onto imagerContext>> <> <> viewer _ NARROW[imagerContext.data, QuickViewer.QuickView].viewer.parent; IF viewer.column # color THEN ViewerOps.ChangeColumn[viewer, color]; <> context3d _ ThreeDScenes.GetFromImagerContext[imagerContext]; <> context3d.props _ Atom.PutPropOnList[context3d.props, $WDir, workingDirectory]; <<>> <> position _ [2.0, -10.0, 3.0]; forward _ [-2, 10, -3]; up _ [0, 0,1]; ThreeDMisc.SetBackground [context3d, "Darkish Blue"]; <<[] _ ThreeDScenes.SetLight [context3d, "Initial", [-100., -200., 50.] ]; >> [] _ ThreeDScenes.SetLight [context3d, "Initial", position]; ThreeDHacks.RegisterNewClasses[context3d]; ThreeDScenes.SetView [ context: context3d, eyePoint: position, ptOfInterest: Vector3d.Add[position, forward], upDirection: up]; noReDraw _ FALSE; viewHasChanged _ TRUE; <> END; <<>> <> <<>> Redraw: PROC [imagerContext: Imager.Context] ~ BEGIN <<9/12/86 - toDo arg added to satisfy new QuickViewer>> <> <> newContext: REF ThreeDScenes.Context; oldContext: Imager.Context; <<>> <> IF noReDraw THEN RETURN; <> oldContext _ ThreeDMisc.GetImagerContext[context3d]; IF oldContext # NIL THEN imagerContext _ oldContext; newContext _ ThreeDScenes.GetFromImagerContext[imagerContext, context3d.alphaBuffer, context3d.depthBuffer]; context3d.display _ newContext.display; context3d.alphaBuffer _ newContext.alphaBuffer; context3d.depthBuffer _ newContext.depthBuffer; context3d.renderMode _ newContext.renderMode; context3d.viewPort _ newContext.viewPort; SetViewPort[context3d.viewPort]; ThreeDScenes.SetWindow[context3d, ThreeDScenes.WindowFromViewPort[context3d.viewPort]]; viewHasChanged _ TRUE; MakeFrame[]; END; ShutDown: PROC [] ~ BEGIN END; MenuHit: PROC [bttn: ATOM, x, y: REAL, ctrl, shift: BOOL] ~ BEGIN END; LoadSurface: PUBLIC PROC[surface: CADTypes.Scad] RETURNS[id: NAT] ~ BEGIN <> index, newID: NAT; <> IF numberOfSurfaces >= maxNumberOfSurfaces THEN ERROR Error[$AllFilledUp]; index _ numberOfSurfaces; numberOfSurfaces _ numberOfSurfaces + 1; <> newID _ nextID; nextID _ nextID + 1; <> surfaces[index] _ [ scad: surface, id: newID, mask: NEW[CADTypes.VisibleMask[surface.cells.nCells]] ]; FOR i: NAT IN [0..surface.cells.nCells) DO surfaces[index].mask[i] _ TRUE; ENDLOOP; <<>> <> FOR cell: NAT IN [0..surface.cells.nCells) DO newCell: REF ThreeDScenes.ShapeInstance; cellName: Rope.ROPE _ MakeShapeName[ newID, surface.cells[cell].indexX, surface.cells[cell].indexY, surface.cells[cell].indexZ]; SELECT surface.cells[cell].dimension FROM <> 0 => BEGIN newCell _ ThreeDHacks.MakeFatPoint[ name: cellName, position: surface.cells[cell].vertices[0]]; ThreeDScenes.PlaceShape[newCell, [0, 0, 0]]; context3d.shapes _ ThreeDScenes.AddShape[context3d.shapes, newCell]; ThreeDMisc.SetFacetedColor[context3d, cellName, [0.1, 0.9, 0.9]]; END; <> 1 => BEGIN vertexSequence: Vector3d.TripleSequence _ NEW[Vector3d.TripleSequenceRec[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]; ThreeDScenes.PlaceShape[newCell, [0, 0, 0]]; context3d.shapes _ ThreeDScenes.AddShape[context3d.shapes, newCell]; ThreeDMisc.SetFacetedColor[context3d, cellName, [0.1, 0.9, 0.9]]; END; <> 2 => BEGIN newCell _ ThreeDHacks.MakeTwoCell[ name: cellName, vertices: surface.cells[cell].vertices, triangles: surface.cells[cell].polygons]; ThreeDScenes.PlaceShape[newCell, [0, 0, 0]]; context3d.shapes _ ThreeDScenes.AddShape[context3d.shapes, newCell]; ThreeDMisc.SetFacetedColor[context3d, cellName, [0.1, 0.9, 0.9]]; END; ENDCASE; <> ENDLOOP; viewHasChanged _ TRUE; MakeFrame[]; RETURN[newID]; END; <<>> MaskSurface: PUBLIC PROC[id: NAT, mask: REF CADTypes.VisibleMask] ~ BEGIN index: NAT _ IndexFromID[id]; --verify ID FOR i: NAT IN [0..surfaces[index].scad.cells.nCells) DO nameToMask: Rope.ROPE _ MakeShapeName[ id, surfaces[index].scad.cells[i].indexX, surfaces[index].scad.cells[i].indexY, surfaces[index].scad.cells[i].indexZ ]; IF mask[i] THEN ThreeDMisc.Reveal[context3d, nameToMask] ELSE ThreeDMisc.Hide[context3d, nameToMask]; ENDLOOP; surfaces[index].mask _ mask; viewHasChanged _ TRUE; MakeFrame[]; END; HideSurface: PUBLIC PROC[id: NAT] ~ BEGIN index: NAT _ IndexFromID[id]; --verify ID namesToHide: LIST OF Rope.ROPE _ ShapesMatchingID[id]; UNTIL namesToHide = NIL DO ThreeDMisc.Hide[context3d, namesToHide.first]; namesToHide _ namesToHide.rest; ENDLOOP; viewHasChanged _ TRUE; MakeFrame[]; END; UnHideSurface: PUBLIC PROC[id: NAT] ~ BEGIN index: NAT _ IndexFromID[id]; --verify ID namesToHide: LIST OF Rope.ROPE _ ShapesMatchingID[id]; UNTIL namesToHide = NIL DO ThreeDMisc.Reveal[context3d, namesToHide.first]; namesToHide _ namesToHide.rest; ENDLOOP; viewHasChanged _ TRUE; MakeFrame[]; END; DeleteSurface: PUBLIC PROC[id: NAT] ~ BEGIN index: NAT _ IndexFromID[id]; namesToDelete: LIST OF Rope.ROPE _ ShapesMatchingID[id]; FOR i: NAT IN [index..numberOfSurfaces - 1) DO surfaces[i] _ surfaces[i + 1]; ENDLOOP; numberOfSurfaces _ numberOfSurfaces - 1; UNTIL namesToDelete = NIL DO context3d.shapes _ ThreeDScenes.DeleteShape[context3d.shapes, namesToDelete.first]; namesToDelete _ namesToDelete.rest; ENDLOOP; viewHasChanged _ TRUE; MakeFrame[]; END; FlushSurfaces: PUBLIC PROC[] ~ BEGIN numberOfSurfaces _ 0; viewHasChanged _ TRUE; MakeFrame[]; END; IndexFromID: PROC [id: NAT] RETURNS [index: NAT] ~ BEGIN <> found: BOOLEAN _ FALSE; FOR i: NAT IN [0..numberOfSurfaces) DO IF surfaces[i].id = id THEN {index _ i; found _ TRUE}; ENDLOOP; IF ~found THEN ERROR Error[$InvalidID]; END; ShapesMatchingID: PROC [id: NAT] RETURNS [shapes: LIST OF Rope.ROPE] ~ BEGIN <> names: LIST OF Rope.ROPE _ NIL; FOR i: NAT IN [0..context3d.shapes.length) DO name: Rope.ROPE _ context3d.shapes[i].name; IF Rope.Compare[name, "Initial"] # equal AND Rope.Compare[name, "Torch"] # equal 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 [ "S%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: 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; ChangePosition: PUBLIC PROC[newPosition: Vector3d.Triple] ~ BEGIN position _ newPosition; ThreeDScenes.SetView [ context: context3d, eyePoint: position, ptOfInterest: Vector3d.Add[position, forward], upDirection: up]; viewHasChanged _ TRUE; END; <<>> ChangeOrientation: PUBLIC PROC[newForward, newUp: Vector3d.Triple] ~ BEGIN forward _ newForward; up _ newUp; ThreeDScenes.SetView [ context: context3d, eyePoint: position, ptOfInterest: Vector3d.Add[position, forward], upDirection: up]; viewHasChanged _ TRUE; END; <<>> ChangeScope: PUBLIC PROC[newScope: REAL] ~ BEGIN viewHasChanged _ TRUE; END; DrawFrame: PUBLIC PROC [] ~ BEGIN IF viewHasChanged THEN MakeFrame[]; END; InvokeRayTracer: PUBLIC PROC[variables: CADTypes.VariableRec, filename: Rope.ROPE, pixelsU, pixelsV: NAT] ~ BEGIN <<>> <> scads: REF CADTypes.ScadSequence; colors: REF ShadingModels.ShadingSequence; masks: REF CADTypes.VisibleMaskSequence; behind, right, behindAndRight, above, pointSourcePosition: Vector3d.Triple; pointSources: REF LightingModels.PointSourceSequence; lighting: LightingModels.Model; <<>> <> n: NAT _ 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] _ surfaces[i].scad; colors[i] _ [ surfaceColor: surfaces[i].scad.color, ambientReflectionCoefficient: 1.0, diffuseReflectionCoefficient: 0.4, specularReflectionCoefficient: 0.8]; masks[i] _ surfaces[i].mask; ENDLOOP; <> behind _ Vector3d.Mul[forward, -5]; right _ Vector3d.Mul[Vector3d.Cross[forward, up], 2]; above _ Vector3d.Mul[up, 2]; behindAndRight _ Vector3d.Add[Vector3d.Add[behind, right], above]; pointSourcePosition _ Vector3d.Add[position, behindAndRight]; pointSources _ NEW[LightingModels.PointSourceSequence[1]]; pointSources[0] _ [position: pointSourcePosition, color: [1, 1, 1]]; lighting _ [background: [1, 1, 1], ambientSource: [0.2, 0.2, 0.2], pointSources: pointSources]; <> SurfaceTracer.TraceCells[ surfaces: scads, variables: variables, colors: colors, masks: masks, screenCenter: position, screenU: up, screenV: Vector3d.Cross[up, forward], pixelsU: pixelsU, pixelsV: pixelsV, lightingModel: lighting, filename: filename]; <<>> END; <> Reset: PROC [] ~ BEGIN <> imagerContext: Imager.Context _ ThreeDMisc.GetImagerContext[context3d]; QuickViewer.Reset[imagerContext]; ThreeDSurfaces.EnableDisplay[]; ThreeDMisc.SetViewPortFromImager[context3d, imagerContext]; ThreeDScenes.SetWindow[context3d, ThreeDScenes.WindowFromViewPort[context3d.viewPort]]; context3d.shapes _ context3d.lights; -- delete all the objects ThreeDScenes.SetView[ context3d, [2.0, -10.0, 3.0], [0.0, 0.0, 0.0] ]; END; MakeFrame: PROC [] ~ BEGIN ThreeDSurfaces.EnableDisplay[]; ThreeDScenes.SetView[ -- get new screen dimensions into transformations context: context3d, eyePoint: context3d.eyePoint, ptOfInterest: context3d.ptOfInterest, fieldOfView: context3d.fieldOfView, rollAngle: context3d.rollAngle, upDirection: context3d.upDirection, hitherLimit: context3d.hitherLimit, yonLimit: context3d.yonLimit ]; [] _ ThreeDScenes.SetLight[ context: context3d, name: "Torch", position: context3d.eyePoint, color: [1, 1, 1] ]; ThreeDMisc.MakeFrame[context3d]; viewHasChanged _ FALSE; END; SetViewPort: PROC [size: Imager.Rectangle] ~ BEGIN ThreeDScenes.SetViewPort[context3d, size]; -- set clippers etc. FOR i: NAT IN [0..context3d.shapes.length) DO context3d.shapes[i].vtcesInValid _ TRUE; context3d.shapes[i].shadingInValid _ TRUE; ENDLOOP; ThreeDScenes.SetView[ -- get new screen dimensions into transformations context: context3d, eyePoint: context3d.eyePoint, ptOfInterest: context3d.ptOfInterest, fieldOfView: context3d.fieldOfView, rollAngle: context3d.rollAngle, upDirection: context3d.upDirection, hitherLimit: context3d.hitherLimit, yonLimit: context3d.yonLimit ]; END; Foo: Commander.CommandProc ~ BEGIN CreateSurfaceViewer[]; END; Commander.Register["MakeSurfaceViewer", Foo]; END.