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. 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. €ThreeDDemoImpl.mesa Last Edited by: Crow, June 3, 1986 3:32:29 pm PDT Types Global Variables Context and Interactive Control This resets the clipper, transformation, scene, etc. to the unused state This will be called when the viewer is changed This will be called when the viewer is destroyed This will be called whenever the mouse is moved or a button is pushed. All atomic operations must occur in here. fork process for safe remote aborting fork process for safe remote aborting, then proceeed so buttons may be caught ! ThreeDScenes.ThreeDScenesError => IF reason = $NullClipper THEN RESUME Demos Frame Generation and Animation Κυ˜headšœ™Jšœ1™1defaultšΟk ˜ Jšœ œœ2˜CJšœ œ ˜Jšœœ:˜NJšœ œ˜'Jšœ œ˜(Jšœ œœ˜(Jšœ œ˜Jšœ œ˜'Jšœœœ˜Jšœœ˜,Lšœœ#˜6Jšœ œ˜#Jšœœ ˜ Jšœ œ ˜Jšœ œ˜!JšœœΩ˜μJšœœ ˜5Jšœ œΤ˜ζJšœœf˜y——head2šœœ˜Jšœ›˜’J˜Jšœ˜J˜—head3šΠbi™Iaš œœœ œœ˜5Iunitšœœ˜Jšœœœ˜—šΟb™Jšœ&œ˜@Jšœ&œœ˜KJšœœ˜'Jšœœ˜Jšœœ ˜Jšœ*œœ˜:Lšœ!˜!Jšœ'œ˜+—šŸ™šΟnœœ˜Jšœœ˜#Jšœ˜Jšœ œ$Οc#˜VJšœC‘ ˜PJšœœ˜šœ$˜$Jšœp˜tJšœ˜Jšœ ˜ Jšœ ˜ Jšœ ˜ Jšœ‘'˜/Jšœ˜—Jšœ œ6˜ELšœœ'˜DJšœ œ‘ ˜5Jšœ;˜;JšœD‘˜UJšœ8‘˜OJšœH˜HJšœ ˜ JšœF˜FJšœ œ˜Jšœœ˜Jšœ˜O˜J™H—š œ œ˜JšœC˜CJšœœ˜Jšœ˜Jšœ&‘&˜LJšœ9˜9JšœV˜VJšœ'‘˜@JšœF˜FJšœœ˜Jšœœ˜Jšœœ˜Jšœ˜Icode˜J™.—š œ œ!˜3Jšœ œ˜%Jšœ˜Jšœ œœ‘)˜GJšœœ˜Jšœ œ ‘˜7Jšœ0˜0Jšœ œœ‘˜Dšœ0˜0Jšœ8˜8Jšœ˜—Jšœ'˜'Jšœ/˜/Jšœ/˜/Jšœ-˜-Jšœ)˜)Jšœ"˜"Jšœ œ˜Jšœœ˜Jšœ˜Q˜J™0—š œ œ˜Jšœ‘˜*Jšœ˜Jšœœœ˜6Jšœœ˜Jšœ œ‘+˜;Jšœ œ‘,˜>Jšœ˜Jšœ˜J˜—š  œœœ œ&œ˜Wšœ#˜#Ošœ˜Ošœ˜Ošœ˜Ošœ˜Ošœ˜—OšœB˜BOšœX˜XJšœ'˜'šœœœ!œ˜1Jšœ&œ˜+Jšœ˜—Jšœ˜—š  œœœ œ&œ˜Všœ1˜1Jšœ%˜%Ošœ˜Ošœ˜Ošœ˜Ošœ˜—OšœA˜AOšœW˜Wšœœœ œ˜0Jšœ%œ˜*Jšœ˜—Jšœ˜J™FJ™)—š  œœœœœ˜HJš Ÿœ&œœœ ‘˜`š  œœ œ˜$š œœœœ œœ˜PJš‘%™%—Jšœ)œœ ˜=Jšœ-‘˜AJšœœ˜Jšœ˜—š  œœ œ˜"š œœœœ œœ˜PJš‘M™M—Jšœ)œœ ˜=Jšœ˜—š œœ˜Jšœ˜Jšœ˜Jšœœœ%‘ ˜KJšœ-‘˜AJšœœ˜Jšœ œ˜šœœ˜Jšœœ˜Ošœ!‘˜4J˜—Jšœ˜—šœœœ˜'Jšœ&˜&šœœ˜'Jšœœ˜"šœœœ˜#Jšœœ˜!Jšœœ˜#——Jšœ$˜$Jšœ(˜(Jšœ(˜(Jšœ&˜&Jšœ ˜ Jšœ˜Jšœ*˜*Jšœ(˜(Jšœ&˜&Jšœ,˜,Jšœ0˜0šœœ˜#Jšœ˜#Jšœœ œ˜&š œœœœœ˜CJšœ˜Jšœ˜JšœN˜NJšœ˜Jšœ˜——šœ˜šœœœœ˜>Jšœœ ˜Jšœœ ˜JšœK˜KJšœœœ˜7Jšœ˜——šœ˜Jšœ œ˜!š œœœœœ˜CJšœ˜JšœN˜NJšœ˜Jšœ˜———Jšœ˜J˜J˜—š  œ œ˜Jšœ4˜4Jšœn˜nJšœk˜kJšœp˜pJšœt˜tJšœc˜cJšœu˜uJšœg˜gJšœs˜sJšœe˜eJšœf˜fJšœu˜uJ˜J˜—š  œœ˜0šœ/‘˜CJšœ$œœ™H—šœœœ˜-Jšœ#œ˜(Jšœ%œ˜*Jšœ˜—šœ‘6˜LJšœ˜Jšœ˜Jšœ%˜%Jšœ#˜#Jšœ˜Jšœ#˜#Jšœ#˜#Jšœ˜Jšœ˜—O˜—š œœ œ‘%˜Pšœ˜OšœG˜GOšœB˜Bšœ ˜ OšœX˜X—Ošœœ$˜7—Ošœ˜O˜——šŸ™š œ œ˜!Jšœ œ˜"Jšœœœœ˜.šœ,˜,JšœQ˜WJš œ˜ Jšœ˜—Jšœ%˜%Lšœœœ˜?Jšœ+˜+Jšœ˜Jšœ˜—š  œ œ˜ Jšœ œ˜"Jšœœœœ˜/šœ,˜,JšœQ˜WJšœ˜Jšœ˜—Jšœ%˜%Lšœœ˜Jšœ+˜+Jšœ˜Jšœ˜—š  œ œ˜šœ œ:˜FJšœQ˜WJšœ˜Jšœ˜—Jšœ%˜%Lšœœ˜Jšœ+˜+Jšœ˜Jšœ˜—š œ œ˜!šœ œ:˜FJšœQ˜WJšœ˜Jšœ˜—Jšœ%˜%Lšœœœ˜?Jšœ+˜+Jšœ˜Jšœ˜—š  œ œœ œœ˜Eš   œ œ œœœ˜Ršœœœ˜%Jš œœœœœ˜0Jš˜—Jšœœ˜ J˜—šœœœœ˜@Jšœ3˜3JšœN˜NJšœœ˜ J˜—šœ˜Jšœœ"œ˜Kšœ˜Jšœ3˜3JšœW˜WJšœœ˜ J˜——J˜—š  œ œ ˜Jšœœ˜Jšœœœ˜#šœœ˜Jšœ ˜šœ˜šœœœœ˜.šœœ˜%Jšœ>˜B—Jšœ˜—Jšœ˜Jšœ˜——Jšœ˜—š  œ œ ˜ Jšœœ˜Jšœœœ˜#šœœœœœœœ˜Yšœ:‘˜JJšœ"˜"J˜ —Jšœ?˜?šœ?œœ˜KJš œœœ7œœ˜SJšœE˜EJšœ˜—J˜Jšœ˜—Jšœ˜Jšœ˜—š  œ œ ˜!Jšœœ˜Jšœœœ˜#šœœœœœœœ˜Yšœ:‘˜JJšœ"˜"J˜ —Jšœ>˜>J˜Jšœ˜—Jšœ˜Jšœ˜—š  œ œ ˜"Jšœœ˜Jšœœœ˜#šœœœœœœœ˜Yšœ œœœ˜Jšœ9˜9Jšœ˜—šœ œœ˜Jšœ œœ ˜JšœK˜KJ˜—šœœ7œ ˜OJšœ?˜C—Jšœ˜Jšœ˜—Jšœ˜Jšœ˜—š œ œ˜Jšœœœ˜#Jšœ&‘&˜Lšœ˜Jšœ˜Jšœ ˜ Jšœ#˜#Jšœ˜Jšœ˜Jšœ˜—Jšœ˜J˜—š  œ œ ˜šœ œœ˜Jšœ'‘˜Cšœ!˜!Jšœ‘˜'Jšœ‘ ˜(Jšœ‘ ˜&Jšœœ‘4˜LJšœ˜—JšœX˜XJšœW˜WJšœP˜PJšœG‘˜UJšœE˜EJšœD˜DJšœD˜DJšœE˜EJšœE˜EJšœA˜AJšœ@˜@JšœX˜XJšœU˜UJšœ œJ˜VJšœ˜—Jšœ˜Jšœ˜Jšœ˜Jšœ˜—š  œ œ ˜šœ œ˜Jšœ'‘˜DJšœ|œ‘$˜«JšœN˜NJšœK˜KJšœR˜RJšœF˜FJšœX˜XJšœM˜MJšœE˜EJšœD˜DJšœ>˜>JšœA˜AJšœ@˜@Jšœ@˜@Jšœ?˜?Jšœ œJ˜WJ˜—Jšœ˜Jšœ˜Jšœ˜Jšœ˜—š  œ œ ˜šœ œ˜Jšœ'‘˜DJšœk˜kJšœ œJ˜WJ˜EJ˜—Jšœ˜Jšœ˜Jšœ˜Jšœ˜—š œ œœœ˜,Jšœ*˜*Jšœ˜——šŸ™š  œœ˜Jšœ&‘&˜LJšœ(‘˜CJšœ˜—š  œœ˜Jšœ&‘&˜LJšœ(‘˜GJšœ˜JšœC˜CJšœ>˜>Jšœœ˜Jšœ œ˜—š  œœœ/œ˜[Jšœ˜Jšœ˜Jšœ˜Jšœ˜Jšœ˜Jšœ ˜ Jšœ˜Ošœ œ‘;˜T—š œœ˜Lšœ$˜$Ošœ4˜4šœ#œ˜+JšœT˜TJšœ˜ J˜—Jšœ)˜)JšœT˜TOšœœ˜ Ošœ˜šœ œœ˜Jšœ œ ‘˜3šœ,˜,Jšœ3˜3Jšœ˜—O˜—šœ˜JšœA˜AJšœ˜Jšœ˜—Ošœ˜Ošœ˜J˜Jšœ=˜=Jšœ œ˜*—š  œœ˜Ošœ4˜4šœ"œ˜*JšœO˜OJšœ˜ J˜—Jšœ)˜)JšœW˜WO˜Ošœ œ˜Jšœ ˜ Ošœ œœ œ!˜FOšœH˜HOšœ˜J˜—š œœ‘#˜?š œ œœ‘,œœ+˜₯Jšœ=˜A—Jšœ˜—š œœ‘'˜Cšœ œœ˜0Jšœ>˜B—Jšœ˜—š  œœ˜šœ œ˜Jšœœœœœœœ˜P—Jšœ œ˜Jšœ˜—O˜—˜J˜Jšœ˜——…—UHl½