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]; 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", 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 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. xSurfaceViewerImpl.mesa James Rauen, August 26, 1986 2:14:07 am PDT QuickViewer USING [BuildViewer, QuickView, Reset], Type declarations Global variables Declarations quickView: REF QuickViewer.QuickView; -- 9/12/86 - added for new QV Start out with no surfaces. Don't want ReDraw to do anything during the intitialization sequence. Build a color QuickViewer 9/12/86 - hook onto imagerContext imagerContext _ quickView.imagerCtx; Move it to the color display Get its 3d context. Save the working directory (stolen from ThreeDDemoImpl.mesa) Initiialize the 3d context. [] _ ThreeDScenes.SetLight [context3d, "Initial", [-100., -200., 50.] ]; MakeFrame[]; Private procedures for CreateSurfaceViewer 9/12/86 - toDo arg added to satisfy new QuickViewer Declarations imagerContext: Imager.Context _ ctx; -- 9/12/86 - arg name change in new QV Don't do anything during Init sequence. Redraw according to the new parameters. Declarations Assign the surface the next available position (index) in the surface sequence. If there is no room, signal so. Assign the surface an ID number. Construct a SurfaceViewer record for the surface. Add each cell as a different shape to the 3d context. Zero-cell. One-cell. Two-cell. Do the next cell. Looks to see if there is a surface in the surface sequence with the given id. If there is, returns its index in the sequence. If not, raises Error[$InvalidID]. Returns a list of all the shape names in the 3d context that match id. Declarations. Assemble the sequences needed by the ray tracer. Assemble a lighting model. Invoke the ray tracer. Private procedures Shamelessly stolen from ThreeDDemoImpl Κž˜™J™+J™—codešΟk ˜ Kšœœ˜Kšœœ˜Kšœ œE˜SKšœ œ˜(Kšœœ˜$Kšœœ˜"Kšœ œœ˜Kšœœ.œœ˜CKšœœ˜2Kšœ ˜ Kšœ œ!™2Kšœœ œ˜Kšœœ˜&Kšœ˜Kšœœ˜K˜ Kšœ œ=˜NKšœ ˜ Kšœ ˜ Kšœ˜Kšœ œ>˜LKšœœ ˜Kšœ œ˜K˜—K˜šΠlnœœ˜ Kšœœn˜’Kšœ˜Kšœ˜K˜™šœ œœ˜K˜Kšœœ˜Kšœœ˜ —šœ œœ˜Kšœ œ œœ ˜.—K˜—™Kšœ œ˜$Kšœ œ˜Kšœ˜K˜K˜Kšœœ˜Kšœ œ ˜Kšœœ˜Kšœœ˜Kšœœ˜ —K˜Kš Οnœœœœœ˜&K˜šŸœœœ˜*K˜™ Kšœœ˜K˜K˜Kšœ œΟc™EK˜—™Jšœ œ"˜0Jšœ˜Jšœ ˜ J˜—™EKšœ œ˜K˜—™˜(Kšœ œ˜KšŸ œ ˜KšŸœ ˜KšŸ œ ˜K˜(Kšœ œ˜K˜——šœ!™!Kšœ$™$K˜—™Kšœ œ:˜IKšœœ'˜DK˜—™Kšœ=˜=K˜—™