<> <> DIRECTORY Rope USING [ Cat, ROPE, Substr, Index ], Convert USING [ RopeFromReal, RopeFromInt, TimeFromRope ], BasicTime USING [ GetClockPulses, PulsesToSeconds, Period, Now, GMT ], IO USING [ UnsafePutBlock ], Terminal USING [ Current ], ColorDisplay USING [ GetColorDisplayStatus, SetColorDisplayStatus ], WindowManager USING [ StopColorViewers ], Real USING [ Fix, RoundI, Float ], ComputeServerServer USING [ Register ], Commander USING [ CommandProc, Register ], Args USING [ Arg, ArgsGet ], Pixels USING [ GetScanSeg, GetFromTerminal, PixelBuffer, SampleSetSequence ], SampleMapOps USING [ GetPointer ], ThreeDMisc USING [ AddShapeAt, MakeFrameFromFile, MakeFrame, SetSmoothColor, SetFacetedColor ], ThreeDScenes USING [ Error, Create, ReadScene, SetEyeSpace, SetLight, SetView, SetViewPort, SetWindow, WindowFromViewPort ], ThreeDBasics USING [ Context ]; Render3dSceneImpl: CEDAR PROGRAM IMPORTS Args, BasicTime, ColorDisplay, Commander, ComputeServerServer, Convert, IO, Pixels, Real, Rope, SampleMapOps, Terminal, ThreeDMisc, ThreeDScenes, WindowManager ~ BEGIN Ceiling: PROC[ in: REAL ] RETURNS[ out: INTEGER ] ~ { out _ Real.RoundI[in]; IF Real.Float[out] < in THEN out _ out + 1; }; ElapsedTime: PROC[startTime: REAL] RETURNS[Rope.ROPE] ~ { timeX100: REAL _ 100.0 * (BasicTime.PulsesToSeconds[BasicTime.GetClockPulses[]] - startTime); RETURN[ Rope.Cat[ Convert.RopeFromReal[ Real.Fix[timeX100] / 100.0 ], " s. " ] ]; }; CurrentTime: PROC[] RETURNS[REAL] ~ { RETURN[ BasicTime.PulsesToSeconds[BasicTime.GetClockPulses[]] ]; }; GetContext: PROC[] RETURNS[REF ThreeDBasics.Context] ~ { context: REF ThreeDBasics.Context; renderMode: ATOM; display: Pixels.PixelBuffer; on, onLeft, gray: BOOLEAN; bpp, bppB: CARDINAL; monitorType: Rope.ROPE; [on, onLeft, gray, bpp, bppB, monitorType] _ ColorDisplay.GetColorDisplayStatus[]; IF on THEN WindowManager.StopColorViewers[]; -- get rid of conflicting users of color display IF bpp < 8 THEN bpp _ 8; ColorDisplay.SetColorDisplayStatus[ on: TRUE, onLeft: onLeft, gray: FALSE, bpp: bpp, monitorType: monitorType ]; display _ Pixels.GetFromTerminal[vt: Terminal.Current[], alpha: FALSE, depth: TRUE]; SELECT display.samplesPerPixel FROM 2 => renderMode _ $PseudoClr; 4 => renderMode _ $Dorado24; ENDCASE => ThreeDScenes.Error[[$MisMatch, "Strange Error??"]]; context _ ThreeDScenes.Create[ width: 0, height: 0, renderMode: renderMode, alpha: FALSE, depth: TRUE ]; context.display _ display; ThreeDScenes.SetViewPort[context, [0.0, 0.0, context.display.width, context.display.height] ]; ThreeDScenes.SetWindow[context, ThreeDScenes.WindowFromViewPort[context.viewPort] ]; [] _ ThreeDScenes.SetLight[context, "Initial", [-100., -200., 50.] ]; ThreeDScenes.SetView[ context, [0.0, -10.0, 3.0], [0.0, 0.0, 0.0] ]; RETURN[context]; }; Render3dSceneProc: Commander.CommandProc ~ { <> context: REF ThreeDBasics.Context _ GetContext[ ! ThreeDScenes.Error => GO TO GiveUp ]; fileName: Rope.ROPE _ Rope.Substr[ base: cmd.commandLine, start: 1, len: Rope.Index[cmd.commandLine, 0, "\n"] - 1 ]; ThreeDMisc.MakeFrameFromFile[context, fileName]; EXITS GiveUp => NULL }; Render3dShapeProc: Commander.CommandProc ~ { <> context: REF ThreeDBasics.Context _ GetContext[]; ok: BOOL; shapeFile, x, y, z, fr, fg, fb, sr, sg, sb: Args.Arg; [ok, shapeFile, x, y, z, fr, fg, fb, sr, sg, sb] _ Args.ArgsGet[cmd, "%s-from%rrr-faceted%rrr-smooth%rr"]; IF NOT ok THEN SIGNAL ThreeDScenes.Error[[$MisMatch, "command line bad"]]; IF NOT shapeFile.ok THEN SIGNAL ThreeDScenes.Error[[$MisMatch, "no shape to render"]]; IF x.ok AND y.ok AND z.ok THEN ThreeDScenes.SetView[context, [x.real, y.real, z.real], [0.0, 0.0, 0.0] ]; ThreeDMisc.AddShapeAt[context, "Shape", shapeFile.rope, [0.,0.,0.]]; IF fr.ok AND fg.ok AND fb.ok THEN ThreeDMisc.SetFacetedColor[ context, "Shape", [fr.real, fg.real, fb.real] ] ELSE IF sr.ok AND sg.ok AND sb.ok THEN ThreeDMisc.SetSmoothColor[ context, "Shape", [sr.real, sg.real, sb.real] ] ELSE ThreeDMisc.SetSmoothColor[ context, "Shape", [1.0, 0.8, 0.2] ]; ThreeDMisc.MakeFrame[context]; }; RenderFromStreamProc: Commander.CommandProc ~ { <> <> startTime, lastTime: REAL _ CurrentTime[]; procTime: BasicTime.GMT _ BasicTime.Now[]; scanSeg: REF Pixels.SampleSetSequence; displaycontext: REF ThreeDBasics.Context; context: REF ThreeDBasics.Context _ ThreeDScenes.Create[ 0, 0, $FullClr, TRUE]; serverDelay: INT _ BasicTime.Period[ Convert.TimeFromRope[cmd.commandLine], procTime ]; IF serverDelay > 0 AND serverDelay < 3600 THEN msg _ Rope.Cat[" delay: ", Convert.RopeFromInt[ serverDelay], " s. " ]; ThreeDScenes.ReadScene[context, cmd.in]; displaycontext _ ThreeDScenes.Create[ -- get display bits of proper size width: Ceiling[context.viewPort.w], height: Ceiling[context.viewPort.h], renderMode: $FullClr, alpha: TRUE ]; context.display _ displaycontext.display; -- give display bits to context ThreeDScenes.SetEyeSpace[context]; -- update for actual display size msg _ Rope.Cat[msg, " set-up: ", ElapsedTime[startTime] ]; lastTime _ CurrentTime[]; ThreeDMisc.MakeFrame[context]; -- render image msg _ Rope.Cat[msg, " rendering: ", ElapsedTime[lastTime] ]; lastTime _ CurrentTime[]; <> FOR y: NAT IN [0 .. Ceiling[context.viewPort.h] ) DO scanSeg _ Pixels.GetScanSeg[context.display, 0, y, Ceiling[context.viewPort.w], scanSeg]; FOR i: NAT IN [0.. context.display.samplesPerPixel) DO TRUSTED { IO.UnsafePutBlock[ -- uses 16 bits per byte (wasting net bandwidth) self: cmd.out, block: [ base: LOOPHOLE[SampleMapOps.GetPointer[scanSeg[i], 0, scanSeg[i].length]], count: 2*scanSeg[i].length ] ]; }; ENDLOOP; ENDLOOP; msg _ Rope.Cat[msg, " output: ", ElapsedTime[lastTime], " total: ", ElapsedTime[startTime] ]; context _ displaycontext _ NIL; -- kill off everything, no state saved }; Init: PROC ~ { ComputeServerServer.Register[ key: "Render3dFromStream", proc: RenderFromStreamProc ]; Commander.Register[ key: "RenderFromStream", proc: RenderFromStreamProc ]; Commander.Register[ key: "Render3dScene", proc: Render3dSceneProc ]; Commander.Register[ key: "Render3dShape", proc: Render3dShapeProc ]; }; Init[]; END.