<> <> <> DIRECTORY Atom, BasicTime, CedarProcess, Commander, FS, G3dAnimationSupport, G3dBasic, G3dColorDisplaySupport, G3dRender, G3dRenderWithImager, G3dRenderWithPixels, G3dShape, G3dSortandDisplay, Imager, ImagerBackdoor, ImagerPixel, ImageTwiddle, List, Process, Random, Real, Rope, Terminal, ThreeDViewer, ViewerTools; ThreeDDemoImpl: CEDAR MONITOR IMPORTS Atom, BasicTime, CedarProcess, Commander, FS, G3dAnimationSupport, G3dColorDisplaySupport, G3dRender, G3dRenderWithImager, G3dRenderWithPixels, G3dShape, G3dSortandDisplay, Imager, ImagerBackdoor, ImagerPixel, ImageTwiddle, List, Process, Random, Real, Rope, Terminal, ThreeDViewer, ViewerTools ~ BEGIN <> PropList: TYPE ~ Atom.PropList; ROPE: TYPE ~ Rope.ROPE; Context: TYPE ~ G3dRender.Context; RealSequence: TYPE ~ G3dBasic.RealSequenceRep; IntegerPair: TYPE ~ G3dRender.IntegerPair; Pair: TYPE ~ G3dRender.Pair; Pixel: TYPE ~ G3dRender.Pixel; Triple: TYPE ~ G3dRender.Triple; Rectangle: TYPE ~ G3dRender.Rectangle; RGB: TYPE ~ G3dRender.RGB; Patch: TYPE ~ G3dRender.Patch; ShadingClass: TYPE ~ G3dRender.ShadingClass; Shape: TYPE ~ G3dRender.Shape; ShapeRep: TYPE ~ G3dShape.ShapeRep; ShapeSequence: TYPE ~ G3dRender.ShapeSequence; ShapeSequenceRep: TYPE ~ G3dShape.ShapeSequenceRep; RenderData: TYPE ~ G3dRender.RenderData; ImagerProc: TYPE ~ G3dRender.ImagerProc; ImagerProcRec: TYPE ~ G3dRender.ImagerProcRec; LORA: TYPE ~ LIST OF REF ANY; <> context3d, offScreenCtx: Context; -- , onScreenCtx currentScene, scene1, scene2, scene3: ShapeSequence _ NIL; lastDemoCalled: PROC[makeFrame: BOOLEAN _ FALSE]; frames: REF G3dAnimationSupport.FrameSequence; xNow, yNow, zNow: REAL _ 3.0; xPosition, yPosition: REAL _ 0.0; cursorRange: REAL _ 64.0; quadTime: REAL; animation: BOOLEAN _ FALSE; movieProcess: CedarProcess.Process _ NIL; cachedViewPort: Rectangle _ [0.0, 0.0, 0.0, 0.0]; windowStack, viewPortStack: LIST OF Rectangle _ NIL; mouseWaiting: ATOM _ NIL; mouseRectangle: REF Rectangle _ NIL; <> FindShape: PROC [context: Context, shapeName: ROPE] RETURNS [Shape] ~ G3dRender.FindShape; GetAIS: PROC[ context: Context, fileRoot: ROPE, xOffset, yOffset: INTEGER _ 0, center: BOOLEAN _ TRUE, labeled: BOOLEAN _ FALSE ] RETURNS[ xSize, ySize: INTEGER] ~ G3dColorDisplaySupport.GetAIS; GetProp: PROC [propList: PropList, prop: REF ANY] RETURNS [REF ANY] ~ Atom.GetPropFromList; PutProp: PROC [propList: PropList, prop: REF ANY, val: REF ANY] RETURNS [PropList] ~ Atom.PutPropOnList; <> demoMenu: LIST OF ThreeDViewer.ButtonDesc ~ LIST [ [ proc: SetScene, -- Select Scene choices: LIST[ [$Scene1, "Polyhedra on Checkerboard"], -- left mouse button [$Scene2, "Glass, Banana and Egg"], -- middle mouse button [$Scene3, "Bezier Teapot"], -- right mouse button [$OneShape, "Show One Shape (name from selection)"], -- shift left [NIL, NIL], -- shift middle [NIL, NIL], -- shift right [$Window, "2 Clicks in image define part of scene to display"], -- control left [$ViewPort, "2 Clicks in image define new screen area"], -- control middle [NIL, NIL], -- control right [$RestoreW, "Restore previous window"], -- control shift left [$RestoreVP, "Restore previous viewport"] -- control shift middle ], label: "Select Shapes", purpose: "Chooses scene to manipulate" ], [ proc: SetShading, -- Shading Style choices: LIST[ [$Lines, "Line Drawing"], -- left mouse button [$Facets, "Faceted Shading"], -- middle mouse button [$Smooth, "Smooth Shading"], -- right mouse button [$Hidden, "Hidden Line Drawing"], -- shift left [$Shiny, "Faceted Shading with Highlights"], -- shift middle [$Hilights, "Smooth Shading with Highlights"], -- shift right [$SmoLines, "Smooth Shading on Lines"], -- control left [$Normals, "Line drawing with normal vectors"] -- control middle ], label: "Shading Style", purpose: "Chooses shading for surfaces in current scene" ], [ proc: SetRenderingStyle, -- Rendering Style choices: LIST[ [$Jaggy, "Aliased"], -- left mouse button [$NoJaggy, "AntiAliased"], -- middle mouse button [NIL, NIL], -- right mouse button [$Visible, "Build Image On Display"], -- shift left [$Buffered, "Double Buffer Image"], -- shift middle [NIL, NIL], -- shift right [$Imager, "Use Imager (faceted only)"], -- control left [$Pixels, "Use fancier tiler/shaders"], -- control middle [NIL, NIL], -- control right [$ZBuffer, "Use depth buffer for hidden surfaces"], -- control shift left [$Sorted, "Use sorting for hidden surfaces"], -- control shift middle [NIL, NIL], -- control shift right [$PseudoClr, "8-bit mapped color"], [$Gray, "8-bit grayscale"], [$FullClr, "24-bit full color"] ], label: "Rendering Style", purpose: "Chooses display type, antialising, and double buffering" ], [ proc: DoCommands, -- Commands choices: LIST[ [$Display, "Make a frame with the current scene"], -- left mouse button [$StoreImage, "Store image in file (name from selection)"], -- middle mouse button [$Interpress, "Interpress file (name from selection)"] -- right mouse button ], label: "Do It", purpose: "Make/Store images" ], [ proc: ShowMotion, -- Animation choices: LIST[ [$Orbit, "Orbit about scene computing frames on the fly"], -- left mouse button [$SelectDthr, "Take 8-bit dithered sequence name from selection"], -- middle button [$SelectGray, "Take 8-bit grayscale sequence name from selection"], -- right button [$Shapes, "Play back Banana, Glass, Egg scene"], -- shift left [$Terrain, "Play back Terrain flyover"], -- shift middle [NIL, NIL], -- shift right [$Web1, "Play back front view Paper web"], -- control left [$Web2, "Play back top view Paper web"], -- control middle ], label: "Animation", purpose: "Chooses various animations" ], [ proc: ShowPicture, -- Gallery choices: LIST[ [$SelectColor, "Take rgb file name from selection"], -- left mouse button [$SelectDthr, "Take 8-bit dithered file name from selection"], -- middle mouse button [$SelectGray, "Take 8-bit grayscale file name from selection"], -- right mouse button [$Spoon, "Newell's Bezier patch spoon"], -- shift left [$Bananas, "A field of bananas"], -- shift middle [$Compare, "Shading Comparison on Eggs"], -- shift right [$Bowl, "Sugar bowl with spoon"], -- control left [$TeaPot, "Teapot with Perlin texture"], -- control middle [$Eggtxtr, "Multi-textured Egg"], -- control right [$Heart, "Heart from two Bezier patches"], -- control shift left [$Objects, "Five objects on a checkerboard"], -- control shift middle [$Extents, "Five objects with bounding boxes"], -- control shift right [$HexTiles, "Objects on hex-tiled plane"], [$MikHead, "Mik leers over the curvaceous glass"], [$MikTrees, "Mik leers over scanned-in trees"], [$BallPage, "A sphere with a page of text"], [$BallPages, "A sphere with many pages of text"], [$TeaPages, "Teapot with pages of text"], [$SolidLines, "Drawing with fat lines"] ], label: "Gallery", purpose: "Chooses a pretty picture to display" ], [ proc: StopEverything, -- STOP! button choices: LIST[], -- No Choices, just calls proc label: "STOP!", purpose: "Panic button, stops all 3D activity" ], [ proc: DoReset, -- Reset button choices: LIST[], -- No Choices, just calls proc label: "Reset", purpose: "Reset button, can often get things unwedged" ] ]; SetScene: ENTRY PROC[context: Context, key: ATOM] ~ { context.stopMe^ _ FALSE; -- unstick stop button { ENABLE UNWIND => NULL; -- get out and release lock if error, etc. SELECT key FROM $Scene1 => SetScene1[]; $Scene2 => SetScene2[]; $Scene3 => SetScene3[]; $OneShape => OneShape[]; $Window => GetWindow[]; $ViewPort => GetViewPort[]; $RestoreW => RestoreWindow[]; $RestoreVP => RestoreViewPort[]; ENDCASE; }; }; SetShading: ENTRY PROC[context: Context, key: ATOM] ~ { context.stopMe^ _ FALSE; -- unstick stop button { ENABLE UNWIND => NULL; SELECT key FROM $Lines => LinesDemo[]; $Facets => { SetDull[]; FacetedDemo[]; }; $Smooth => { SetDull[]; SmoothDemo[]; }; $Hidden => HiddenLinesDemo[]; $Shiny => { SetShiny[]; FacetedDemo[]; }; $Hilights => { SetShiny[]; SmoothDemo[]; }; $SmoLines => IF context.class.displayType # $PseudoColor OR ThreeDViewer.SwitchDisplayTo[context, $FullColor] THEN { -- only for $Gray and $FullColor context.preferredRenderMode _ $Pixels; ShadedLinesDemo[]; }; $Normals => NormaledLinesDemo[]; ENDCASE; }; }; SetRenderingStyle: ENTRY PROC[context: Context, key: ATOM] ~ { context.stopMe^ _ FALSE; -- unstick stop button SELECT key FROM $Jaggy => G3dRenderWithPixels.AntiAliasing[context, FALSE]; $Visible => G3dRenderWithPixels.BufferRendering[context, FALSE]; $Imager => context.preferredRenderMode _ $Imager; $NoJaggy => IF context.class.displayType # $PseudoColor OR ThreeDViewer.SwitchDisplayTo[context, $FullColor] THEN { context.preferredRenderMode _ $Pixels; G3dRenderWithPixels.AntiAliasing[context, TRUE]; }; $Buffered => G3dRenderWithPixels.BufferRendering[context, TRUE]; $Pixels => context.preferredRenderMode _ $Pixels; $ZBuffer => G3dRenderWithPixels.DepthBuffering[context, TRUE]; $Sorted => G3dRenderWithPixels.DepthBuffering[context, FALSE]; $PseudoClr => [] _ ThreeDViewer.SwitchDisplayTo[context, $PseudoColor]; $Gray => [] _ ThreeDViewer.SwitchDisplayTo[context, $Gray]; $FullClr => [] _ ThreeDViewer.SwitchDisplayTo[context, $FullColor]; ENDCASE; { ENABLE UNWIND => NULL; ThreeDViewer.DrawInViewer[context, NIL]; }; }; DoCommands: ENTRY PROC[context: Context, key: ATOM] ~ { context.stopMe^ _ FALSE; -- unstick stop button { ENABLE UNWIND => NULL; SELECT key FROM $Display => { IF DemoErrorMessages[] THEN RETURN; SELECT lastDemoCalled FROM LinesDemo => MakeFrame[]; ShadedLinesDemo => MakeFrame[]; HiddenLinesDemo => HiddenLinesDemo[TRUE]; NormaledLinesDemo => NormaledLinesDemo[TRUE]; FacetedDemo => MakeFrame[]; SmoothDemo => MakeFrame[]; ENDCASE => MakeFrame[]; }; $StoreImage => G3dColorDisplaySupport.PutAIS[ context3d, ViewerTools.GetSelectionContents[] ]; $Interpress => InterpressDemo[]; ENDCASE; }; }; ShowMotion: ENTRY PROC[context: Context, key: ATOM] ~ { SetSingleBuffer: PROC[] ~ { G3dRenderWithPixels.AntiAliasing[context, FALSE]; G3dRenderWithPixels.DepthBuffering[context, FALSE]; }; context.stopMe^ _ FALSE; -- unstick stop button { ENABLE UNWIND => NULL; IF key = $Orbit OR context.class.displayType # $FullColor OR ThreeDViewer.SwitchDisplayTo[context, $PseudoColor] -- ensure 8-bit display THEN SELECT key FROM $Orbit => Orbit[]; $SelectDthr => { [] _ ThreeDViewer.SwitchDisplayTo[context, $PseudoColor]; SetSingleBuffer[]; SetUpMovie[ fileRoot: ViewerTools.GetSelectionContents[] ]; }; $SelectGray => { [] _ ThreeDViewer.SwitchDisplayTo[context, $Gray]; SetSingleBuffer[]; SetUpMovie[ fileRoot: ViewerTools.GetSelectionContents[] ]; }; $Shapes => { [] _ ThreeDViewer.SwitchDisplayTo[context, $PseudoColor]; SetSingleBuffer[]; SetUpMovie[ fileRoot: "/Pixel/Crow/Animation/StillCloser.ais", numFiles: 40, start: 1 ]; }; $Terrain => { [] _ ThreeDViewer.SwitchDisplayTo[context, $PseudoColor]; SetSingleBuffer[]; SetUpMovie[ fileRoot: "/Cyan/AIS/Animation/LakeSceneTest.ais", numFiles: 64 ]; ImageTwiddle.SetUpTerrainColors[context.terminal]; }; $Web1 => { [] _ ThreeDViewer.SwitchDisplayTo[context, $Gray]; SetSingleBuffer[]; SetUpMovie[ fileRoot: "/Pixel/Crow/Animation/Paper4Web.ais", numFiles: 40 ]; }; $Web2 => { [] _ ThreeDViewer.SwitchDisplayTo[context, $Gray]; SetSingleBuffer[]; SetUpMovie[ fileRoot: "/Pixel/Crow/Animation/Paper5Web.ais", numFiles: 40 ]; }; ENDCASE; IF key # $Orbit THEN movieProcess _ CedarProcess.Fork[PlayBackbyFrame]; }; }; ShowPicture: ENTRY PROC[context: Context, key: ATOM] ~ { context.stopMe^ _ FALSE; -- unstick stop button { ENABLE UNWIND => NULL; SELECT key FROM $SelectDthr => IF context.class.displayType # $PseudoColor THEN IF ThreeDViewer.SwitchDisplayTo[context, $PseudoColor] THEN -- switch to dithered { [] _ CedarProcess.Fork[ WaitThenShowPicture, LIST[context, key] ]; RETURN; }; $SelectGray => IF context.class.displayType # $Gray THEN IF ThreeDViewer.SwitchDisplayTo[context, $Gray] THEN -- switch to 8-bit gray { [] _ CedarProcess.Fork[ WaitThenShowPicture, LIST[context, key] ]; RETURN; }; ENDCASE => IF context.class.displayType # $FullColor THEN IF ThreeDViewer.SwitchDisplayTo[context, $FullColor] THEN -- switch to full color { [] _ CedarProcess.Fork[ WaitThenShowPicture, LIST[context, key] ]; RETURN; }; SELECT key FROM $SelectDthr, $SelectGray, $SelectColor => [] _ GetAIS[context3d, ViewerTools.GetSelectionContents[] ]; $Spoon => [] _ GetAIS[context3d, "/cyan/AIS/Crow/Spoon.ais" ]; $Bananas => [] _ GetAIS[context3d, "/cyan/AIS/Crow/FieldOfBanana.ais" ]; $Compare => [] _ GetAIS[context3d, "/cyan/AIS/Crow/ComparisonEggs.ais" ]; $Bowl => [] _ GetAIS[context3d, "/cyan/AIS/Crow/BowlAndSpoon.ais" ]; $TeaPot => [] _ GetAIS[context3d, "/cyan/AIS/Crow/ZebraBurlTeaPot.ais" ]; $Eggtxtr => [] _ GetAIS[context3d, "/cyan/AIS/Crow/MultiTxtrdEgg2.ais" ]; $Heart => [] _ GetAIS[context3d, "/cyan/AIS/Crow/Heart.ais" ]; $Objects => [] _ GetAIS[context3d, "/cyan/AIS/Crow/TestScene2.ais" ]; $Extents => [] _ GetAIS[context3d, "/cyan/AIS/Crow/FiveObjWBoxes.ais" ]; $HexTiles => [] _ GetAIS[context3d, "/cyan/AIS/Crow/HexTiles.ais" ]; $MikHead => [] _ GetAIS[context3d, "/cyan/AIS/Crow/Lamming6Scene.ais" ]; $MikTrees => [] _ GetAIS[context3d, "/cyan/AIS/Crow/Lamming7Scene.ais" ]; $BallPage => [] _ GetAIS[context3d, "/cyan/AIS/Crow/SphereWithPage.ais" ]; $BallPages => [] _ GetAIS[context3d, "/cyan/AIS/Crow/SphereWithPages.ais" ]; $TeaPages => [] _ GetAIS[context3d, "/cyan/AIS/Crow/PagedTeaPot.ais" ]; $SolidLines => [] _ GetAIS[context3d, "/cyan/AIS/Crow/StillLines.ais" ]; ENDCASE }; }; WaitThenShowPicture: CedarProcess.ForkableProc ~ { <> <> list: LORA _ NARROW[data]; context: Context _ NARROW[list.first]; key: ATOM _ NARROW[list.rest.first]; WHILE GetProp[ context.displayProps, $ViewerAdjusted ] # NIL DO Process.PauseMsec[ 500 ]; ENDLOOP; -- wait for viewer paint proc to complete ShowPicture[context, key]; }; StopEverything: PROC[context: Context, key: ATOM] ~ { -- panic stop bkgrdContext: Context _ NIL; WITH GetProp[context.props, $BackGround] SELECT FROM bkGrdCtx: Context => bkgrdContext _ bkGrdCtx; ENDCASE; context.stopMe^ _ TRUE; WHILE bkgrdContext # NIL DO -- stop chain of background contexts tmpCtx: Context _ bkgrdContext; tmpCtx.stopMe^ _ TRUE; bkgrdContext _ NARROW[GetProp[tmpCtx.props, $BackGround]]; ENDLOOP; IF movieProcess # NIL THEN { Process.Yield[]; CedarProcess.Abort[movieProcess]; movieProcess _ NIL; Process.Yield[]; G3dRender.SetViewPort[ context, cachedViewPort ]; }; }; DoReset: PROC [context: Context, key: ATOM] ~ { -- get out of stuckness, start over StopEverything[context, NIL]; Process.PauseMsec[ 3000 ]; -- wait 3 seconds for processes to stop context3d.stopMe^ _ FALSE; -- get stop flag unstuck, if necessary context3d.window _ NIL; context3d.shapes _ context3d.visibleShapes _ NIL; context3d.lightSources _ NIL; G3dRender.SetView[ context3d, [2.0, -10.0, 3.0], [0.0, 0.0, 0.0] ]; G3dRender.AddLight[context3d, "Light0", [-100., -200., 50.] ]; G3dRender.SetViewPort[context3d, [0.0, 0.0, 65536.0, 65536.0] ]; windowStack _ viewPortStack _ NIL; mouseWaiting _ NIL; mouseRectangle _ NIL; currentScene _ NIL; frames _ NIL; context3d.props _ Atom.RemPropFromList[ context3d.props, $SinglePatch ]; context3d.props _ Atom.RemPropFromList[ context3d.props, $SingleVtx ]; }; <> ThreeDDemoCommand: Commander.CommandProc ~ { context3d _ G3dRender.Create[]; context3d.preferredRenderMode _ $Pixels; -- $Pixels, Imager; ThreeDViewer.MakeViewer[ context: context3d, displayType: $PseudoColor, -- $Gray, ImagerDithered bannerName: "ThreeDWorld Demonstration", menu: demoMenu, mouseAction: MouseControl, verticalMenu: FALSE ]; G3dRender.NameBackgroundColor[ context3d, "Darkish Blue" ]; -- set background color G3dRender.NameAmbientLight[ context3d, "Darkish Gray" ]; -- set ambient light G3dRender.AddLight[context3d, "Light0", [-100., -200., 50.] ]; G3dRender.SetView[ context3d, [2.0, -10.0, 3.0], [0.0, 0.0, 0.0] ]; }; InitNoDisplay: PROC[] ~ { context3d _ G3dRender.Create[]; G3dRender.NameBackgroundColor[ context3d, "Darkish Blue" ]; -- set background color G3dRender.NameAmbientLight[ context3d, "Darkish Gray" ]; -- set ambient light G3dRender.AddLight[context3d, "Light0", [-100., -200., 50.] ]; G3dRender.SetView[ context3d, [2.0, -10.0, 3.0], [0.0, 0.0, 0.0] ]; }; InitNoViewer: PROC[] ~ { context3d _ G3dRender.Create[]; G3dRender.LoadDisplayClass[context3d, $PseudoColor]; G3dRender.NameBackgroundColor[ context3d, "Darkish Blue" ]; -- set background color G3dRender.NameAmbientLight[ context3d, "Darkish Gray" ]; -- set ambient light G3dRender.AddLight[context3d, "Light0", [-100., -200., 50.] ]; G3dRender.SetView[ context3d, [2.0, -10.0, 3.0], [0.0, 0.0, 0.0] ]; }; InitNoViewerFullColor: PROC[] ~ { context3d _ G3dRender.Create[]; G3dRender.LoadDisplayClass[context3d, $FullColor]; G3dRender.NameBackgroundColor[ context3d, "Darkish Blue" ]; -- set background color G3dRender.NameAmbientLight[ context3d, "Darkish Gray" ]; -- set ambient light G3dRender.AddLight[context3d, "Light0", [-100., -200., 50.] ]; G3dRender.SetView[ context3d, [2.0, -10.0, 3.0], [0.0, 0.0, 0.0] ]; }; Reset: PROCEDURE [] ~ { DoReset[context3d, NIL]; }; MouseControl: ThreeDViewer.MouseProc ~ { <> <> <> <> width, height: INTEGER; divisor: REAL; IF mouseWaiting # NIL THEN { IF bttn = $LeftButton THEN GetMouseRectangle[x, y]; RETURN; }; IF context.viewer # NIL THEN { width _ context.viewer.ww; height _ context.viewer.wh; } ELSE { width _ context.pixels.box.max.f - context.pixels.box.min.f; height _ context.pixels.box.max.s - context.pixels.box.min.s; }; divisor _ ((width/2.0) * (width/2.0)) / cursorRange; x _ x - width / 2.0; -- center mouse coords y _ y - height / 2.0; SELECT bttn FROM $LeftButton, $LeftHeld => IF movieProcess # NIL THEN frameRate _ INTEGER[Real.Fix[x / 10.]] ELSE { xNow _ (x * ABS[x] / divisor) + context3d.lookAt.x; yNow _ (y * ABS[y] / divisor) + context3d.lookAt.y; G3dRender.SetView[ context, [xNow, yNow, zNow], context.lookAt, context.fieldOfView, context.rollAngle, context.upDirection, context.hitherLimit, context.yonLimit ]; DoCommands[context, $Display]; }; $MiddleButton, $MiddleHeld => { xLight: REAL _ x * 1.0; -- roughly plus or minus 300-500 yLight: REAL _ y * 1.0; [] _ G3dRender.AddLight[ context, "Light0", [xLight, yLight, 50.0] ]; DoCommands[context, $Display]; }; $RightButton, $RightHeld => { zNow _ (y * ABS[y] / divisor) + context3d.lookAt.z; G3dRender.SetView[ context, [xNow, yNow, zNow], context.lookAt, context.fieldOfView, context.rollAngle, context.upDirection, context.hitherLimit, context.yonLimit ]; DoCommands[context, $Display]; }; ENDCASE; }; <<>> MoveToCursor: PROC[] ~ { width, height, offset: INTEGER; sPos: IntegerPair; IF context3d.viewer # NIL THEN { width _ context3d.viewer.ww; height _ context3d.viewer.wh; offset _ 28; } ELSE { width _ context3d.pixels.box.max.f - context3d.pixels.box.min.f; height _ context3d.pixels.box.max.s - context3d.pixels.box.min.s; offset _ context3d.pixels.box.min.s }; [[sPos.x, sPos.y]] _ Terminal.GetColorCursorPosition[context3d.terminal]; xPosition _ 1.0 * sPos.x / width; yPosition _ 1.0 * (height - sPos.y + offset) / height; }; DrawToCursor: PROC[ color: RGB _ [1.0,1.0,1.0] ] ~ { width, height, offset: INTEGER; sPos: IntegerPair; newPos: Pair; clrPxl: Pixel _ [Real.Fix[color.R*255], Real.Fix[color.G*255], Real.Fix[color.B*255], 0, 0]; IF context3d.viewer # NIL THEN { width _ context3d.viewer.ww; height _ context3d.viewer.wh; offset _ 28; } ELSE { width _ context3d.pixels.box.max.f - context3d.pixels.box.min.f; height _ context3d.pixels.box.max.s - context3d.pixels.box.min.s; offset _ context3d.pixels.box.min.s }; [[sPos.x, sPos.y]] _ Terminal.GetColorCursorPosition[context3d.terminal]; newPos _ [1.0 * sPos.x / width, 1.0 * (height - sPos.y + offset) / height]; context3d.class.draw2DLine[ context3d, [xPosition, yPosition], newPos, clrPxl ]; xPosition _ newPos.x; yPosition _ newPos.y; }; TextAtCursor: PROC[ rope: ROPE, color: RGB _ [1.0,1.0,1.0], size: REAL _ 20.0, font: ROPE _ NIL ] ~ { sPos: IntegerPair; pos: Pair; width, height, offset: INTEGER; clrPxl: Pixel _ [Real.Fix[color.R*255], Real.Fix[color.G*255], Real.Fix[color.B*255], 0, 0]; IF context3d.viewer # NIL THEN { width _ context3d.viewer.ww; height _ context3d.viewer.wh; offset _ 28; } ELSE { width _ context3d.pixels.box.max.f - context3d.pixels.box.min.f; height _ context3d.pixels.box.max.s - context3d.pixels.box.min.s; offset _ context3d.pixels.box.min.s }; [[sPos.x, sPos.y]] _ Terminal.GetColorCursorPosition[context3d.terminal]; pos _ [1.0 * sPos.x / width, 1.0 * (height - sPos.y + offset) / height]; IF font = NIL THEN font _ "Xerox/Pressfonts/TimesRoman-MRR"; context3d.class.draw2DRope[context3d, rope, pos, clrPxl, size, font]; }; GetOffScreenCtx: PROC[context: Context, width, height: NAT] ~ { offScreenCtx _ G3dRender.GetTmpContext[context]; offScreenCtx.viewer _ NIL; offScreenCtx.viewPort _ NEW[ -- set viewport directly to define pixelMap size Rectangle _ [ x: 0.0, y: 0.0, w: Real.Float[width], h: Real.Float[height] ] ]; G3dRenderWithPixels.AllocatePixelMemory[offScreenCtx]; -- get display memory G3dRender.SetViewPort[ offScreenCtx, [0.0, 0.0, Real.Float[width], Real.Float[height]] ]; IF context.antiAliasing THEN G3dRenderWithPixels.AntiAliasing[offScreenCtx];-- get state straight IF context.depthBuffering THEN G3dRenderWithPixels.DepthBuffering[offScreenCtx]; [] _ G3dRender.StartLog[offScreenCtx]; offScreenCtx.changed _ TRUE; G3dSortandDisplay.ValidateContext[offScreenCtx]; G3dSortandDisplay.ValidateContext[context]; -- just in case it hasn't been used yet }; GetOnScreenCtx: PROC[context: Context, width, height: NAT] ~ { <> onScreenCtx: Context _ G3dRender.GetTmpContext[context]; G3dRender.SetViewPort[ onScreenCtx, [0.0, 0.0, Real.Float[width], Real.Float[height]] ]; onScreenCtx.class.render _ G3dRenderWithPixels.MakeFrame; -- load direct memory procs onScreenCtx.class.displayPolygon _ G3dRenderWithPixels.PolygonTiler; IF context.antiAliasing THEN G3dRenderWithPixels.AntiAliasing[onScreenCtx]; IF context.depthBuffering THEN G3dRenderWithPixels.DepthBuffering[onScreenCtx]; onScreenCtx.changed _ TRUE; G3dSortandDisplay.ValidateContext[onScreenCtx]; G3dSortandDisplay.ValidateContext[context]; -- just in case it hasn't been used yet }; <> DemoErrorMessages: PROCEDURE [] RETURNS[ error: BOOLEAN _ FALSE ] ~ { NoSurfaces: PROCEDURE [shapes: ShapeSequence] RETURNS[BOOLEAN]~{ FOR i: NAT IN [0..shapes.length) DO IF shapes[i].vertices # NIL AND shapes[i].surfaces # NIL THEN RETURN[FALSE]; ENDLOOP; RETURN[TRUE]; }; IF context3d.shapes = NIL OR NoSurfaces[context3d.shapes] THEN SetScene1[]; IF context3d.shapes = NIL OR NoSurfaces[context3d.shapes] THEN { context3d.class.draw2DRope[context3d, "No objects, nothing to display", [60, 340] ]; error _ TRUE; }; IF context3d.antiAliasing AND NOT List.Memb[ context3d.class.displayType, LIST[$Gray, $FullColor] ] THEN { context3d.class.draw2DRope[context3d, "NoJaggy needs GrayScale or 24-bit Color", [60, 300] ]; error _ TRUE; }; }; LinesDemo: PROCEDURE [makeFrame: BOOLEAN _ FALSE] ~ { IF DemoErrorMessages[] THEN RETURN; FOR i: NAT IN [0..context3d.shapes.length) DO G3dRender.SetRenderStyle[ FindShape[context3d, context3d.shapes[i].name], lines ]; ENDLOOP; context3d.changed _ TRUE; IF makeFrame THEN context3d.class.render[context3d]; lastDemoCalled _ LinesDemo; }; ShadedLinesDemo: PROCEDURE [makeFrame: BOOLEAN _ FALSE] ~ { IF DemoErrorMessages[] THEN RETURN; FOR i: NAT IN [0..context3d.shapes.length) DO G3dRender.SetRenderStyle[ FindShape[context3d, context3d.shapes[i].name], shadedLines ]; ENDLOOP; context3d.changed _ TRUE; IF makeFrame THEN context3d.class.render[context3d]; lastDemoCalled _ ShadedLinesDemo; }; HiddenLinesDemo: PROCEDURE [makeFrame: BOOLEAN _ FALSE] ~ { tmpContext: Context _ G3dRender.GetTmpContext[context3d]; -- get modifiable context IF DemoErrorMessages[] THEN RETURN; G3dRender.NameBackgroundColor[ tmpContext, "White" ]; G3dRender.CopyContextShapes[tmpContext, context3d]; -- insulate shapes from changes FOR i: NAT IN [0..tmpContext.shapes.length) DO G3dRender.SetRenderStyle[ FindShape[tmpContext, tmpContext.shapes[i].name], hiddenLines ]; ENDLOOP; context3d.changed _ TRUE; IF makeFrame THEN tmpContext.class.render[tmpContext]; lastDemoCalled _ HiddenLinesDemo; }; NormaledLinesDemo: PROCEDURE [makeFrame: BOOLEAN _ FALSE] ~ { tmpContext: Context _ G3dRender.GetTmpContext[context3d]; -- get modifiable context IF DemoErrorMessages[] THEN RETURN; G3dRender.NameBackgroundColor[ tmpContext, "White" ]; G3dRender.CopyContextShapes[tmpContext, context3d]; -- insulate shapes from changes FOR i: NAT IN [0..tmpContext.shapes.length) DO G3dRender.SetColor[ FindShape[tmpContext, tmpContext.shapes[i].name], [1.0, 1.0, 1.0] ]; G3dRender.SetRenderStyle[ FindShape[tmpContext, tmpContext.shapes[i].name], hiddenLines ]; ENDLOOP; context3d.changed _ TRUE; IF makeFrame THEN tmpContext.class.render[tmpContext]; lastDemoCalled _ NormaledLinesDemo; }; FacetedDemo: PROCEDURE [makeFrame: BOOLEAN _ FALSE] ~ { IF DemoErrorMessages[] THEN RETURN; FOR i: NAT IN [0..context3d.shapes.length) DO G3dRender.SetRenderStyle[ FindShape[context3d, context3d.shapes[i].name], faceted ]; ENDLOOP; context3d.changed _ TRUE; IF makeFrame THEN context3d.class.render[context3d]; lastDemoCalled _ FacetedDemo; }; SmoothDemo: PROCEDURE [makeFrame: BOOLEAN _ FALSE] ~ { IF DemoErrorMessages[] THEN RETURN; FOR i: NAT IN [0..context3d.shapes.length) DO G3dRender.SetRenderStyle[ FindShape[context3d, context3d.shapes[i].name], smooth ]; ENDLOOP; context3d.changed _ TRUE; lastDemoCalled _ SmoothDemo; IF makeFrame THEN context3d.class.render[context3d]; }; SetShiny: PROCEDURE [] ~ { FOR i: NAT IN [0..context3d.shapes.length) DO G3dRender.SetShininess[ FindShape[context3d, context3d.shapes[i].name], 50.0 ]; ENDLOOP; context3d.changed _ TRUE; }; SetDull: PROCEDURE [] ~ { <> FOR i: NAT IN [0..context3d.shapes.length) DO G3dRender.SetShininess[ FindShape[context3d, context3d.shapes[i].name], 0.0 ]; ENDLOOP; context3d.changed _ TRUE; }; InterpressDemo: PROCEDURE [] ~ { fileName: Rope.ROPE _ ViewerTools.GetSelectionContents[]; IF Rope.Length[fileName] < 1 THEN { SIGNAL G3dRender.Error[$MisMatch, "No selection for file name"]; RETURN; }; IF DemoErrorMessages[] THEN RETURN; IF lastDemoCalled # HiddenLinesDemo AND lastDemoCalled # NormaledLinesDemo THEN G3dRenderWithImager.MakeInterpressPage[context3d, fileName ] ELSE { tmpContext: Context _ G3dRender.GetTmpContext[context3d]; -- get mod. context context3d.changed _ TRUE; G3dRender.NameBackgroundColor[ tmpContext, "White" ]; G3dRender.CopyContextShapes[tmpContext, context3d]; -- insulate shapes from change FOR i: NAT IN [0..context3d.shapes.length) DO G3dRender.SetColor[ FindShape[tmpContext, tmpContext.shapes[i].name], [1.0,1.0,1.0] ]; IF G3dRender.ShapeClassFrom[tmpContext.shapes[i]].type # $Light -- avoid lights THEN IF lastDemoCalled # NormaledLinesDemo THEN G3dRender.SetRenderStyle[ FindShape[tmpContext, tmpContext.shapes[i].name], hiddenLines ] ELSE G3dRender.SetRenderStyle[ FindShape[tmpContext, tmpContext.shapes[i].name], linesWnormals ]; ENDLOOP; G3dRenderWithImager.MakeInterpressPage[tmpContext, fileName ] }; }; RandomQuads: PROCEDURE [context: Context] ~ { x, y: REAL; time: REAL _ BasicTime.PulsesToSeconds[BasicTime.GetClockPulses[]]; width: REAL _ context.viewPort.w; height: REAL _ context.viewPort.h; aspectRatio: REAL _ height / width; rs: Random.RandomStream _ Random.Create[Real.Round[width]]; -- limit to display width p: REF Patch _ NEW[ Patch[4] ]; shape: Shape _ NEW[ShapeRep]; renderData: REF RenderData _ G3dRender.RenderDataFrom[shape]; renderData.shadingClass _ NEW[ShadingClass]; renderData.shadingClass.renderMethod _ $Smooth; p.props _ PutProp[ p.props, $Shape, shape ]; p.nVtces _ 4; FOR i: NAT IN [0..1000) DO IF context.stopMe^ THEN EXIT; x _ Random.NextInt[rs]; y _ Random.NextInt[rs] * aspectRatio; FOR j: NAT IN [0..4) DO xSgn, ySgn: INTEGER; xSgn _ IF j < 1 OR j > 3 THEN -1 ELSE 1; ySgn _ IF j < 2 THEN 1 ELSE -1; p[j].coord.sx _ MAX[0, MIN[ width-1, x + xSgn * Random.NextInt[rs] * 0.1]]; p[j].coord.sy _ MAX[0, MIN[ height-1, y+ySgn * Random.NextInt[rs] *0.1 *aspectRatio]]; p[j].shade.er _ Random.NextInt[rs] / width; p[j].shade.eg _ Random.NextInt[rs] / width; p[j].shade.eb _ Random.NextInt[rs] / width; ENDLOOP; [] _ context.class.displayPolygon[context, p]; ENDLOOP; quadTime _ BasicTime.PulsesToSeconds[BasicTime.GetClockPulses[]] - time; }; <> SetScene1: PROCEDURE [] ~ { IF scene1 = NIL THEN { Reset[]; G3dRender.AddShapeFromFile[ context3d, "CheckerBoard", -- internal name "CheckerBoard.shape", -- file name [-8.0, -8.0, -2.0] -- position ]; G3dRender.SetColor[ FindShape[context3d, "CheckerBoard"], [.8, .4, .2] ]; -- add shading G3dRender.AddShapeFromFile[ context3d, "Icosahedron", "Icosahedron.shape", [2.0, 0.0, 0.0] ]; G3dRender.SetColor[ FindShape[context3d, "Icosahedron"], [1., 1., 1.] ]; G3dRender.AddShapeFromFile[ context3d, "SoccerBall", "SoccerBall.shape", [-2.0, 0.0, 0.0] ]; G3dRender.SetColor[ FindShape[context3d, "SoccerBall"], [1., 1., 1.] ]; G3dRender.AddShapeFromFile[ context3d, "CutCube", "CutCube.shape", [0.0, 3.0, 0.0] ]; G3dRender.SetColor[ FindShape[context3d, "CutCube"], [.9, .8, .5] ]; scene1 _ NEW[ShapeSequenceRep[context3d.shapes.length]]; FOR i: NAT IN [0..context3d.shapes.length) DO scene1[i] _ context3d.shapes[i]; ENDLOOP; scene1.length _ context3d.shapes.length; } ELSE { context3d.shapes _ NEW[ShapeSequenceRep[scene1.length]]; FOR i: NAT IN [0..scene1.length) DO context3d.shapes[i] _ scene1[i]; ENDLOOP; context3d.shapes.length _ scene1.length; }; G3dRenderWithPixels.DepthBuffering[context3d, FALSE]; currentScene _ scene1; }; SetScene2: PROCEDURE [] ~ { IF scene2 = NIL THEN { Reset[]; G3dRender.AddShapeFromFile[context3d, "ChampagneGlass", "ChampagneGlass.shape", [2.0, 0.0, 0.0] ]; G3dRender.SetColor[ FindShape[context3d, "ChampagneGlass"], [1.,0.,1.] ]; G3dRender.SetTransmittance[ FindShape[context3d, "ChampagneGlass"], 0.8 ]; G3dRender.AddShapeFromFile[context3d, "UtahEgg", "UtahEgg.shape" ]; G3dShape.TransformShape[ shape: FindShape[context3d, "UtahEgg"], translate: [-2.,.0,.0], axis: [[0.0, 0.0, 0.0], [1.0, 1.0, 0.0]], rotation: 90.0 ]; G3dRender.SetColor[ FindShape[context3d, "UtahEgg"], [1.0, .8, .5] ]; G3dRender.AddShapeFromFile[context3d, "Banana", "Banana.shape" ]; G3dRender.SetColor[ FindShape[context3d, "Banana"], [1.0, .9, .1] ]; scene2 _ NEW[ShapeSequenceRep[context3d.shapes.length]]; FOR i: NAT IN [0..context3d.shapes.length) DO scene2[i] _ context3d.shapes[i]; ENDLOOP; scene2.length _ context3d.shapes.length; } ELSE { context3d.shapes _ NEW[ShapeSequenceRep[scene2.length]]; FOR i: NAT IN [0..scene2.length) DO context3d.shapes[i] _ scene2[i]; ENDLOOP; context3d.shapes.length _ scene2.length; }; G3dRenderWithPixels.DepthBuffering[context3d, FALSE]; currentScene _ scene2; }; SetScene3: PROCEDURE [] ~ { IF scene3 = NIL THEN { Reset[]; G3dRender.AddShapeFromFile[context3d, "TeaPot", "TeaPotWithBot.shape", [0.0, 0.0, -1.25]]; scene3 _ NEW[ShapeSequenceRep[context3d.shapes.length]]; FOR i: NAT IN [0..context3d.shapes.length) DO scene3[i] _ context3d.shapes[i]; ENDLOOP; scene3.length _ context3d.shapes.length; G3dRender.SetView[context3d, [3.0, -10.0, 3.0], [0.0, 0.0, 0.0] ]; } ELSE { context3d.shapes _ NEW[ShapeSequenceRep[scene3.length]]; FOR i: NAT IN [0..scene3.length) DO context3d.shapes[i] _ scene3[i]; ENDLOOP; context3d.shapes.length _ scene3.length; }; currentScene _ scene3; }; OneShape: PROCEDURE [] ~ { Reset[]; G3dRender.AddShapeFromFile[context3d, "Shape0", ViewerTools.GetSelectionContents[] ]; G3dRender.SetView[context3d, [0.0, -10.0, 3.0], [0.0, 0.0, 0.0] ]; }; GetMouseRectangle: PROCEDURE[x, y: REAL] ~ { IF mouseRectangle # NIL THEN { mouseRectangle.w _ x - mouseRectangle.x; IF mouseRectangle.w < 0.0 THEN { mouseRectangle.x _ mouseRectangle.x + mouseRectangle.w; mouseRectangle.w _ -mouseRectangle.w; }; mouseRectangle.h _ y - mouseRectangle.y; IF mouseRectangle.h < 0.0 THEN { mouseRectangle.y _ mouseRectangle.y + mouseRectangle.h; mouseRectangle.h _ -mouseRectangle.h; }; SELECT mouseWaiting FROM $Window => { mouseRectangle.x _ mouseRectangle.x - context3d.viewPort.x; mouseRectangle.y _ mouseRectangle.y - context3d.viewPort.y; mouseRectangle.w _ MIN[mouseRectangle.w, context3d.viewPort.w]; mouseRectangle.x _ 2.0 * (mouseRectangle.x / context3d.viewPort.w - 0.5); -- center mouseRectangle.y _ 2.0 * (mouseRectangle.y - context3d.viewPort.h/2.0) / context3d.viewPort.w; mouseRectangle.w _ 2.0 * mouseRectangle.w / context3d.viewPort.w; mouseRectangle.h _ mouseRectangle.w * context3d.viewPort.h/context3d.viewPort.w; windowStack _ CONS[ context3d.window^, windowStack ]; G3dRender.SetWindow[ context3d, mouseRectangle^ ]; mouseRectangle _ NIL; mouseWaiting _ NIL; }; $ViewPort => { viewPortStack _ CONS[ context3d.viewPort^, viewPortStack ]; G3dRender.SetViewPort[ context3d, mouseRectangle^ ]; mouseRectangle _ NIL; mouseWaiting _ NIL; }; ENDCASE => SIGNAL G3dRender.Error[$MisMatch, "Unknown Mouse Atom"]; } ELSE mouseRectangle _ NEW[ Rectangle _ [x, y, 0.0, 0.0] ]; }; GetWindow: PROCEDURE[] ~ { mouseWaiting _ $Window }; RestoreWindow: PROCEDURE[] ~ { IF windowStack # NIL THEN { G3dRender.SetWindow[ context3d, windowStack.first ]; windowStack _ windowStack.rest; } ELSE SIGNAL G3dRender.Error[$MisMatch, "No previous window"]; }; GetViewPort: PROCEDURE [] ~ { mouseWaiting _ $ViewPort }; RestoreViewPort: PROCEDURE[] ~ { IF viewPortStack # NIL THEN { G3dRender.SetViewPort[ context3d, viewPortStack.first ]; viewPortStack _ viewPortStack.rest; } ELSE SIGNAL G3dRender.Error[$MisMatch, "No previous viewport"]; }; ShowSinglePatch: PROCEDURE[ shapeNumber, patchNumber: NAT, keep: BOOL _ FALSE ] ~ { context3d.props _ PutProp[ context3d.props, $SinglePatch, NEW[ IntegerPair _ [shapeNumber, patchNumber] ] ]; DoCommands[context3d, $Display]; IF NOT keep THEN context3d.props _ Atom.RemPropFromList[ context3d.props, $SinglePatch ]; }; ShowPatchesOnVtx: PROCEDURE[ shapeNumber, vtxNumber: NAT, keep: BOOL _ FALSE ] ~ { context3d.props _ PutProp[ context3d.props, $SingleVtx, NEW[ IntegerPair _ [shapeNumber, vtxNumber] ] ]; DoCommands[context3d, $Display]; IF NOT keep THEN context3d.props _ Atom.RemPropFromList[ context3d.props, $SingleVtx ]; }; <> sumTable: REF RealSequence _ NIL; discreteTable: BOOLEAN _ FALSE; -- TRUE if table made from discrete samples testPatNumStripes, testPatRatio: REAL; MakeCurves: PROC[numStripes: NAT, ratio: REAL] ~ { testPatNumStripes _ numStripes; testPatRatio _ ratio; IF context3d.viewer # NIL THEN { -- do through viewer context3d.class.drawInViewer[context3d, NEW[ImagerProcRec _ [ViewerMakeCurves, NIL]]]; }; }; ViewerMakeCurves: ImagerProc ~ { DoMakeCurves: PROC[pixelMap: ImagerPixel.PixelMap] ~ { Ceiling: PROC[number: REAL] RETURNS[ result: INTEGER ] ~ { result _ Real.RoundI[number]; IF result < number THEN result _ result + 1; }; DrawFilter: PROC[] ~ { IF sumTable # NIL THEN { -- draw convolution filter and pixel fiducials by: NAT _ Real.RoundC[viewPort.h/12.0]; x: NAT _ Real.RoundC[viewPort.w/2.0 - 128.0]; Imager.SetColor[displayContext, Imager.black]; FOR i: NAT IN [0..4] DO -- draw pixel fiducials Imager.MaskVector[displayContext, [ x, by+10 ], [ x, by-10 ]]; Imager.MaskVector[displayContext, [ x+10, by ], [ x-10, by ]]; x _ x + 64; ENDLOOP; FOR i: NAT IN ( 0..sumTable.length ) DO -- draw convolution filter xx: NAT _ Real.RoundC[viewPort.w/2.0 + viewPort.x] + i - sumTable.length/2; yy: INTEGER _ Real.FixI[ (sumTable[i] - sumTable[i-1]) * 35.0 * viewPort.h / 3.0 ]; IF yy # 0.0 AND i # 192 AND i # 64 THEN { IF discreteTable THEN yy _ Real.FixI[ MIN[ .8 * viewPort.h/4.0, yy/15.0 ]]; yy _ by + yy; Imager.MaskVector[displayContext, [ xx-1, by ], [ xx-1, yy ]]; Imager.MaskVector[displayContext, [ xx, by ], [ xx, yy ]]; Imager.MaskVector[displayContext, [ xx+1, by ], [ xx+1, yy ]]; }; ENDLOOP; }; }; numStripes: REAL _ testPatNumStripes; ratio: REAL _ testPatRatio; viewPort: Imager.Rectangle _ ImagerBackdoor.GetBounds[ imagerCtx ]; factor: REAL _ numStripes / viewPort.w; pos: REF RealSequence _ NEW[ RealSequence[numStripes] ]; inc1: REF RealSequence _ NEW[ RealSequence[numStripes] ]; inc2: REF RealSequence _ NEW[ RealSequence[numStripes] ]; line: REF RealSequence _ NEW[ RealSequence[Real.Round[viewPort.w]+4] ]; scanLIne: ImagerPixel.PixelBuffer _ ImagerPixel.NewPixels[ pixelMap, 1, viewPort.w ]; maxValue: REAL _ 255.0; viewPort.h _ viewPort.h * 3.0 / 4.0; -- use just 3/4 of viewport FOR i: NAT IN [ 0..numStripes ) DO -- draw spacing curve pos[i] _ ( 1.0 - ratio/(i+ratio) ) * viewPort.w * 1.0 / (1.0 - ratio / (numStripes+ratio)); inc1[i] _ Real.Float[(numStripes - i)] / numStripes; inc2[i] _ -2 * inc1[i] / viewPort.h; ENDLOOP; Imager.DoSaveAll[imagerCtx, DrawFilter]; FOR y: NAT IN [ Real.RoundC[viewPort.h/3.0] .. Real.RoundC[viewPort.h*4.0/3.0] ) DO lastX, thisX: REAL _ 0; white: BOOLEAN _ TRUE; IF sumTable # NIL THEN FOR i: NAT IN [0..line.length) DO line[i] _ 0.0; ENDLOOP; FOR i: NAT IN [ 0 .. numStripes ) DO pxlValue: CARDINAL; thisX _ pos[i]; IF white THEN pxlValue _ Real.FixC[maxValue] ELSE pxlValue _ 0; IF sumTable = NIL THEN -- no table, output plain FOR x: NAT IN [ Real.FixC[lastX] .. Real.FixC[thisX] ) DO IF x < Real.RoundC[viewPort.w] THEN scanLine[x] _ pxlValue; ENDLOOP ELSE IF sumTable.length = 128 THEN { -- 2-pixel table tX: REAL _ thisX + 2; lX: REAL _ lastX + 2; IF white THEN { lastIndex: NAT _ Real.FixC[lX * 64.0 - (Real.FixC[lX] * 64)]; thisIndex: NAT _ Real.FixC[tX * 64.0 - (Real.FixC[tX] * 64)]; loopStart: NAT _ Real.FixC[lX]-1; loopEnd: NAT _ Real.FixC[tX]; FOR x: NAT IN [ loopStart .. loopEnd ] DO SELECT x FROM loopStart => { line[x] _ line[x] + 1.0 - sumTable[lastIndex+64]; IF loopStart = loopEnd-1 THEN line[x] _ line[x] - (1.0 - sumTable[thisIndex+64]); }; loopStart+1 => { line[x] _ line[x] + 1.0 - sumTable[lastIndex]; IF loopStart = loopEnd-1 THEN line[x] _ line[x] - (1.0 - sumTable[thisIndex]); IF loopStart = loopEnd-2 THEN line[x] _ line[x] - (1.0 - sumTable[thisIndex+64]); }; loopEnd-1 => { line[x] _ line[x] + sumTable[thisIndex+64]; }; loopEnd => { line[x] _ line[x] + sumTable[thisIndex]; }; ENDCASE => line[x] _ 1.0; ENDLOOP; } } ELSE IF sumTable.length = 256 THEN { -- 4-pixel negative lobe table tX: REAL _ thisX + 2; lX: REAL _ lastX + 2; IF white THEN { lastIndex: NAT _ Real.FixC[lX * 64.0 - (Real.FixC[lX] * 64)]; thisIndex: NAT _ Real.FixC[tX * 64.0 - (Real.FixC[tX] * 64)]; loopStart: NAT _ Real.FixC[lX]-2; loopEnd: NAT _ Real.FixC[tX]+1; FOR x: NAT IN [ loopStart .. loopEnd ] DO SELECT x FROM loopStart => { line[x] _ line[x] + sumTable[255] - sumTable[lastIndex+192]; IF loopStart = loopEnd-3 -- start and end in same pixel span THEN line[x] _ line[x] - (sumTable[255] - sumTable[thisIndex+192]); }; loopStart+1 => { line[x] _ line[x] + sumTable[255] + sumTable[191] - sumTable[lastIndex+128]; IF loopStart = loopEnd-3 -- start and end in same pixel span THEN line[x] _ line[x] - ( sumTable[255] + sumTable[191] - sumTable[thisIndex+128] ); IF loopStart = loopEnd-4 -- start and end in adjacent pixel spans THEN line[x] _ line[x] - ( sumTable[255] - sumTable[thisIndex+192] ); }; loopStart+2 => { line[x] _ line[x] + sumTable[255] + sumTable[191] - sumTable[lastIndex+64]; IF loopStart = loopEnd-3 -- start and end in same pixel span THEN line[x] _ line[x] - ( sumTable[255] + sumTable[191] - sumTable[thisIndex+64] ); IF loopStart = loopEnd-4 -- start and end in adjacent pixel spans THEN line[x] _ line[x] - ( sumTable[255] + sumTable[191] - sumTable[thisIndex+128] ); IF loopStart = loopEnd-5 -- start and end in pixels separated by one span THEN line[x] _ line[x] - ( sumTable[255] - sumTable[thisIndex+192] ); }; loopStart+3 => { line[x] _ line[x] + sumTable[255] + sumTable[191] + sumTable[63] - sumTable[lastIndex]; IF loopStart = loopEnd-3 -- start and end in same pixel span THEN line[x] _ line[x] - ( sumTable[255] + sumTable[191] + sumTable[63] - sumTable[thisIndex] ); IF loopStart = loopEnd-4 -- start and end in adjacent pixel spans THEN line[x] _ line[x] - ( sumTable[255] + sumTable[191] - sumTable[thisIndex+64] ); IF loopStart = loopEnd-5 -- start and end in pixels separated by one span THEN line[x] _ line[x] - ( sumTable[255] + sumTable[191] - sumTable[thisIndex+128] ); IF loopStart = loopEnd-6 -- start and end in pixels separated by two spans THEN line[x] _ line[x] - ( sumTable[255] - sumTable[thisIndex+192] ); }; loopEnd-3 => { line[x] _ line[x] + sumTable[63] + sumTable[191] + sumTable[thisIndex+192]; }; loopEnd-2 => { line[x] _ line[x] + sumTable[63] + sumTable[thisIndex+128]; }; loopEnd-1 => { line[x] _ line[x] + sumTable[63] + sumTable[thisIndex+64]; }; loopEnd => { line[x] _ line[x] + sumTable[thisIndex]; }; ENDCASE => line[x] _ 1.0; ENDLOOP; } }; white _ NOT white; pos[i] _ pos[i] + inc1[i]; inc1[i] _ inc1[i] + inc2[i]; lastX _ thisX; ENDLOOP; IF sumTable # NIL THEN FOR i: NAT IN [2..Real.RoundC[viewPort.w]+2) DO pixelValue: INTEGER _ MAX[ 0, Real.FixI[ MIN[maxValue, line[i]*(maxValue)] ] ]; scanLine[i-2] _ pixelValue; ENDLOOP; ImagerPixel.PutPixels[ self: pixelMap, pixels: scanLine, initIndex: [f: xStart, s: y], count: viewPort.w ]; ENDLOOP; }; ImagerBackdoor.AccessBufferRectangle[imagerCtx, DoMakeCurves, context.viewPort^]; }; MakeNilTable: PROC[] ~ { sumTable _ NIL; }; MakeImpulseTable: PROC[] ~ { sumTable _ NEW[ RealSequence[128] ]; FOR i: NAT IN [0 .. 64) DO sumTable[i] _ 0.0; ENDLOOP; FOR i: NAT IN [64 .. 128) DO sumTable[i] _ 1.0; ENDLOOP; discreteTable _ TRUE; }; Make2ImpulseTable: PROC[] ~ { sumTable _ NEW[ RealSequence[128] ]; FOR i: NAT IN [0 .. 48) DO sumTable[i] _ 0.0; ENDLOOP; FOR i: NAT IN [48 .. 80) DO sumTable[i] _ 0.5; ENDLOOP; FOR i: NAT IN [80 .. 128) DO sumTable[i] _ 1.0; ENDLOOP; discreteTable _ TRUE; }; Make4ImpulseTable: PROC[] ~ { sumTable _ NEW[ RealSequence[128] ]; FOR i: NAT IN [0 .. 40) DO sumTable[i] _ 0.0; ENDLOOP; FOR i: NAT IN [40 .. 56) DO sumTable[i] _ 0.25; ENDLOOP; FOR i: NAT IN [56 .. 72) DO sumTable[i] _ 0.50; ENDLOOP; FOR i: NAT IN [72 .. 88) DO sumTable[i] _ 0.75; ENDLOOP; FOR i: NAT IN [88 .. 128) DO sumTable[i] _ 1.0; ENDLOOP; discreteTable _ TRUE; }; Make8ImpulseTable: PROC[] ~ { sumTable _ NEW[ RealSequence[128] ]; FOR i: NAT IN [0 .. 36) DO sumTable[i] _ 0.000; ENDLOOP; FOR i: NAT IN [36 .. 44) DO sumTable[i] _ 0.125; ENDLOOP; FOR i: NAT IN [44 .. 52) DO sumTable[i] _ 0.250; ENDLOOP; FOR i: NAT IN [52 .. 60) DO sumTable[i] _ 0.375; ENDLOOP; FOR i: NAT IN [60 .. 68) DO sumTable[i] _ 0.500; ENDLOOP; FOR i: NAT IN [68 .. 76) DO sumTable[i] _ 0.625; ENDLOOP; FOR i: NAT IN [76 .. 84) DO sumTable[i] _ 0.750; ENDLOOP; FOR i: NAT IN [84 .. 92) DO sumTable[i] _ 0.875; ENDLOOP; FOR i: NAT IN [92 .. 128) DO sumTable[i] _ 1.000; ENDLOOP; discreteTable _ TRUE; }; MakeWtd8ImpulseTable: PROC[] ~ { sumTable _ NEW[ RealSequence[128] ]; FOR i: NAT IN [0 .. 8) DO sumTable[i] _ 0.0/32.0; ENDLOOP; FOR i: NAT IN [8 .. 24) DO sumTable[i] _ 1.0/32.0; ENDLOOP; FOR i: NAT IN [24 .. 40) DO sumTable[i] _ 4.0/32.0; ENDLOOP; FOR i: NAT IN [40 .. 56) DO sumTable[i] _ 9.0/32.0; ENDLOOP; FOR i: NAT IN [56 .. 72) DO sumTable[i] _ 16.0/32.0; ENDLOOP; FOR i: NAT IN [72 .. 88) DO sumTable[i] _ 23.0/32.0; ENDLOOP; FOR i: NAT IN [88 .. 104) DO sumTable[i] _ 28.0/32.0; ENDLOOP; FOR i: NAT IN [104 .. 120) DO sumTable[i] _ 31.0/32.0; ENDLOOP; FOR i: NAT IN [120 .. 128) DO sumTable[i] _ 32.0/32.0; ENDLOOP; discreteTable _ TRUE; }; MakeWtd16ImpulseTable: PROC[] ~ { sum: REAL _ 0; lastPos: NAT _ 0; thisPos: NAT _ 4; sumTable _ NEW[ RealSequence[128] ]; FOR i: NAT IN [0..16) DO j: NAT _ 8 - ABS[8 - i]; IF i > 7 THEN j _ j -1; FOR k: NAT IN [lastPos .. thisPos) DO sumTable[k] _ sum; ENDLOOP; sum _ sum + (j*2 + 1)/128.0; lastPos _ thisPos; thisPos _ thisPos + 8; ENDLOOP; FOR k: NAT IN [lastPos .. 128) DO sumTable[k] _ 1.0; ENDLOOP; discreteTable _ TRUE; }; MakeBoxTable: PROC[] ~ { sumTable _ NEW[ RealSequence[128] ]; FOR i: NAT IN [0 .. 32) DO sumTable[i] _ 0.0; ENDLOOP; FOR i: NAT IN [32 .. 96) DO sumTable[i] _ (i-32) / 64.0; ENDLOOP; FOR i: NAT IN [96 .. 128) DO sumTable[i] _ 1.0; ENDLOOP; discreteTable _ FALSE; }; MakeTriangleTable: PROC[] ~ { <> sumTable _ NEW[ RealSequence[128] ]; FOR i: NAT IN [0..64) DO t: REAL _ i * 1.0 / 64.0; sumTable[i] _ Sqr[t] / 2.; sumTable[i + 64] _ 1. - Sqr[1. - t] / 2.; ENDLOOP; discreteTable _ FALSE; }; MakeGaussTable: PROC[spread: REAL] ~ { <> sumTable _ NEW[ RealSequence[128] ]; FOR i: NAT IN [0..64) DO t: REAL _ (i * 1.0 / 64.0); sumTable[64 + i] _ RealFns.Exp[-spread*t*t]; sumTable[63 - i] _ sumTable[64 + i]; ENDLOOP; FOR i: NAT IN (0..128) DO sumTable[i] _ sumTable[i-1] + sumTable[i]; ENDLOOP; FOR i: NAT IN [0..128) DO sumTable[i] _ sumTable[i] / sumTable[127]; ENDLOOP; discreteTable _ FALSE; }; MakeSinc2Table: PROC[] ~ { <> sumTable _ NEW[ RealSequence[128] ]; FOR i: NAT IN [0..64) DO t: REAL _ (1.0 - i * 1.0 / 64.0) * 3.1416; sumTable[i] _ RealFns.Sin[t] / t; sumTable[127 - i] _ sumTable[i]; ENDLOOP; FOR i: NAT IN (0..128) DO sumTable[i] _ sumTable[i-1] + sumTable[i]; ENDLOOP; FOR i: NAT IN [0..128) DO sumTable[i] _ sumTable[i] / sumTable[127]; ENDLOOP; discreteTable _ FALSE; }; MakeSinc4Table: PROC[weighted, sincWeighting: BOOLEAN _ TRUE] ~ { <> completeSum: REAL; sumTable _ NEW[ RealSequence[256] ]; FOR i: NAT IN [0..128) DO t: REAL _ (2.0 - i * 1.0 / 64.0) * 3.1416; sumTable[i] _ RealFns.Sin[t] / t; IF weighted THEN IF sincWeighting THEN sumTable[i] _ (RealFns.Sin[t/2.0] / (t/2.0)) * sumTable[i] ELSE sumTable[i] _ (i * 1.0 / 128.0) * sumTable[i]; -- triangle weight sumTable[255 - i] _ sumTable[i]; ENDLOOP; FOR i: NAT IN (0..64) DO sumTable[i] _ sumTable[i-1] + sumTable[i]; sumTable[i+192] _ sumTable[i+192-1] + sumTable[i+192]; ENDLOOP; FOR i: NAT IN (0..128) DO sumTable[i+64] _ sumTable[i+64-1] + sumTable[i+64]; ENDLOOP; completeSum _ sumTable[63] + sumTable[191] + sumTable[255]; FOR i: NAT IN [0..256) DO sumTable[i] _ sumTable[i] / completeSum; ENDLOOP; sumTable[0] _ sumTable[0]; discreteTable _ FALSE; }; <> Orbit: PROCEDURE [] ~ { IF DemoErrorMessages[] THEN RETURN; animation _ TRUE; G3dAnimationSupport.Orbit[ context: context3d, lookingFrom: context3d.eyePoint, lookingAt: context3d.lookAt, axis: [0.3, 0.0, 1.0], base: context3d.lookAt, framesPerRev: 53 ! UNWIND => animation _ FALSE ]; animation _ FALSE; }; MakeFrame: PROC ~ { context3d.class.render[context3d ]; -- clear and make new frame }; ShowPixels: PROC ~ { context3d.class.drawInViewer[ context3d, NEW[ImagerProcRec _ [G3dColorDisplaySupport.StuffBuf, NIL]] ]; }; ShowShapes: PROC ~ { G3dSortandDisplay.ShowShapes[context3d ]; -- show shapes without clearing }; movieFileRoot: Rope.ROPE; movieFileLog: Rope.ROPE; movieFileLogTime: BasicTime.GMT; movieNumFiles: NAT; movieStart: NAT; movieLabeledFrames: BOOLEAN; SetUpMovie: PROC[fileRoot: Rope.ROPE, numFiles, start: NAT _ 0, labels: BOOLEAN _ FALSE] ~ { fileUpdated: BOOLEAN _ FALSE; IF frames # NIL AND Rope.Equal[movieFileRoot, fileRoot] THEN { latestTime: BasicTime.GMT; [created: latestTime] _ FS.FileInfo[ G3dRender.GetLogFileName[fileRoot] ]; IF BasicTime.Period[from: movieFileLogTime, to: latestTime] > 0 THEN fileUpdated _ TRUE; } ELSE frames _ NIL; IF frames = NIL OR fileUpdated THEN { movieFileRoot _ fileRoot; [fullFName: movieFileLog, created: movieFileLogTime] _ FS.FileInfo[ G3dRender.GetLogFileName[fileRoot] ]; movieNumFiles _ numFiles; movieStart _ start; movieLabeledFrames _ labels; frames _ NIL; }; }; frameRate: INTEGER _ 6; -- playback rate in frames/second, negative plays backwards PlayBackbyFrame: CedarProcess.ForkableProc ~ { CleanUp: PROC ~ { G3dRender.SetViewPort[ context3d, cachedViewPort ]; IF context3d.class.displayType = $PseudoColor THEN G3dColorDisplaySupport.LoadStd8BitClrMap[context3d.terminal]; }; size, posn: Pair; G3dSortandDisplay.ValidateContext[context3d]; cachedViewPort _ context3d.viewPort^; context3d.class.loadBackground[context3d]; IF frames = NIL THEN { frames _ G3dAnimationSupport.CacheNumberedAISFiles[ context3d, movieFileRoot, movieNumFiles, movieStart, movieLabeledFrames ]; }; <> IF context3d.stopMe^ THEN { CleanUp[]; RETURN[]; }; size _ [frames[0].box.max.f - frames[0].box.min.f, frames[0].box.max.s - frames[0].box.min.s]; posn _ IF context3d.viewer # NIL THEN [ context3d.viewer.cx + (context3d.viewer.cw/2 - size.x/2), context3d.viewer.cy + (context3d.viewer.ch/2 - size.y/2) ] ELSE [ context3d.pixels.box.max.f/2 - size.x/2, context3d.pixels.box.max.s/2 - size.y/2 ]; G3dRender.SetViewPort[ context3d, [ posn.x, posn.y, size.x, size.y ] ]; IF context3d.viewer # NIL THEN ThreeDViewer.ViewerUpdate[context3d]; -- install viewport context3d.class.draw2DRope[context3d, "Control frame rate using left button", [140, 50] ]; WHILE TRUE DO ENABLE UNWIND => CleanUp[]; IF context3d.stopMe^ THEN { CleanUp[]; RETURN[]; }; G3dAnimationSupport.ShowNextAISCacheFrame[context3d, frames, frameRate]; CedarProcess.CheckAbort[]; ENDLOOP; }; Commander.Register["ThreeDDemo", ThreeDDemoCommand, "\nDemonstrate ThreeDWorld"]; END.