DIRECTORY Atom USING [ GetPropFromList, RemPropFromList, PutPropOnList ], List USING [ Memb ], CedarProcess USING [ Abort, CheckAbort, Fork, ForkableProc, Process], Process USING [ Pause, SecondsToTicks ], Terminal USING [ Virtual, Current ], Rope USING [ ROPE ], Real USING [ FixI, Float ], Imager USING [ Context, Rectangle ], ImagerColor USING [ RGB ], ImagerColorMap USING [SetStandardColorMap], QuickViewer USING [ BuildViewer, DrawInViewer, QuickView ], ViewerOps USING [ ChangeColumn, OpenIcon ], Vector3d USING [ Triple ], Pixels USING [ PixelBuffer ], ThreeDScenes USING [ AddAlphaBuffer, AddDepthBuffer, Context, Create, DisplayFromImagerContext, DisplayFromVM, FillInBackGround, FindShape, GetShading, PutShading, SetLight, SetView, SetViewPort, SetWindow, ShapeSequence, WindowFromViewPort ], ThreeDMisc USING [ AddShapeAt, CloseLog, CopyContextData, LoadColorRamp, LoadStd8BitClrMap, MakeFrame, OrbitEye, PutPixel, SetBackgroundColor, SetFacetedColor, SetShininess, SetSmoothColor, SetTransmittance, ShowRope, ShowShapes, StartLog, UpdateDisplay ], AISAnimation USING [ FrameSequence, ShowNextAISCacheFrame, CacheAISFiles, CacheNumberedAISFiles ]; ThreeDDemoImpl: CEDAR MONITOR IMPORTS Atom, List, AISAnimation, CedarProcess, ImagerColorMap, Process, QuickViewer, Real, Terminal, ThreeDMisc, ThreeDScenes, ViewerOps ~ BEGIN ThreeDDemoError: PUBLIC SIGNAL [reason: ATOM] = CODE; Context: TYPE ~ ThreeDScenes.Context; Triple: TYPE ~ Vector3d.Triple; RGB: TYPE ~ ImagerColor.RGB; window3d: REF QuickViewer.QuickView; context3d, offScreenCtx, onScreenCtx: REF Context; currentScene, scene1, scene2, scene3: REF ThreeDScenes.ShapeSequence _ NIL; frames: REF AISAnimation.FrameSequence; xNow, yNow, zNow: REAL _ 3.0; xOrigin, yOrigin: REAL _ 100.0; animation, gallery: BOOLEAN _ FALSE; movieProcess: CedarProcess.Process _ NIL; cachedViewPort: Imager.Rectangle; Init: PROC[] ~ { context3d _ ThreeDScenes.Create[]; context3d.preferredRenderMode _ $PseudoColor; context3d.viewer _ window3d _ QuickViewer.BuildViewer[ "ThreeDDemo", LIST["Help", "NewScene", "Lines", "Facets", "Smooth", "Shiny", "Orbit", "STOP!", "Movie", "Gallery", "Jaggy", "NoJaggy", "Reset"], ReDraw, MenuHit, ShutDown ]; ThreeDMisc.SetBackgroundColor[ context3d, "Darkish Blue" ]; -- set background color [] _ ThreeDScenes.SetLight[context3d, "Initial", [-100., -200., 50.] ]; ThreeDScenes.SetView[ context3d, [2.0, -10.0, 3.0], [0.0, 0.0, 0.0] ]; SetScene1[]; IF window3d.outer.column # color THEN ViewerOps.ChangeColumn[window3d.outer, color]; IF window3d.outer.iconic THEN ViewerOps.OpenIcon[icon: window3d.outer]; }; Reset: PROCEDURE [] ~ { DoReDraw: PROCEDURE [imagerCtx: Imager.Context] ~ { ReDraw[imagerCtx, NIL]; }; context3d.stopMe _ FALSE; -- get stop flag unstuck, if necessary 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] ]; gallery _ FALSE; currentScene _ NIL; frames _ NIL; QuickViewer.DrawInViewer[window3d, DoReDraw]; -- gets a new imager context }; ReDraw: PROCEDURE [imagerCtx: Imager.Context, toDo: REF ANY] ~ { ENABLE UNWIND => NULL; ThreeDScenes.DisplayFromImagerContext[context3d, imagerCtx]; IF context3d.depthBuffer THEN ThreeDScenes.AddDepthBuffer[context3d]; IF context3d.alphaBuffer THEN ThreeDScenes.AddAlphaBuffer[context3d]; }; Notify: ENTRY PROCEDURE [] ~ { NOTIFY context3d.halted; }; ShutDown: PROCEDURE [] ~ { buf: Pixels.PixelBuffer; -- zeroed buffer context3d.display _ buf; IF offScreenCtx # NIL THEN offScreenCtx.display _ buf; frames _ NIL; -- free frame storage for garbage colection pictures _ NIL; -- free image storage for garbage collection ThreeDMisc.CloseLog[context3d]; }; GetOffScreenCtx: PROC[context: REF Context, width, height: NAT] ~ { offScreenCtx _ ThreeDScenes.Create[]; ThreeDScenes.DisplayFromVM[offScreenCtx, width, height, context.renderMode]; IF context.alphaBuffer THEN ThreeDScenes.AddAlphaBuffer[offScreenCtx]; 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: PROC[context: REF Context, width, height: NAT] ~ { GetDisplay: PROC[ imagerCtx: Imager.Context] ~ { ThreeDScenes.DisplayFromImagerContext[ onScreenCtx, imagerCtx ]; IF context.depthBuffer THEN ThreeDScenes.AddDepthBuffer[context3d]; IF context.alphaBuffer THEN ThreeDScenes.AddAlphaBuffer[context3d]; }; onScreenCtx _ ThreeDScenes.Create[]; QuickViewer.DrawInViewer[ NARROW[context.viewer], GetDisplay ]; IF context.alphaBuffer THEN ThreeDScenes.AddAlphaBuffer[onScreenCtx]; IF context.depthBuffer THEN ThreeDScenes.AddDepthBuffer[onScreenCtx]; 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; }; StopEverything: PROCEDURE[] ~ { -- panic stop bufContext: REF Context _ NARROW[ Atom.GetPropFromList[context3d.props, $BufferContext] ]; context3d.stopMe _ TRUE; IF bufContext # NIL THEN { bufContext.stopMe _ TRUE; context3d.props _ Atom.RemPropFromList[context3d.props, $BufferContext]; }; IF gallery THEN ClearGallery[]; IF movieProcess # NIL THEN { CedarProcess.Abort[movieProcess]; movieProcess _ NIL; SetViewPort[ cachedViewPort ]; }; }; MenuHit: PROCEDURE[bttn, choice: ATOM, x, y: REAL] ~ { x _ x - context3d.display.width/2; -- center mouse coords y _ y - context3d.display.height/2; SELECT bttn FROM $Help => HelpMessage; $NewScene => IF currentScene = NIL THEN SetScene1[] ELSE IF currentScene = scene1 THEN SetScene2[] ELSE IF currentScene = scene2 THEN SetScene3[] ELSE SetScene1[]; $Lines => LinesDemo[]; $Facets => FacetedDemo[]; $Smooth => SmoothDemo[]; $Shiny => ShinyDemo[]; $Orbit => Orbit[]; $STOP => StopEverything[]; $Movie => movieProcess _ CedarProcess.Fork[PlayBackbyFrame]; $Gallery => [] _ CedarProcess.Fork[LoadGallery]; $Jaggy => SetAliased[]; $NoJaggy => SetAntiAliased[]; $Reset => { StopEverything[]; Reset[]; }; $LeftButton, $LeftHeld => IF movieProcess # NIL THEN frameRate _ Real.FixI[x / 10.] ELSE IF gallery THEN ShowNextPicture[] ELSE { xNow _ x / 15.0; yNow _ y / 15.0; ThreeDScenes.SetView[ context3d, [xNow, yNow, zNow], context3d.ptOfInterest ]; MakeFrame[]; }; $MiddleButton, $MiddleHeld => IF NOT context3d.lineDrawing THEN { xLight: REAL _ x * 1.0; yLight: REAL _ y * 1.0; [] _ ThreeDScenes.SetLight[ context3d, "Initial", [xLight, yLight, 50.0] ]; MakeFrame[]; }; $RightButton, $RightHeld => IF gallery THEN ShowLastPicture[] ELSE { zNow _ y / 15.0; ThreeDScenes.SetView[ context3d, [xNow, yNow, zNow], context3d.ptOfInterest ]; MakeFrame[]; }; ENDCASE; }; HelpMessage: PROCEDURE [] ~ { 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, $PseudoColor, $Grey} SELECT mode FROM $Dithered => ImagerColorMap.SetStandardColorMap[ Terminal.Current[] ]; $PseudoColor => 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; context3d.preferredRenderMode _ mode; context3d.display.props _ Atom.PutPropOnList[ context3d.display.props, $RenderMode, mode ]; }; SetDepthBuffer: PROCEDURE [] ~ { IF context3d.depthBuffer = TRUE THEN RETURN[]; ThreeDScenes.AddDepthBuffer[context3d]; }; NoDepthBuffer: PROCEDURE [] ~ { GetDisplay: PROC[ imagerCtx: Imager.Context] ~ { ThreeDScenes.DisplayFromImagerContext[ context3d, imagerCtx ]; }; IF context3d.depthBuffer = FALSE THEN RETURN[]; QuickViewer.DrawInViewer[ NARROW[context3d.viewer], GetDisplay ]; IF context3d.alphaBuffer THEN ThreeDScenes.AddAlphaBuffer[context3d]; context3d.depthBuffer _ FALSE; }; SetAliased: PROCEDURE [] ~ { GetDisplay: PROC[ imagerCtx: Imager.Context] ~ { ThreeDScenes.DisplayFromImagerContext[ context3d, imagerCtx ]; }; IF context3d.alphaBuffer = FALSE THEN RETURN[]; QuickViewer.DrawInViewer[ NARROW[context3d.viewer], GetDisplay ]; IF context3d.depthBuffer THEN ThreeDScenes.AddDepthBuffer[context3d]; context3d.alphaBuffer _ FALSE; }; SetAntiAliased: PROCEDURE [] ~ { IF context3d.alphaBuffer = TRUE THEN RETURN[]; ThreeDScenes.AddAlphaBuffer[context3d]; }; 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.ShowRope[context3d, 60.0, 340.0, "No objects, nothing to display"]; error _ TRUE; }; IF context3d.alphaBuffer AND NOT List.Memb[ context3d.renderMode, LIST[$Grey, $FullColor, $Dorado24] ] THEN { 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; 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 { color: REF _ ThreeDScenes.GetShading[context3d.shapes[i], $Color]; rgb: RGB _ IF color # NIL THEN NARROW[color, REF RGB ]^ ELSE [0.7, 0.7, 0.7]; 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; context3d.stopMe _ FALSE; -- get stop flag unstuck, if necessary context3d.suspendMe _ FALSE; animation _ TRUE; ThreeDMisc.OrbitEye[ context: context3d, lookingFrom: context3d.eyePoint, lookingAt: context3d.ptOfInterest, axis: [0.3, 0.0, 1.0], framesPerRev: 53 ! UNWIND => animation _ FALSE ]; animation _ FALSE; }; 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 ]; 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, "CutCube", [.9, .3, .1] ]; scene1 _ NEW[ThreeDScenes.ShapeSequence[context3d.shapes.length] _ context3d.shapes^]; context3d.lineDrawing _ TRUE; } 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] ]; 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.shape", [0.0, 0.0, -1.25] ]; 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 ~ { context3d.stopMe _ FALSE; -- get stop flag unstuck, if necessary ThreeDMisc.MakeFrame[context3d ]; -- clear and make new frame }; ShowShapes: PROC ~ { context3d.stopMe _ FALSE; -- 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[$PseudoColor]; movieFileRoot _ fileRoot; movieViewPort _ viewPort; movieNumFiles _ numFiles; movieStart _ start; frames _ NIL; }; frameRate: INTEGER _ 6; -- playback rate in frames/second, negative plays backwards PlayBackbyFrame: ENTRY CedarProcess.ForkableProc ~ { ENABLE UNWIND => NULL; context3d.stopMe _ FALSE; -- get stop flag unstuck, if necessary cachedViewPort _ context3d.viewPort; IF context3d.renderMode # $PseudoColor THEN { ThreeDMisc.ShowRope[context3d, 140.0, 50.0, "Change to 8-bit pseudocolor, please!"]; RETURN[]; }; ThreeDScenes.FillInBackGround[context3d]; SetViewPort[ movieViewPort ]; IF frames = NIL THEN { pictures _ NIL; -- avoid using up all the VM frames _ AISAnimation.CacheNumberedAISFiles[ context3d, movieFileRoot, movieNumFiles, movieStart ]; }; ThreeDMisc.ShowRope[context3d, 140.0, 50.0, "Control frame rate using left button"]; WHILE TRUE DO ENABLE UNWIND => SetViewPort[ cachedViewPort ]; changed: BOOLEAN _ ThreeDMisc.UpdateDisplay[context3d]; IF changed THEN { Process.Pause[Process.SecondsToTicks[2]]; -- hang on moment to allow things to settle SetViewPort[ movieViewPort ]; }; AISAnimation.ShowNextAISCacheFrame[context3d, frames, frameRate]; CedarProcess.CheckAbort[]; ENDLOOP; }; pictureFile: Rope.ROPE _ "/Cyan/AIS/Crow/PrettyPictures.txt"; pictures: REF AISAnimation.FrameSequence; LoadGallery: CedarProcess.ForkableProc ~ { IF context3d.renderMode # $Dorado24 THEN { ThreeDMisc.ShowRope[context3d, 140.0, 50.0, "Change to 24-bit color, please!"]; RETURN[]; }; context3d.stopMe _ FALSE; -- get stop flag unstuck, if necessary ThreeDScenes.FillInBackGround[context3d]; ThreeDMisc.ShowRope[context3d, 140.0, 50.0, "Pictures will appear as they are read in"]; ThreeDMisc.ShowRope[context3d, 140.0, 20.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, December 16, 1986 5:22:56 pm PST 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, grabs Imager context and rebuilds context3d.display This will be called when the viewer is destroyed Makes a new view of the supplied context, useful for using two portions of the screen differently, etc. This will be called whenever the mouse is moved or a button is pushed. ! ThreeDScenes.ThreeDScenesError => IF reason = $NullClipper THEN RESUME Demos Frame Generation and Animation ΚY˜headšœ™Jšœ6™6defaultšΟk ˜ Jšœ œœ2˜CJšœ œ ˜Jšœœ3˜GJšœ œ˜+Jšœ œ˜'Jšœ œœ˜Jšœ œ˜Jšœ œ˜'Jšœœœ˜Jšœœ˜,Lšœœ*˜=Jšœ œ˜-Jšœ œ ˜Jšœ œ˜!Jšœœ†˜™Jšœ œ”˜¦JšœœY˜l——head2šœœ˜Jšœƒ˜ŠJ˜Jšœ˜J˜—head3šΠbi™Iaš œœœ œœ˜5Iunitšœ œ˜%Lšœœ˜Jšœœœ˜—šΟb™Jšœ œ˜$Jšœ&œ ˜3Jšœ&œœ˜KJšœœ˜'Jšœœ˜Jšœœ ˜Jšœœœ˜$Lšœ%œ˜)Lšœ!˜!—šŸ™šΟnœœ˜Jšœ"˜"Ošœ-˜-šœ6˜6Jšœ ˜ Jšœ~˜‚Jšœ˜Jšœ ˜ Jšœ ˜ Jšœ˜—Jšœ=Οc˜TJšœH˜HJšœF˜FJšœ ˜ Lšœœ/˜TLšœœ*˜GJšœ˜O˜J™H—š œ œ˜Jš œ œ4œ˜PJšœœ‘&˜FJšœV˜VJšœ'‘˜@JšœF˜FJšœ œ˜Jšœœ˜Jšœ œ˜ Jšœ0‘˜LJšœ˜Icode˜J™c—š œ œ#œœ˜AJšœœœ˜Jšœ<˜Jšœ˜Jšœ˜J˜—š œœ œœ˜COšœ%˜%OšœL˜LOšœœ+˜FOšœB˜BOšœX˜XJšœ'˜'šœœœ!œ˜1Jšœ&œ˜+Jšœ˜—Jšœ˜—š œœ œœ˜BOšœg™gš  œœ ˜0Ošœ@˜@Jšœœ(˜CJšœœ(˜CO˜—Ošœ$˜$Ošœœ˜?Ošœœ*˜EOšœœ*˜EOšœA˜AOšœW˜Wšœœœ œ˜0Jšœ%œ˜*Jšœ˜—Jšœ˜—š œ œ‘ ˜5šœ œ œ˜!Ošœ5˜5Ošœ˜—Jšœœ˜šœœœ˜Jšœœ˜OšœH˜HJšœ˜—Jšœ œ˜šœœœ˜Jšœ!˜!Jšœœ˜Jšœ˜Jšœ˜—Jšœ˜—š œ œœœ˜7J™FJšœ&‘˜˜>O˜—Jšœœœœ˜/Ošœœ!˜AOšœœ(˜EJšœœ˜Jšœ˜—š  œ œ˜š  œœ ˜0Ošœ>˜>O˜—Jšœœœœ˜/Ošœœ!˜AOšœœ(˜EJšœœ˜Jšœ˜—š œ œ˜!Jšœœœœ˜.Jšœ'˜'Jšœ˜—š  œ œœ œœ˜Eš   œ œ œœœ˜Ršœœœ˜%Jš œœœœœ˜0Jš˜—Jšœœ˜ J˜—šœœœœ˜@JšœN˜NJšœœ˜ J˜—šœ˜Jšœœ"œ ˜Mšœ˜JšœW˜WJšœœ˜ J˜——J˜—š  œ œ ˜Jšœœ˜Jšœœœ˜#šœœœœ˜.šœœ˜%Jšœ>˜B—Jšœ˜—Jšœ˜Jšœ˜—š  œ œ ˜ Jšœœ˜Jšœœœ˜#šœœœœœœœ˜Yšœ:‘˜JJšœ"˜"J˜ —Jšœ?˜?šœ?œœ˜KJšœœ8˜BJšœœœ œœœœœœ˜NJšœ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šœœ‘&˜FJšœœ˜Jšœ œ˜šœ˜Jšœ˜Jšœ ˜ Jšœ#˜#Jšœ˜Jšœ˜Jšœœ˜Jšœ˜—Jšœ œ˜Jšœ˜J˜—š  œ œ ˜šœ œœ˜Jšœ'‘˜Cšœ!˜!Jšœ‘˜'Jšœ‘ ˜(Jšœ‘ ˜%Jšœ˜—JšœX˜XJšœW˜WJšœP˜PJšœG‘˜UJšœE˜EJšœA˜AJšœ œJ˜VJšœœ˜Jšœ˜—Jšœ˜Jšœ˜Jšœ˜Jšœ˜—š  œ œ ˜šœ œ˜Jšœ'‘˜DJšœf˜fJšœ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šœV˜VJšœ œJ˜WJ˜EJ˜—Jšœ˜Jšœ˜Jšœ˜Jšœ˜—š œ œœœ˜,Jšœ*˜*Jšœ˜——šŸ™š  œœ˜Jšœœ‘&˜FJšœ(‘˜CJšœ˜—š  œœ˜Jšœœ‘&˜FJšœ(‘˜GJšœ˜Jšœœ+˜CJšœ>˜>Jšœœ˜Jšœ œ˜—š  œœœ/œ˜[Jšœ˜Jšœ˜Jšœ˜Jšœ˜Jšœ˜Jšœ ˜ Jšœ˜Ošœ œ‘;˜T—š œœ˜4Jšœœœ˜Jšœœ‘&˜FLšœ$˜$šœ%œ˜-JšœT˜TJšœ˜ J˜—Jšœ)˜)Ošœ˜šœ œœ˜Jšœ œ ‘˜3šœ,˜,Jšœ3˜3Jšœ˜—O˜—JšœT˜Tšœœ˜ Jšœœ"˜/Jšœ œ*˜:šœ œ˜Jšœ*‘+˜UJšœ˜J˜—JšœA˜AJšœ˜Jšœ˜—Ošœ˜J˜Jšœœ'˜=Jšœ œ˜*—š  œ˜*šœ"œ˜*JšœO˜OJšœ˜ J˜—Jšœœ‘&˜FJšœ)˜)JšœX˜XJšœW˜WO˜Ošœ œ˜Jšœ ˜ Ošœ œœ œ!˜FOšœH˜HOšœ˜J˜—š œœ‘#˜?š œ œœ‘,œœ+˜₯Jšœ=˜A—Jšœ˜—š œœ‘'˜Cšœ œœ˜0Jšœ>˜B—Jšœ˜—š  œœ˜šœ œ˜Jšœœœœœœœ˜P—Jšœ œ˜Jšœ˜—O˜—˜J˜Jšœ˜——…—LώbΫ