<> <> DIRECTORY Atom USING [ GetPropFromList, PutPropOnList, RemPropFromList ], List USING [ Memb ], CedarProcess USING [ ForkableProc, Process, Fork, Join, Abort, CheckAbort ], Terminal USING [ Virtual, Current ], Commander USING [ PrependWorkingDir ], Rope USING [ ROPE, Substr, Length ], Real USING [ FixI, Float ], Imager USING [ Context, Rectangle ], ImagerColor USING [ RGB ], ImagerColorMap USING [SetStandardColorMap], QuickViewer USING [ BuildViewer, Reset, QuickView ], ViewerOps USING [ ChangeColumn ], ViewerClasses USING [ Viewer ], Vector3d USING [ Triple ], Pixels USING [ PixelBuffer ], ThreeDScenes USING [ Context, Create, FindShape, SetLight, SetView, FillInBackGround, SetViewPort, ShapeInstance, ShapeSequence, GetFromImagerContext, GetShading, PutShading, SetWindow, WindowFromViewPort ], ThreeDSurfaces USING [ EnableDisplay, StopDisplay ], ThreeDMisc USING [ AddShapeAt, CloseLog, CopyContextData, GetImagerContext, GetPolygonColors, LoadColorRamp, LoadStd8BitClrMap, MakeFrame, OrbitEye, PutPixel, SetBackground, SetFacetedColor, SetNamedColor, SetShininess, SetSmoothColor, SetTransmittance, SetViewPortFromImager, ShowRope, ShowShapes, StartLog ], AISAnimation USING [ FrameSequence, ShowNextAISCacheFrame, CacheAISFiles, CacheNumberedAISFiles, StopDisplay ]; ThreeDDemoImpl: CEDAR MONITOR IMPORTS Atom, List, AISAnimation, CedarProcess, ImagerColorMap, QuickViewer, Real, Terminal, ThreeDMisc, ThreeDSurfaces, ThreeDScenes, Commander, Rope, ViewerOps ~ BEGIN <> ThreeDDemoError: PUBLIC SIGNAL [reason: ATOM] = CODE; Triple: TYPE ~ Vector3d.Triple; RGB: TYPE ~ ImagerColor.RGB; <> context3d, offScreenCtx, onScreenCtx: REF ThreeDScenes.Context; currentScene, scene1, scene2, scene3: REF ThreeDScenes.ShapeSequence _ NIL; frames: REF AISAnimation.FrameSequence; xNow, yNow, zNow: REAL _ 3.0; xOrigin, yOrigin: REAL _ 100.0; movie, gallery, noReDraw, buttonsEnabled: BOOLEAN _ FALSE; cachedViewPort: Imager.Rectangle; currentProcess: CedarProcess.Process _ NIL; <> Init: PROC[] ~ { viewer: ViewerClasses.Viewer _ NIL; imagerCtx: Imager.Context; wDir: Rope.ROPE _ Commander.PrependWorkingDir[" "]; -- working dir plus (needed) space wDir _ Rope.Substr[ base: wDir, len: Rope.Length[wDir] - 1 ]; -- drop space buttonsEnabled _ FALSE; imagerCtx _ QuickViewer.BuildViewer[ LIST[$Help, $NewScene, $Lines, $Facets, $Smooth, $Shiny, $Orbit, $STOP, $Movie, $Gallery, $Jaggy, $NoJaggy, $Reset], ReDraw, ShutDown, MenuHit, "ThreeDDemo", TRUE -- shut off scrolling and extra buttons ]; viewer _ NARROW[imagerCtx.data, QuickViewer.QuickView].viewer.parent; IF viewer.column # color THEN ViewerOps.ChangeColumn[viewer, color]; noReDraw _ TRUE; -- stop recursion through ReDraw context3d _ ThreeDScenes.GetFromImagerContext[ imagerCtx ]; context3d.props _ Atom.PutPropOnList[context3d.props, $WDir, wDir]; -- keep directory ThreeDMisc.SetBackground[ context3d, "Darkish Blue" ]; -- set background color [] _ ThreeDScenes.SetLight[context3d, "Initial", [-100., -200., 50.] ]; SetScene1[]; ThreeDScenes.SetView[ context3d, [2.0, -10.0, 3.0], [0.0, 0.0, 0.0] ]; noReDraw _ FALSE; buttonsEnabled _ TRUE; }; <> Reset: PROCEDURE [] ~ { imagerCtx: Imager.Context _ ThreeDMisc.GetImagerContext[context3d]; buttonsEnabled _ FALSE; QuickViewer.Reset[ imagerCtx ]; ThreeDSurfaces.EnableDisplay[]; -- get stop flag unstuck, if necessary ThreeDMisc.SetViewPortFromImager[ context3d, imagerCtx ]; 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] ]; movie _ FALSE; buttonsEnabled _ TRUE; currentScene _ NIL; }; <> ReDraw: PROCEDURE [imagerCtx: Imager.Context] ~ { newContext: REF ThreeDScenes.Context; oldCtx: Imager.Context; IF noReDraw THEN RETURN; -- Don't do anything during Init sequence buttonsEnabled _ FALSE; noReDraw _ TRUE; -- stop recursion from viewers oldCtx _ ThreeDMisc.GetImagerContext[context3d]; IF oldCtx # NIL THEN imagerCtx _ oldCtx; -- use original context newContext _ ThreeDScenes.GetFromImagerContext[ imagerCtx, 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 ]; noReDraw _ FALSE; buttonsEnabled _ TRUE; }; <> ShutDown: PROCEDURE [] ~ { buf: Pixels.PixelBuffer; -- zeroed buffer context3d.display _ buf; IF offScreenCtx # NIL THEN offScreenCtx.display _ buf; buttonsEnabled _ FALSE; frames _ NIL; -- free frame storage for garbage colection pictures _ NIL; -- free image storage for garbage collection ThreeDMisc.CloseLog[context3d]; }; GetOffScreenCtx: PUBLIC PROC[context: REF ThreeDScenes.Context, width, height: NAT] ~ { offScreenCtx _ ThreeDScenes.Create[ width, height, context.renderMode, context.alphaBuffer ]; ThreeDMisc.CopyContextData[dstCtx: offScreenCtx, srcCtx: context]; offScreenCtx.viewPort _ [ x: 0.0, y: 0.0, w: Real.Float[width], h: Real.Float[height] ]; [] _ ThreeDMisc.StartLog[offScreenCtx]; FOR i: NAT IN [0..offScreenCtx.shapes.length) DO offScreenCtx.shapes[i].vtcesInValid _ TRUE; ENDLOOP; }; GetOnScreenCtx: PUBLIC PROC[context: REF ThreeDScenes.Context, width, height: NAT] ~ { onScreenCtx _ ThreeDScenes.GetFromImagerContext[ ThreeDMisc.GetImagerContext[context], context.depthBuffer, context.alphaBuffer, context.renderMode = $Grey ]; ThreeDMisc.CopyContextData[dstCtx: onScreenCtx, srcCtx: context]; onScreenCtx.viewPort _ [ x: 0.0, y: 0.0, w: Real.Float[width], h: Real.Float[height] ]; FOR i: NAT IN [0..onScreenCtx.shapes.length) DO onScreenCtx.shapes[i].vtcesInValid _ TRUE; ENDLOOP; }; <> <> MenuHit: ENTRY PROCEDURE[bttn: ATOM, x, y: REAL, ctrl, shift: BOOL] ~ { DoIt: CedarProcess.ForkableProc ~ { [] _ NARROW[ data, REF PROC]^[]; }; -- call the procedure ForkAndWait: PROC [ proc: PROC ] ~ { IF currentProcess # NIL AND currentProcess.status = busy OR gallery THEN RETURN; <> currentProcess _ CedarProcess.Fork[DoIt, NEW[ PROC _ proc] ]; [] _ CedarProcess.Join[currentProcess]; -- await termination currentProcess _ NIL; }; ForkAndGo: PROC [ proc: PROC ] ~ { IF currentProcess # NIL AND currentProcess.status = busy OR gallery THEN RETURN; <> currentProcess _ CedarProcess.Fork[DoIt, NEW[ PROC _ proc] ]; }; StopEverything: PROC ~ { ThreeDSurfaces.StopDisplay[]; AISAnimation.StopDisplay[]; IF currentProcess # NIL THEN CedarProcess.Abort[currentProcess]; -- kill it [] _ CedarProcess.Join[currentProcess]; -- await termination currentProcess _ NIL; IF gallery THEN ClearGallery[]; IF movie THEN { movie _ FALSE; SetViewPort[ cachedViewPort ]; -- restore viewport }; }; IF buttonsEnabled THEN SELECT bttn FROM $Help => ForkAndGo[ HelpMessage ]; $NewScene => IF currentScene = scene1 THEN ForkAndGo[ SetScene2 ] ELSE IF currentScene = scene2 THEN ForkAndGo[ SetScene3 ] ELSE ForkAndGo[ SetScene1 ]; $Lines => ForkAndGo[ LinesDemo ]; $Facets => ForkAndGo[ FacetedDemo ]; $Smooth => ForkAndGo[ SmoothDemo ]; $Shiny => ForkAndGo[ ShinyDemo ]; $Orbit => ForkAndGo[ Orbit ]; $STOP => StopEverything[]; $Movie => ForkAndGo[ PlayBackbyFrame ]; $Gallery => ForkAndGo[ LoadGallery ]; $Jaggy => ForkAndGo[ SetAliased ]; $NoJaggy => ForkAndGo[ SetAntiAliased ]; $Reset => { StopEverything[]; Reset[]; }; $LeftButton, $LeftHeld => IF movie THEN frameRate _ Real.FixI[x / 10.] ELSE IF gallery THEN ShowNextPicture[] ELSE IF currentProcess = NIL OR currentProcess.status # busy THEN { xNow _ x / 15.0; yNow _ y / 15.0; ThreeDScenes.SetView[ context3d, [xNow, yNow, zNow], context3d.ptOfInterest ]; ForkAndGo[MakeFrame]; }; $MiddleButton, $MiddleHeld => IF currentProcess = NIL OR currentProcess.status # busy THEN { xLight: REAL _ x * 1.0; yLight: REAL _ y * 1.0; [] _ ThreeDScenes.SetLight[ context3d, "Initial", [xLight, yLight, 50.0] ]; IF NOT context3d.lineDrawing THEN ForkAndGo[MakeFrame]; }; $RightButton, $RightHeld => IF gallery THEN ShowLastPicture[] ELSE IF currentProcess = NIL OR currentProcess.status # busy THEN { zNow _ y / 15.0; ThreeDScenes.SetView[ context3d, [xNow, yNow, zNow], context3d.ptOfInterest ]; ForkAndGo[MakeFrame]; }; ENDCASE; }; HelpMessage: PROCEDURE [] ~ { ThreeDMisc.SetNamedColor[context3d, "Vivid Green" ]; ThreeDMisc.ShowRope[context3d, 60.0, 360.0, "Scene1 - Select Scene with Polyhedra on Checkerboard." ]; ThreeDMisc.ShowRope[context3d, 60.0, 330.0, "Scene2 - Select Scene with Egg, banana, and Glass." ]; ThreeDMisc.ShowRope[context3d, 60.0, 300.0, "Lines, Facets, Smooth, Shiny - Make image as specified." ]; ThreeDMisc.ShowRope[context3d, 60.0, 270.0, "Orbit - Make images following elliptical path around scene." ]; ThreeDMisc.ShowRope[context3d, 60.0, 240.0, "Movie - Play back a precalculated sequence."]; ThreeDMisc.ShowRope[context3d, 60.0, 210.0, "Jaggy/NoJaggy - turn antialiasing off/on (NoJaggy is slow!)." ]; ThreeDMisc.ShowRope[context3d, 60.0, 180.0, "Buttoning in the image makes a new image with:" ]; ThreeDMisc.ShowRope[context3d, 60.0, 150.0, " Left Button determining eyepoint position in x-y plane," ]; ThreeDMisc.ShowRope[context3d, 60.0, 120.0, " Right Button determining eyepoint height," ]; ThreeDMisc.ShowRope[context3d, 60.0, 90.0, " Middle Button determining light source x-y." ]; ThreeDMisc.ShowRope[context3d, 60.0, 60.0, "STOP - stops long operations, Reset - recovers from trouble."]; }; SetViewPort: PROC [ size: Imager.Rectangle ] ~ { ThreeDScenes.SetViewPort[ context3d, size ]; -- set clippers etc. < IF reason = $NullClipper THEN RESUME>> 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 ]; }; ChangeRenderMode: PROC [ mode: ATOM ] ~ { -- for {$Dithered, $PseudoClr, $Grey} SELECT mode FROM $Dithered => ImagerColorMap.SetStandardColorMap[ Terminal.Current[] ]; $PseudoClr => ThreeDMisc.LoadStd8BitClrMap[ Terminal.Current[] ]; $Grey => ThreeDMisc.LoadColorRamp[ Terminal.Current[], [0.,0.,0.], [1.,1.,1.], [.43, .43, .43] ]; ENDCASE => SIGNAL ThreeDDemoError[$CantHackThatMode]; context3d.renderMode _ mode; }; <> SetDepthBuffer: PROCEDURE [] ~ { context: REF ThreeDScenes.Context; IF context3d.depthBuffer = TRUE THEN RETURN[]; context _ ThreeDScenes.GetFromImagerContext[ NARROW[Atom.GetPropFromList[ context3d.display.props, $ImagerContext], Imager.Context], FALSE, TRUE ]; context3d.display _ context.display; context3d.alphaBuffer _ FALSE; context3d.depthBuffer _ TRUE; context3d.renderMode _ context.renderMode; SetViewPort[context.viewPort]; }; NoDepthBuffer: PROCEDURE [] ~ { context: REF ThreeDScenes.Context; IF context3d.depthBuffer = FALSE THEN RETURN[]; context _ ThreeDScenes.GetFromImagerContext[ NARROW[Atom.GetPropFromList[ context3d.display.props, $ImagerContext], Imager.Context], context3d.alphaBuffer ]; context3d.display _ context.display; context3d.depthBuffer _ FALSE; context3d.renderMode _ context.renderMode; SetViewPort[context.viewPort]; }; SetAliased: PROCEDURE [] ~ { context: REF ThreeDScenes.Context _ ThreeDScenes.GetFromImagerContext[ NARROW[Atom.GetPropFromList[ context3d.display.props, $ImagerContext], Imager.Context], FALSE, context3d.depthBuffer ]; context3d.display _ context.display; context3d.alphaBuffer _ FALSE; context3d.renderMode _ context.renderMode; SetViewPort[context.viewPort]; }; SetAntiAliased: PROCEDURE [] ~ { context: REF ThreeDScenes.Context _ ThreeDScenes.GetFromImagerContext[ NARROW[Atom.GetPropFromList[ context3d.display.props, $ImagerContext], Imager.Context], TRUE ]; context3d.display _ context.display; context3d.alphaBuffer _ TRUE; context3d.depthBuffer _ FALSE; context3d.renderMode _ context.renderMode; SetViewPort[context.viewPort]; }; DemoErrorMessages: PROCEDURE [] RETURNS[ error: BOOLEAN _ FALSE] ~ { NoSurfaces: PROCEDURE [shapes: REF ThreeDScenes.ShapeSequence] RETURNS[BOOLEAN]~{ FOR i: NAT IN [0..shapes.length) DO IF shapes[i].surface # NIL THEN RETURN[FALSE]; ENDLOOP; RETURN[TRUE]; }; IF context3d.shapes = NIL OR NoSurfaces[context3d.shapes] THEN { ThreeDMisc.SetNamedColor[context3d, "Vivid Green"]; ThreeDMisc.ShowRope[context3d, 60.0, 340.0, "No objects, nothing to display"]; error _ TRUE; }; IF context3d.alphaBuffer AND NOT List.Memb[ context3d.renderMode, LIST[$Grey, $FullClr, $Dorado24] ] THEN { ThreeDMisc.SetNamedColor[context3d, "Vivid Green"]; ThreeDMisc.ShowRope[context3d, 60.0, 300.0, "NoJaggy needs GreyScale or 24-bit Color"]; error _ TRUE; }; }; LinesDemo: PROCEDURE [] ~ { context3d.lineDrawing _ TRUE; IF DemoErrorMessages[] THEN RETURN; IF NOT context3d.alphaBuffer THEN MakeFrame[] ELSE { FOR i: NAT IN [0..context3d.shapes.length) DO IF context3d.shapes[i].surface # NIL THEN ThreeDScenes.PutShading[context3d.shapes[i], $Type, $Lines ]; ENDLOOP; MakeFrame[]; }; }; FacetedDemo: PROCEDURE [] ~ { context3d.lineDrawing _ FALSE; IF DemoErrorMessages[] THEN RETURN; FOR i: NAT IN [0..context3d.shapes.length) DO IF context3d.shapes[i].surface # NIL THEN { context3d.shapes[i].shadingProps _ Atom.RemPropFromList[ -- no highlights context3d.shapes[i].shadingProps, $Shininess ]; ThreeDScenes.PutShading[context3d.shapes[i], $Type, $Faceted ]; IF ThreeDScenes.GetShading[context3d.shapes[i], $PatchColors ] = NIL THEN { rgb: RGB _ NARROW[ThreeDScenes.GetShading[context3d.shapes[i], $Color], REF RGB ]^; ThreeDMisc.SetFacetedColor[context3d, context3d.shapes[i].name, rgb]; }; }; ENDLOOP; MakeFrame[]; }; SmoothDemo: PROCEDURE [] ~ { context3d.lineDrawing _ FALSE; IF DemoErrorMessages[] THEN RETURN; FOR i: NAT IN [0..context3d.shapes.length) DO IF context3d.shapes[i].surface # NIL THEN { context3d.shapes[i].shadingProps _ Atom.RemPropFromList[ -- no highlights context3d.shapes[i].shadingProps, $Shininess ]; ThreeDScenes.PutShading[context3d.shapes[i], $Type, $Smooth ]; }; ENDLOOP; MakeFrame[]; }; ShinyDemo: PROCEDURE [] ~ { context3d.lineDrawing _ FALSE; IF DemoErrorMessages[] THEN RETURN; FOR i: NAT IN [0..context3d.shapes.length) DO IF context3d.shapes[i].surface # NIL THEN { shininess: REF REAL _ NARROW[ ThreeDScenes.GetShading[context3d.shapes[i], $Shininess] ]; IF shininess = NIL THEN { shininess _ NEW[REAL _ 50.0]; ThreeDMisc.SetShininess[ context3d, context3d.shapes[i].name, shininess^ ]; }; IF NARROW[ ThreeDScenes.GetShading[context3d.shapes[i], $Type], ATOM ] = $Lines THEN ThreeDScenes.PutShading[context3d.shapes[i], $Type, $Smooth ]; }; ENDLOOP; MakeFrame[]; }; Orbit: PROCEDURE [] ~ { IF DemoErrorMessages[] THEN RETURN; ThreeDSurfaces.EnableDisplay[]; -- get stop flag unstuck, if necessary ThreeDMisc.OrbitEye[ context: context3d, lookingFrom: context3d.eyePoint, lookingAt: context3d.ptOfInterest, axis: [0.3, 0.0, 1.0], framesPerRev: 53 ]; }; SetScene1: PROCEDURE [] ~ { IF scene1 = NIL THEN { context3d.shapes _ context3d.lights; -- don't change the lighting ThreeDMisc.AddShapeAt[ context3d, "CheckerBoard", -- internal name "CheckerBoard.shape", -- file name [-8.0, -8.0, -2.0], -- position $ConvexPolygon, TRUE -- not a closed shape (TRUE allows backfacing polys) ]; ThreeDMisc.AddShapeAt[ context3d, "Icosahedron", "Icosahedron.shape", [2.0, 0.0, 0.0] ]; ThreeDMisc.AddShapeAt[ context3d, "SoccerBall", "SoccerBall.shape", [-2.0, 0.0, 0.0] ]; ThreeDMisc.AddShapeAt[ context3d, "CutCube", "CutCube.shape", [0.0, 3.0, 0.0] ]; ThreeDMisc.SetFacetedColor[ context3d, "CheckerBoard", [.8, .4, .2] ]; -- add shading ThreeDMisc.SetSmoothColor[ context3d, "CheckerBoard", [.8, .4, .2] ]; ThreeDMisc.SetFacetedColor[ context3d, "SoccerBall", [.7, .7, .6] ]; ThreeDMisc.SetSmoothColor[ context3d, "SoccerBall", [1.0, .8, .8] ]; ThreeDMisc.SetFacetedColor[ context3d, "Icosahedron", [.1, .9, .1] ]; ThreeDMisc.SetSmoothColor[ context3d, "Icosahedron", [.8, 1.0, .8] ]; ThreeDMisc.SetFacetedColor[ context3d, "CutCube", [.9, .3, .1] ]; ThreeDMisc.SetSmoothColor[ context3d, "CutCube", [.9, .3, .1] ]; ThreeDMisc.GetPolygonColors[ context3d, "Icosahedron", "IcosahedronPolyColors.vtces" ]; ThreeDMisc.GetPolygonColors[ context3d, "SoccerBall", "SoccerBallPolyColors.vtces" ]; scene1 _ NEW[ThreeDScenes.ShapeSequence[context3d.shapes.length] _ context3d.shapes^]; } ELSE context3d.shapes _ scene1; NoDepthBuffer[]; currentScene _ scene1; }; SetScene2: PROCEDURE [] ~ { IF scene2 = NIL THEN { context3d.shapes _ context3d.lights; -- don't change the lighting; ThreeDMisc.AddShapeAt[context3d, "ChampagneGlass", "ChampagneGlass.shape", [2.0, 0.0, 0.0], $ConvexPolygon, TRUE ]; -- TRUE allows the inside to be seen ThreeDMisc.AddShapeAt[context3d, "UtahEgg", "UtahEgg.shape", [-2.0, .0, .0] ]; ThreeDMisc.AddShapeAt[context3d, "Banana", "Banana.shape", [0.0, .0, .0] ]; ThreeDScenes.FindShape[ context3d.shapes, "UtahEgg" ].orientation _ [-1., 1., 0.]; ThreeDScenes.FindShape[ context3d.shapes, "UtahEgg" ].rotation _ 90.0; ThreeDScenes.FindShape[ context3d.shapes, "ChampagneGlass" ].orientation _ [0., 0., 1.]; ThreeDScenes.FindShape[ context3d.shapes, "ChampagneGlass" ].rotation _ 45.0; ThreeDMisc.SetFacetedColor[context3d, "ChampagneGlass", [1.,0.,1.] ]; ThreeDMisc.SetSmoothColor[context3d, "ChampagneGlass", [1.,0.,1.] ]; ThreeDMisc.SetTransmittance[context3d, "ChampagneGlass", .8 ]; ThreeDMisc.SetFacetedColor[context3d, "UtahEgg", [1.0, .8, .5] ]; ThreeDMisc.SetSmoothColor[context3d, "UtahEgg", [1.0, .8, .5] ]; ThreeDMisc.SetFacetedColor[context3d, "Banana", [1.0, .9, .1] ]; ThreeDMisc.SetSmoothColor[context3d, "Banana", [1.0, .9, .1] ]; scene2 _ NEW[ThreeDScenes.ShapeSequence[context3d.shapes.length] _ context3d.shapes^]; } ELSE context3d.shapes _ scene2; NoDepthBuffer[]; currentScene _ scene2; }; SetScene3: PROCEDURE [] ~ { IF scene3 = NIL THEN { context3d.shapes _ context3d.lights; -- don't change the lighting; ThreeDMisc.AddShapeAt[context3d, "TeaPot", "TeaPotWithBot.bezier", [0.0, 0.0, -1.25], $Bezier ]; scene3 _ NEW[ThreeDScenes.ShapeSequence[context3d.shapes.length] _ context3d.shapes^]; ThreeDScenes.SetView[context3d, [3.0, -10.0, 3.0], [0.0, 0.0, 0.0] ]; } ELSE context3d.shapes _ scene3; SetDepthBuffer[]; currentScene _ scene3; }; PutPixel: PROCEDURE[x, y: NAT, clr: RGB] ~ { ThreeDMisc.PutPixel[context3d, x, y, clr]; }; <> MakeFrame: PROC ~ { ThreeDSurfaces.EnableDisplay[]; -- get stop flag unstuck, if necessary ThreeDMisc.MakeFrame[context3d ]; -- clear and make new frame }; ShowShapes: PROC ~ { ThreeDSurfaces.EnableDisplay[]; -- get stop flag unstuck, if necessary ThreeDMisc.ShowShapes[context3d ]; -- show shapes without clearing }; movieFileRoot: Rope.ROPE _ "/Pixel/Crow/Animation/StillCloser.ais"; movieViewPort: Imager.Rectangle _ [120.0, 90.0, 400.0, 300.0]; movieNumFiles: NAT _ 40; movieStart: NAT _ 1; SetUpMovie: PROC[fileRoot: Rope.ROPE, viewPort: Imager.Rectangle, numFiles, start: NAT] ~ { ChangeRenderMode[$PseudoClr]; movieFileRoot _ fileRoot; movieViewPort _ viewPort; movieNumFiles _ numFiles; movieStart _ start; frames _ NIL; }; frameRate: INTEGER _ 6; -- playback rate in frames/second, negative plays backwards PlayBackbyFrame: PROC ~ { cachedViewPort _ context3d.viewPort; ThreeDMisc.SetNamedColor[context3d, "Vivid Green" ]; IF context3d.renderMode # $PseudoClr THEN { ThreeDMisc.ShowRope[context3d, 140.0, 50.0, "Change to 8-bit pseudocolor, please!"]; RETURN[]; }; ThreeDScenes.FillInBackGround[context3d]; ThreeDMisc.ShowRope[context3d, 140.0, 50.0, "Control frame rate using left button"]; movie _ TRUE; SetViewPort[ movieViewPort ]; IF frames = NIL THEN { pictures _ NIL; -- avoid using up all the VM frames _ AISAnimation.CacheNumberedAISFiles[ context3d, movieFileRoot, movieNumFiles, movieStart ]; }; WHILE movie DO AISAnimation.ShowNextAISCacheFrame[context3d, frames, frameRate]; CedarProcess.CheckAbort[]; ENDLOOP; SetViewPort[ cachedViewPort ]; }; pictureFile: Rope.ROPE _ "/Cyan/AIS/Crow/PrettyPictures.txt"; pictures: REF AISAnimation.FrameSequence; LoadGallery: PROC ~ { ThreeDMisc.SetNamedColor[context3d, "Vivid Green" ]; IF context3d.renderMode # $Dorado24 THEN { ThreeDMisc.ShowRope[context3d, 140.0, 50.0, "Change to 24-bit color, please!"]; RETURN[]; }; ThreeDScenes.FillInBackGround[context3d]; ThreeDMisc.ShowRope[context3d, 140.0, 50.0, "Left button, ahead - Right button, back"]; gallery _ TRUE; SetAliased[]; IF pictures = NIL THEN pictures _ NEW[AISAnimation.FrameSequence[16]]; pictures _ AISAnimation.CacheAISFiles[context3d, pictureFile, pictures]; }; ShowNextPicture: PROC ~ { -- display next picture in sequence IF pictures # NIL AND pictures.length > 0 -- make sure frame ready and no wraparound AND ((pictures.currentFrame + 1) MOD pictures.length) >= pictures.currentFrame THEN AISAnimation.ShowNextAISCacheFrame[context3d, pictures, 10]; }; ShowLastPicture: PROC ~ { -- display previous picture in sequence IF pictures # NIL AND pictures.currentFrame > 0 THEN AISAnimation.ShowNextAISCacheFrame[context3d, pictures, -10]; }; ClearGallery: PROC ~ { IF pictures # NIL THEN FOR i: NAT IN [0..pictures.length) DO pictures[i].pixels _ NIL; ENDLOOP; gallery _ FALSE; }; Init[]; END.