DIRECTORY Args, CedarProcess, Commander, Controls, Draw2d, G3dBasic, G3dControl, G3dDraw, G3dLight, G3dMatrix, G3dModel, G3dRender, G3dShape, G3dTool, G3dVector, Imager, ImagerArtwork, ImagerBackdoor, ImagerColor, ImagerFont, ImagerSample, IO, PFS, Rope, ViewerAbort, ViewerOps; G3dToolDrawImpl: CEDAR PROGRAM IMPORTS Args, Controls, Draw2d, G3dControl, G3dDraw, G3dMatrix, G3dModel, G3dRender, G3dShape, G3dTool, G3dVector, Imager, ImagerArtwork, ImagerBackdoor, ImagerFont, ImagerSample, IO, PFS, Rope, ViewerAbort, ViewerOps EXPORTS G3dTool ~ BEGIN ClickProc: TYPE ~ Controls.ClickProc; Viewer: TYPE ~ Controls.Viewer; Triple: TYPE ~ G3dBasic.Triple; Matrix: TYPE ~ G3dMatrix.Matrix; Shape: TYPE ~ G3dShape.Shape; Buffering: TYPE ~ G3dTool.Buffering; Client: TYPE ~ G3dTool.Client; DrawProc: TYPE ~ G3dTool.DrawProc; NamedBuffer: TYPE ~ G3dTool.NamedBuffer; Tool: TYPE ~ G3dTool.Tool; View: TYPE ~ G3dTool.View; ViewProc: TYPE ~ G3dTool.ViewProc; Context: TYPE ~ Imager.Context; Rectangle: TYPE ~ Imager.Rectangle; ROPE: TYPE ~ Rope.ROPE; maxDisplayTime: REAL ¬ 0.1; -- in seconds useCG6: BOOL ¬ TRUE; -- to debug, don't use CG6! Repaint: PUBLIC PROC [tool: Tool, whatChanged: REF ¬ $Client, buffering: Buffering ¬ default] ~ { Paint: ViewProc ~ {ViewerOps.PaintViewer[view.viewer, client, FALSE, whatChanged]}; IF tool.views = NIL OR tool.views.length = 0 THEN RETURN; tool.buffering ¬ buffering; IF whatChanged = $Camera AND tool.camera.mouse.state = up THEN RETURN; -- whatChanged ¬ $Store; G3dTool.DoWithViews[tool, Paint, whatChanged = $Camera]; IF tool.timing THEN G3dTool.PrintElapsedTime[tool, tool.previousDisplayTime, "Draw"]; tool.previousWhatChanged ¬ whatChanged; }; SetMinFPS: PUBLIC PROC [fps: NAT ¬ 4] ~ {maxDisplayTime ¬ 1.0/REAL[fps]}; Store: PUBLIC PROC [context: Context, view: View, id: ATOM ¬ $Frame] ~ { Buffer[context, view, store, id]; }; Restore: PUBLIC PROC [context: Context, view: View, id: ATOM ¬ $Frame] ~ { Buffer[context, view, restore, id]; }; Buffer: PROC [context: Context, view: View, op: {store, restore}, id: ATOM] ~ { r: Rectangle; r ¬ view.tool.bounds ¬ ImagerBackdoor.GetBounds[context ! Imager.Error => GOTO Quit]; IF view # NIL THEN SELECT op FROM store => { Store: PROC [pm: Imager.PixelMap] ~ { nb: NamedBuffer ¬ [id, ImagerSample.Copy[pm[0]]]; FOR l: LIST OF NamedBuffer ¬ view.idBuffer, l.rest WHILE l # NIL DO IF l.first.id = id THEN { ImagerSample.ReleaseScratchMap[l.first.map]; l.first ¬ nb; RETURN; }; ENDLOOP; view.idBuffer ¬ CONS[nb, view.idBuffer]; }; ImagerBackdoor.AccessBufferRectangle[context, Store, r]; }; ENDCASE => FOR l: LIST OF NamedBuffer ¬ view.idBuffer, l.rest WHILE l # NIL DO Restore: PROC [pm: Imager.PixelMap] ~ {ImagerSample.Transfer[pm[0], l.first.map]}; IF l.first.id # id THEN LOOP; IF l.first.map # NIL THEN ImagerBackdoor.AccessBufferRectangle[context, Restore, r]; EXIT; ENDLOOP; EXITS Quit => NULL; -- ImagerBackdoor operations not defined for Interpress masters }; Draw: PUBLIC G3dTool.DrawProc ~ { IF v # NIL AND (whatChanged = $IPOut OR v.viewer = viewer) THEN WITH whatChanged SELECT FROM proc: REF CedarProcess.ForkableProc => [] ¬ proc[tool.context3d]; ENDCASE => SELECT whatChanged FROM $Store => Store[context, v]; $Restore => Restore[context, v]; ENDCASE => { ViewerAbortAction: PROC ~ {DoDraw[context, tool, whatChanged, viewer, v]}; IF tool.camera.use = view THEN { v.camera.matrix ¬ G3dMatrix.CopyMatrix[tool.camera.matrix, v.camera.matrix]; G3dControl.SaveState[tool.camera, v.camera]; }; SELECT whatChanged FROM NIL, $Camera, $DrawOps, $ShapeOps, $Scene => InvalidateVertexScreens[tool, all]; ENDCASE; IF tool.shapes # NIL THEN FOR n: NAT IN [0..tool.shapes.length) DO IF GetRenderStyle[tool.shapes[n]] # lines THEN { G3dTool.Render[tool, FALSE]; RETURN; }; ENDLOOP; ViewerAbort.CallWithAbortEnabled[viewer, ViewerAbortAction]; }; G3dRender.SetView[ tool.context3d, tool.camera.eyePoint, tool.camera.lookAt, tool.camera.fieldOfView.value, 0, tool.camera.up]; }; GetRenderStyle: PROC [s: Shape] RETURNS [rs: G3dRender.RenderStyle ¬ lines] ~ { d: G3dRender.RenderData ¬ G3dRender.RenderDataFrom[s]; IF d # NIL THEN rs ¬ d.renderStyle; }; DoDraw: PROC [context: Context, clientData, whatChanged: REF, viewer: Viewer, v: View] ~ { DrawSprite: PROC ~ {G3dDraw.Mark[context, t.sprite, x, vp,, asterisk]}; DrawAxes: PROC ~ { Vec: PROC [v: Triple, r: ROPE] ~ {G3dDraw.Vector[context, [], v, x, vp, r]}; Vec[[1, 0, 0], "x"]; Vec[[0, 1, 0], "y"]; Vec[[0, 0, 1], "z"]; }; LabelVertex: PROC ~ { vtx: G3dShape.Vertex ¬ t.shapes[t.selectedShape].vertices[t.selectedVertex]; r: ROPE ¬ IO.PutFLR[" #%g (%g, %g, %g)", LIST[ IO.int[t.selectedVertex], IO.real[vtx.point.x], IO.real[vtx.point.y], IO.real[vtx.point.z]]]; IF t.shapes.length#1 THEN r ¬IO.PutFR["%g (shape %g)", [rope[r]], IO.int[t.selectedVertex]]; Imager.SetFont[context, ImagerFont.Find["xerox/tiogafonts/helvetica12"]]; G3dDraw.Vector[context, vtx.point, vtx.normal, x, vp, r,, 30.0, asterisk]; }; IdentifyView: PROC ~ { NViews: PROC RETURNS [i: INT ¬ 0] ~ { FOR l: LIST OF NAT ¬ t.activeViews ,l.rest WHILE l#NIL DO i ¬ i+1; ENDLOOP; }; active: BOOL ¬ FALSE; IF whatChanged = $IPOut THEN RETURN; IF t.shapes = NIL AND NViews[] = 1 THEN RETURN; IF t.camera.use = view THEN FOR l: LIST OF NAT ¬ t.activeViews, l.rest WHILE l # NIL DO IF v.index = l.first THEN {active ¬ TRUE; EXIT}; ENDLOOP; G3dDraw.SetColor[context, [0.0, 0.0, 0.0]]; IF active THEN { G3dDraw.Quadrangle[context, 0, 0, 0, 20, 20, 20, 20, 0, cg6]; G3dDraw.SetColor[context, [1.0, 1.0, 1.0]]; } ELSE { G3dDraw.Line2d[context, [0, 20], [20, 20], solid, cg6]; G3dDraw.Line2d[context, [20, 0], [20, 20], solid, cg6]; G3dDraw.SetColor[context, [0.0, 0.0, 0.0]]; }; Draw2d.Label[context, [5, 5], IO.PutFR1["%g", IO.int[v.index]]]; }; ClientsDraw: PROC [whatChanged: REF ANY] ~ { IF NOT t.drawClient THEN RETURN; IF t.client.draw # NIL THEN t.client.draw[context, viewer, whatChanged, x, vp, v, t, t.client.data]; IF t = G3dTool.GetActiveTool[] THEN FOR c: LIST OF Client ¬ G3dTool.GetActiveClients[], c.rest WHILE c # NIL DO IF c.first.draw # NIL THEN c.first.draw[context, viewer, whatChanged, x, vp, v, t, c.first.data]; ENDLOOP; }; DrawShapesLights: PROC ~ { DrawCertainShapes: PROC [which: {selected, unselected, all}, type: Draw2d.DrawType]~{ lv: Triple ¬ IF t.lights#NIL AND t.lights.length>0 THEN t.lights[0].direction ELSE [.7,.7,.0]; IF t.shapes # NIL THEN FOR n: NAT IN [0..t.shapes.length) DO s: Shape ¬ t.shapes[n]; IF s # NIL AND s.visible AND (which = all OR s.selected = (which=selected)) THEN { sv: G3dDraw.Options ¬ t.drawOptions; t.drawOptions.lineType ¬ type; IF NOT G3dShape.FaceValid[s, normal] THEN G3dShape.SetFaceNormals[s]; IF NOT s.showBackfaces AND sv.backFaces = on THEN t.drawOptions.backFaces ¬ off; v.screens[n] ¬ G3dDraw.Shape[context, s, x,, vp, lv, v.screens[n],, t.drawOptions]; t.drawOptions ¬ sv; }; ENDLOOP; }; -- IF t.ops.shape THEN -- DrawCertainShapes[unselected, dashed]; -- IF t.ops.shape THEN -- DrawCertainShapes[selected, solid]; IF t.shapes # NIL AND t.ops.light AND t.lights # NIL THEN { DrawSun: PROC [x, y: INTEGER, fill: BOOL] ~ { DrawQuad: PROC [x1, y1, x2, y2, x3, y3, x4, y4: INTEGER] ~ { IF fill THEN G3dDraw.Quadrangle[context, x1, y1, x2, y2, x3, y3, x4, y4, cg6] ELSE { G3dDraw.Line2d[context, [x1, y1], [x2, y2], solid, cg6]; G3dDraw.Line2d[context, [x2, y2], [x3, y3], solid, cg6]; G3dDraw.Line2d[context, [x3, y3], [x4, y4], solid, cg6]; }; }; x1, x2, x3, x4, y1, y2, y3, y4: INTEGER; x1 ¬ x-7; x2 ¬ x-3; x3 ¬ x+3; x4 ¬ x+7; y1 ¬ y-5; y2 ¬ y+5; y3 ¬ y1-7; y4 ¬ y2+7; DrawQuad[x1, y, x2, y1, x3, y1, x4, y]; DrawQuad[x1, y, x2, y2, x3, y2, x4, y]; G3dDraw.Line2d[context, [x1, y], [x-14, y], solid, cg6]; G3dDraw.Line2d[context, [x4, y], [x+14, y], solid, cg6]; G3dDraw.Line2d[context, [x2, y1], [x1, y3], solid, cg6]; G3dDraw.Line2d[context, [x3, y1], [x4, y3], solid, cg6]; G3dDraw.Line2d[context, [x2, y2], [x1, y4], solid, cg6]; G3dDraw.Line2d[context, [x3, y2], [x4, y4], solid, cg6]; }; hasPersp: BOOL ¬ G3dMatrix.HasPerspective[x]; IF t.drawLights THEN FOR i: INTEGER IN [0..t.lights.length) DO l: G3dLight.Light ¬ t.lights[i]; screen: G3dBasic.Screen ¬ G3dMatrix.GetScreen[l.position, x, hasPersp, vp]; r: Triple ¬ IF G3dVector.FrontFacing[l.direction, l.position, x] THEN [1,0,0] ELSE [0,0,1]; G3dDraw.SetColor[context, r]; l.screen ¬ screen.pos; DrawSun[screen.intPos.x, screen.intPos.y, i = t.selectedLight]; G3dDraw.Vector[context, l.position, l.direction, x, vp]; ENDLOOP; G3dDraw.SetColor[context, [0.0, 0.0, 0.0]]; }; }; Clear: PROC ~ { color: ImagerColor.RGB ¬ t.context3d.backgroundColor; IF whatChanged # $IPOut THEN G3dDraw.Clear[context, t.background]; }; Action: PROC ~ { SELECT whatChanged FROM $Clear => Clear[]; $Vertex => {Restore[context, v, $Pose]; IF vertex THEN LabelVertex[]}; $Sprite => IF t.drawSprite THEN {Restore[context, v, $Pose]; DrawSprite[]}; NIL, $Camera, $DrawOps, $IPOut, $ShapeOps, $Scene, $Stuff, $Client, $SelectShape, $SelectLight, $Pose => { Clear[]; IdentifyView[]; Imager.SetStrokeWidth[context, t.ipStrokeWidth]; G3dDraw.SetColor[context, [0.0, 0.0, 0.0]]; ClientsDraw[whatChanged]; DrawShapesLights[]; IF t.drawAxes THEN DrawAxes[]; IF t.drawPendant THEN G3dDraw.Pendant[context, x, .07, .7, .7, ["x", "y", "z",,,]]; IF vertex THEN LabelVertex[]; IF t.drawSprite THEN DrawSprite[]; IF whatChanged = NIL OR whatChanged = $Pose THEN Store[context, v]; }; $View => IdentifyView[]; ENDCASE => { ClientsDraw[whatChanged]; RETURN; }; ClientsDraw[$Overlay]; }; t: Tool ¬ NARROW[clientData]; x: Matrix ¬ v.camera.matrix; vp: G3dMatrix.Viewport ¬ v.viewport; vertex: BOOL ¬ t.queryVertices AND t.selectedShape # -1 AND t.selectedVertex # -1; cg6: G3dDraw.UseCG6 ¬ IF useCG6 AND whatChanged # $IPOut AND NOT t.drawOptions.tapered AND NOT t.drawOptions.dimFurtherLines AND G3dDraw.CG6Available[] THEN y ELSE n; IF cg6 = y THEN G3dDraw.WrapInCG6[context, Action] ELSE Action[]; }; InvalidateVertexScreens: PUBLIC PROC [t: Tool, which: G3dTool.WhichVertices] ~ { IF t.shapes # NIL THEN FOR n: NAT IN [0..t.shapes.length) DO s: Shape ¬ t.shapes[n]; IF s # NIL AND (which = all OR s.selected) THEN { renderData: G3dRender.RenderData ¬ G3dRender.RenderDataFrom[s]; IF t.views # NIL THEN FOR i: NAT IN [0..t.views.length) DO screens: G3dTool.ScreenSequence ¬ t.views[i].screens[n]; screens.screensValid ¬ screens.extentValid ¬ FALSE; ENDLOOP; }; ENDLOOP; }; DrawOpsButton: PUBLIC ClickProc ~ { save: BOOL ¬ FALSE; t: Tool ¬ NARROW[clientData]; choice: INT ¬ Controls.PopUpRequest[["Draw Ops"], LIST[ -- 1 -- Controls.BoolRequest[t.drawOptions.flatShade, "Flat Shade"], -- 2 -- Controls.BoolRequest[t.drawOptions.hiddenLineElim, "Hidden Line Elimination"], -- 3 -- Controls.BoolRequest[t.drawOptions.vertexNormals, "Vertex Normals"], -- 4 -- Controls.BoolRequest[t.drawOptions.faceNormals, "Face Normals"], -- 5 -- Controls.BoolRequest[t.drawOptions.verticesOnly, "Vertices Only"], -- 6 -- Controls.BoolRequest[t.drawOptions.labelVertices, "Label Vertices"], -- 7 -- Controls.BoolRequest[t.drawOptions.labelPolygons, "Label Polygons"], -- 8 -- Controls.BoolRequest[t.drawSprite, "Sprite"], -- 9 -- Controls.BoolRequest[t.drawPendant, "Pendant"], -- 10 -- Controls.BoolRequest[t.drawClient, "Client Display"], -- 11 -- Controls.BoolRequest[t.timing, "Timing"], -- 12 -- Controls.BoolRequest[t.drawOptions.silhouettesOnly, "Silhouettes"], -- 13 -- Controls.BoolRequest[t.drawOptions.backFaces=dashed, "Dashed Backfaces"], -- 14 -- Controls.BoolRequest[t.drawCurves, "Curves"], -- 15 -- Controls.BoolRequest[t.queryVertices, "Vertex Querying"], -- 16 -- Controls.BoolRequest[t.drawOptions.tapered, "Tapered lines"], -- 17 -- Controls.BoolRequest[t.drawOptions.dimFurtherLines, "Dim far lines"], -- 18 -- ["SetDrawMode", "Line Drawing Mode (will prompt)"], -- 19 -- ["Stuff", "Stuff to Tioga selection"], -- 20 -- ["Write Vectors", "Write 2d vectors to a file"]]]; SELECT choice FROM 1 => t.drawOptions.flatShade ¬ NOT t.drawOptions.flatShade; 2 => t.drawOptions.hiddenLineElim ¬ NOT t.drawOptions.hiddenLineElim; 3 => t.drawOptions.vertexNormals ¬ NOT t.drawOptions.vertexNormals; 4 => t.drawOptions.faceNormals ¬ NOT t.drawOptions.faceNormals; 5 => t.drawOptions.verticesOnly ¬ NOT t.drawOptions.verticesOnly; 6 => t.drawOptions.labelVertices ¬ NOT t.drawOptions.labelVertices; 7 => t.drawOptions.labelPolygons ¬ NOT t.drawOptions.labelPolygons; 8 => IF (t.drawSprite ¬ NOT t.drawSprite) THEN save ¬ TRUE; 9 => t.drawPendant ¬ NOT t.drawPendant; 10 => t.drawClient ¬ NOT t.drawClient; 11 => t.timing ¬ NOT t.timing; 12 => t.drawOptions.silhouettesOnly ¬ NOT t.drawOptions.silhouettesOnly; 13 => t.drawOptions.backFaces ¬ IF t.drawOptions.backFaces = dashed THEN on ELSE dashed; 14 => { t.drawCurves ¬ NOT t.drawCurves; IF t.drawCurves AND t.shapes # NIL THEN FOR n: NAT IN [0..t.shapes.length) DO m: G3dModel.Model ¬ G3dModel.GetModel[t.shapes[n]]; IF m.curves = NIL THEN G3dModel.SetCurves[t.shapes[n]]; ENDLOOP; }; 15 => IF (t.queryVertices ¬ NOT t.queryVertices) THEN save ¬ TRUE; 16 => t.drawOptions.tapered ¬ NOT t.drawOptions.tapered; 17 => t.drawOptions.dimFurtherLines ¬ NOT t.drawOptions.dimFurtherLines; 18 => { choice: INT ¬ Controls.MultiRequest["Line Drawing Mode is ", LIST[ ["Solid", t.drawOptions.lineType = solid AND NOT t.drawOptions.verticesOnly], ["Dashed", t.drawOptions.lineType = dashed AND NOT t.drawOptions.verticesOnly], ["Dotted", t.drawOptions.lineType = dotted AND NOT t.drawOptions.verticesOnly]]]; t.drawOptions.lineType ¬ SELECT choice FROM 2 => dashed, 3 => dotted, ENDCASE => solid; }; 19 => { DoStuff: PROC [context: Context] ~ { Inner: PROC ~ {G3dTool.Draw[context, NIL, $Stuff, NIL, [], NIL, t, t]}; Imager.TranslateT[context, [-t.bounds.x, -t.bounds.y]]; Imager.DoSaveAll[context, Inner]; }; ImagerArtwork.PasteArtwork[DoStuff, t.bounds, ImagerArtwork.Points[],,, FALSE]; }; 20 => { fileName: ROPE ¬ Controls.TypescriptReadFileName[t.typescript]; IF fileName # NIL AND t.shapes # NIL THEN { out: IO.STREAM ¬ PFS.StreamOpen[PFS.PathFromRope[fileName], create]; v: View ¬ G3dTool.GetView[NIL, t]; IO.PutF1[t.cmd.out, "Writing %g\n", IO.rope[fileName]]; FOR n: NAT IN [0..v.screens.length) DO s: Shape ¬ t.shapes[n]; screens: G3dTool.ScreenSequence ¬ v.screens[n]; FOR i: NAT IN [0..s.edges.length) DO e: G3dShape.Edge ¬ s.edges[i]; p0: G3dBasic.Pair ¬ screens[e.v0].pos; p1: G3dBasic.Pair ¬ screens[e.v1].pos; IO.PutFL[out, "%6.5f\t%6.5f\t%6.5f\t%6.5f\n", LIST[IO.real[p0.x], IO.real[p0.y], IO.real[p1.x], IO.real[p1.y]]]; ENDLOOP; ENDLOOP; IO.Close[out]; }; }; ENDCASE; IF save THEN G3dTool.Repaint[t, $Save]; IF Controls.GetPopUpButton[] = right AND choice > 0 AND choice # 10 THEN Repaint[t, $DrawOps]; }; UseCG6: Commander.CommandProc ~ { SELECT TRUE FROM Rope.Equal[Args.GetRope[cmd], "yes"] => useCG6 ¬ TRUE; Rope.Equal[Args.GetRope[cmd], "no"] => useCG6 ¬ FALSE; Rope.Equal[Args.GetRope[cmd], "?"] => IO.PutF1[cmd.out, "useCG6 = %g\n", IO.rope[IF useCG6 THEN "yes" ELSE "no"]]; ENDCASE => IO.PutRope[cmd.out, "specify yes, no, or ?\n"]; }; G3dTool.Register["UseCG6", UseCG6, "enable or disable CG6"]; END. .. doubleBuffer: BOOL ¬ FALSE; IF NOT doubleBuffer THEN { Imager.SetColor[context, Imager.white]; Imager.SetColor[context, Imager.black]; }; IF doubleBuffer THEN { mn: SF.Vec ¬ SF.Min[v.extent.min, v.previousExtent.min]; mx: SF.Vec ¬ SF.Max[v.extent.max, v.previousExtent.max]; Imager.DoWithBuffer[context, A, mn.f, mn.s, mx.f-mn.f, mx.s-mn.s, Imager.white]; } ELSE ViewerAbort.CallWithAbortEnabled[viewer, A]; G3dTool.StartTimer[t]; t.previousDisplayTime ¬ G3dTool.ElapsedTime[t]; noneSelected: BOOL ¬ t.selectedShape = -1 AND t.focusNode = NIL; SetScreensGetExtent: PROC [t: Tool, v: View, context: Context, whatChanged: REF ANY] RETURNS [b: SF.Box] ~ { clientDraw: BOOL ¬ t.client.draw # NIL; fullBox: SF.Box ¬ [[0, 0], [10000, 10000]]; IF NOT clientDraw AND t = G3dTool.GetActiveTool[] THEN FOR c: LIST OF Client ¬ G3dTool.GetActiveClients[], c.rest WHILE c # NIL DO IF c.first.draw # NIL THEN {clientDraw ¬ TRUE; EXIT}; ENDLOOP; SELECT whatChanged FROM $Camera, $DrawOps, $ShapeOps, $Scene, $Pose, NIL => { rb: G2dBasic.Box ¬ [[10000, 10000], [-10000, -10000]]; IF v.context3d.shapes = NIL THEN RETURN[[[0, 0], [0, 0]]]; FOR n: NAT IN [0..t.shapes.length) DO s: Shape ¬ t.shapes[n]; IF s.visible THEN { scr: G3dShape.ScreenSequence ¬ v.screens[n]; IF scr = NIL OR NOT scr.screensValid THEN v.screens[n] ¬ scr ¬ G3dShape.SetScreenCoords[context, s, v.camera.matrix, scr, TRUE]; rb.min ¬ [MIN[rb.min.x, scr.extent.min.x], MIN[rb.min.y, scr.extent.min.y]]; rb.max ¬ [MAX[rb.max.x, scr.extent.max.x], MAX[rb.max.y, scr.extent.max.y]]; }; ENDLOOP; b.min ¬ [Real.Round[rb.min.y], Real.Round[rb.min.x]]; b.max ¬ [Real.Round[rb.max.y], Real.Round[rb.max.x]]; }; $IPOut, $Stuff, $SelectShape, $View => RETURN[v.extent]; ENDCASE => RETURN[fullBox]; IF clientDraw THEN RETURN[fullBox]; IF t.queryVertices AND t.selectedShape # -1 AND t.selectedVertex # -1 THEN b ¬ [SF.Sub[b.min, [5, 5]], SF.Add[b.max, [10, 10]]]; };  G3dToolDrawImpl.mesa Copyright c 1985 by Xerox Corporation. All rights reserved. Bloomenthal, April 9, 1993 4:04 pm PDT Heckbert, August 9, 1988 5:51:51 pm PDT 3d Tool: Line Drawing Types Line Drawing Display Print: PROC [context: Context, x, y: INTEGER, rope: ROPE] ~ { font: Imager.Font ¬ ImagerFont.Find["xerox/tiogafonts/helvetica18"]; Imager.SetFont[context, font]; IF x # -1 AND y # -1 THEN Imager.SetXY[context, [x, y]]; Imager.ShowRope[context, rope]; }; double buffering method, which, however, does not work with the CG6 hardware because the CG6 only functions with the actual SparcStation frame buffer and cannot write into other memory, such as the scratch sample map ViewerAbortAction: PROC ~ { Action: PROC [map: ImagerSample.RasterSampleMap] ~ { Restore: PROC [pm: Imager.PixelMap] ~ { ImagerSample.Transfer[pm[0], map, ImagerSample.GetBox[pm[0]].min]; }; maps: CtBasic.SampleMaps ¬ CtBasic.SampleMapsFromMaps[map, NIL, NIL]; temp: Context ¬ CtBasic.ContextFromSampleMaps[maps]; DoDraw[temp, tool, whatChanged, viewer, v]; ImagerBackdoor.AccessBufferRectangle[context, Restore, bounds]; }; bounds: Imager.Rectangle ¬ ImagerBackdoor.GetBounds[context]; box: ImagerSample.Box ¬ [ [Real.Round[bounds.y], Real.Round[bounds.x]], [Real.Round[bounds.h], Real.Round[bounds.w]]]; ImagerSample.DoWithScratchMap[box, 8, Action]; }; It appears (see G3dDraw.Vector, eg) that Draw2d calls can be wrapped within CG6. context.propList ¬ Prop.Rem[context.propList, $CG6]; -- disable CG6 in other procs Imager.SetStrokeWidth[context, IF whatChanged=$IPOut THEN t.ipStrokeWidth ELSE 0]; Line/Flat-Shade Drawing Ops Initialization IF (toggle ¬ NOT toggle) THEN { TerminalIO.PutF["eye = (%6.4f %6.4f %6.4f), ", IO.real[t.camera.eyePoint.x], IO.real[t.camera.eyePoint.y], IO.real[t.camera.eyePoint.z]]; TerminalIO.PutF["look = (%6.4f %6.4f %6.4f)\n", IO.real[t.camera.lookAt.x], IO.real[t.camera.lookAt.y], IO.real[t.camera.lookAt.z]]; WriteCamera[v.context3d]; }; toggle: BOOL ¬ TRUE; WriteCamera: PROC [c: Context3d] ~ { pi: REAL ¬ 3.14159265359; AimZ: PROC [direction: Triple] ~ { xzlen, yzlen, yrot, xrot: REAL; TerminalIO.PutF["direction %7.5f %7.5f %7.5f\n", IO.real[direction.x], IO.real[direction.y], IO.real[direction.z]]; IF G3dVector.Null[direction] THEN {TerminalIO.PutF["NULL!\n"]; RETURN}; xzlen ¬ RealFns.SqRt[direction.x*direction.x+direction.z*direction.z]; TerminalIO.PutF["xzlen = %g\n", IO.real[xzlen]]; yrot ¬ IF xzlen = 0.0 THEN (IF direction.y < 0.0 THEN 180.0 ELSE 0.0) ELSE 180.0*G2dBasic.ArcCos[direction.z/xzlen]/pi; yzlen ¬ RealFns.SqRt[direction.y*direction.y+xzlen*xzlen]; xrot ¬ 180.0*G2dBasic.ArcCos[xzlen/yzlen]/pi; TerminalIO.PutF["Rotate %7.5f 1.0 0.0 0.0\n", IO.real[IF direction.y > 0.0 THEN xrot ELSE -xrot]]; TerminalIO.PutF["Rotate %7.5f 0.0 1.0 0.0\n", IO.real[IF direction.x > 0.0 THEN -yrot ELSE yrot]]; }; eye: Triple ¬ [c.eyePoint.x, c.eyePoint.y, -c.eyePoint.z]; -- negate z look: Triple ¬ [c.lookAt.x, c.lookAt.y, -c.lookAt.z]; -- negate z TerminalIO.PutF["up %7.5f %7.5f %7.5f\n", IO.real[c.upDirection.x], IO.real[c.upDirection.y], IO.real[c.upDirection.z]]; TerminalIO.PutF["Rotate %7.5f 0.0 0.0 1.0\n", IO.real[c.rollAngle]]; AimZ[G3dVector.Sub[look, eye]]; TerminalIO.PutF["Translate %7.5f %7.5f %7.5f\n\n", IO.real[-eye.x], IO.real[-eye.y], IO.real[-eye.z]]; }; doubleBuffer ¬ t.buffering = double OR (t.buffering = default AND (t.previousDisplayTime < maxDisplayTime OR t.drawOptions.silhouettesOnly)); w: INTEGER ¬ v.previousExtent.max.f-v.previousExtent.min.f+1; h: INTEGER ¬ v.previousExtent.max.s-v.previousExtent.min.s+1; Imager.MaskRectang[context,v.previousExtent.min.f,v.previousExtent.min.s,w,h]; v.previousExtent ¬ v.extent; v.extent ¬ SetScreensGetExtent[t, v, context, whatChanged]; $SelectShape, $Pose => { IF t.previousWhatChanged = whatChanged OR noneSelected THEN Restore[context, v, $Unselected] ELSE { Draw2d.Clear[context]; IdentifyView[]; DrawCertainShapes[IF whatChanged = $Pose THEN unselected ELSE all, dashed]; Store[context, v, $Unselected]; }; DrawCertainShapes[selected, solid]; Store[context, v, $Frame]; }; Ê!ü•NewlineDelimiter ™™Jšœ Ïmœ1™J˜—–( Postfix0.320 0.931 0.362 textColor š§ œŸœ˜J˜Lš œŸœŸœ ¨œ¨œ¨œŸœ˜.JšŸœŸœŸœŸœ˜]—JšŸ¨œ¨Ÿ¨œ¨œŸœ ¨œ¨œ¨œ Ÿœ˜\JšœI˜IJ˜JJ˜—–( Postfix0.320 0.931 0.362 textColor š§ œ¨Ÿ¨œ¨œ˜–(Postfix0.320 0.931 0.362 textColorš§œŸœŸœŸœ˜%JšŸ¨œŸ¨Ÿ¨Ÿœ¨Ÿ¨œŸ¨Ÿ¨œ¨œ¨œ¨Ÿœ˜KJ˜—JšœŸœŸœ˜JšŸœŸœŸœ˜$Jš Ÿœ ŸœŸœŸœŸœ˜/šŸœŸœŸœŸœŸœŸœŸœŸœŸ˜WJšŸœŸœ ŸœŸœ˜0JšŸœ˜—J˜+šŸœ˜ šŸœ˜J˜=J˜+J˜—šŸœ˜J˜7J˜7J˜+J˜——JšœŸœŸœ˜@J˜—–( Postfix0.320 0.931 0.362 textColor!š§ œŸœŸœŸœ˜,JšŸœŸœŸœŸœ˜ šŸœŸ˜JšŸœI˜M—šŸœŸ˜#š ŸœŸœŸœ-ŸœŸœŸ˜KšŸœŸ˜JšŸœG˜K—JšŸœ˜——J˜—–(Postfix0.320 0.931 0.362 textColor š§œŸœ˜–(Postfix0.320 0.931 0.362 textColorDš§œ¨Ÿ¨œ¨œ ¨œ ¨œ¨œ¨œ˜UJšœ¨œ¨œÐdsŸœ ŸœŸœŸœŸœ ˜^šŸœ ŸœŸ˜šŸœŸœŸœŸ˜%J˜šŸ¨œ¨œ¨Ÿ¨Ÿ¨œ ¨Ÿ¨œ ¨Ÿ¨œ¨Ÿœ˜RJ˜$J˜JšŸœŸœŸœ˜Eš Ÿ¨Ÿ¨œ¨Ÿ¨œ˜,JšŸ¨œ˜#—šœ ¨œ˜J˜D—J˜J˜—JšŸœ˜——J˜—Jš£œ'˜@Jš£œ$˜=š Ÿœ ŸœŸœ Ÿœ ŸœŸœ˜;–(Postfix0.320 0.931 0.362 textColor&š§œŸœŸœŸœ˜-–(Postfix0.320 0.931 0.362 textColor4š§œŸœ"Ÿœ˜<šŸœ˜JšŸœA˜EšŸœ˜J˜8J˜8J˜8J˜——J˜—Jšœ Ÿœ˜(J˜QJšœ'˜'Jšœ'˜'J˜8J˜8J˜8J˜8J˜8J˜8J˜—Jšœ Ÿœ˜-š ŸœŸœŸœŸœŸœŸ˜>J˜ J˜KJšœ¨œ¨œ¨Ÿ¨œ"¨œ ¨œ¨Ÿ¨œ¨Ÿ¨œ˜[J˜J˜J˜?J˜8JšŸœ˜—J˜,J˜—J˜—–(Postfix0.320 0.931 0.362 textColor š§œŸœ˜JšœŸœ˜5JšŸœŸœ&˜BJ˜—–(Postfix0.320 0.931 0.362 textColor š§œŸœ˜šŸœ Ÿ˜J˜Jšœ(ŸœŸœ˜FJšœ ŸœŸœ,˜KJš Ÿœ ¨œ ¨œ¨œ ¨œ¨œ˜Cš¢!œ˜&J–'5Postfix16.0 24 .div 1 1 textColoršœ4£™RJ˜Jšœ˜Jš œ¨Ÿ¨œ¨Ÿ¨œ¨Ÿ¨œ™RJšœ¨œ˜0J˜+J˜J˜JšŸœ Ÿœ ˜JšŸœŸœ>˜SJšŸœŸœ˜JšŸœŸœ˜"J𡢡¢¡¢¡¢˜CJ˜—Jšœ˜šŸœ˜ Jšœ˜JšŸœ˜Jšœ˜——J˜J˜—Jšœ Ÿœ ˜J˜J˜$JšœŸœŸœŸœ˜R˜šŸœŸœŸ˜&JšŸœŸœŸœ˜?šŸœ˜JšŸœŸœ˜———šŸœ˜ JšŸœ#˜'JšŸœ ˜—J˜J˜—–(Postfix0.320 0.931 0.362 textColor9š§œŸœŸœ,˜PšŸœ ŸœŸ˜šŸœŸœŸœŸ˜%J˜š ŸœŸœŸœŸœ Ÿœ˜1J˜?š Ÿœ ŸœŸœŸœŸœŸœŸ˜:J˜8Jšœ-Ÿœ˜3JšŸœ˜—J˜—JšŸœ˜——J˜——–0.0 24 .div 1 1 textColoršž™–( Postfix0.320 0.931 0.362 textColorš§ œŸœ˜#JšœŸœŸœ˜Jšœ Ÿœ ˜šœŸœ'Ÿœ˜7Jš£œ@˜HJš£œP˜XJš£œF˜NJš£œB˜JJš£œD˜LJš£œF˜NJš£œF˜NJš£œ3˜;Jš£œ4˜˜FJš£œ@˜HJš£œF˜NJš£œ4˜Jšœ;Ÿœ˜A—Jšœ ŸœŸœ˜LJšœ ŸœŸœ˜LJ˜—JšŸœ˜—J˜5J˜5J˜—Jšœ¨œ¨œŸœ ˜8JšŸœŸœ ˜—JšŸœ ŸœŸœ ˜#šŸœŸœŸœ˜EJšŸœŸœŸœ˜:—J˜J˜—J˜——…—BÄtÀ