<> <> <> <> <> DIRECTORY Atom, CedarProcess, Commander, G3dBasic, G3dMappedAndSolidTexture, G3dMatrix, G3dRender, G3dRenderWithPixels, G3dShadeClipXfm, G3dShape, G3dSortandDisplay, G3dView, ImagerColorFns, ImagerColorMap, IO, NamedColors, Real, Rope, RuntimeError, SafeStorage, ViewerOps; G3dRenderImpl: CEDAR MONITOR IMPORTS Atom, CedarProcess, Commander, G3dMappedAndSolidTexture, G3dMatrix, G3dRender, G3dRenderWithPixels, G3dShadeClipXfm, G3dShape, G3dSortandDisplay, G3dView, ImagerColorFns, ImagerColorMap, NamedColors, Rope, RuntimeError, SafeStorage, ViewerOps EXPORTS G3dRender ~ BEGIN <> Error: PUBLIC SIGNAL [code: ATOM, reason: ROPE] = CODE; <> <> PropList: TYPE ~ Atom.PropList; STREAM: TYPE ~ IO.STREAM; ROPE: TYPE ~ Rope.ROPE; Process: TYPE ~ CedarProcess.Process; <> NatSequence: TYPE ~ G3dBasic.NatSequence; NatSequenceRep: TYPE ~ G3dBasic.NatSequenceRep; PairSequence: TYPE ~ G3dBasic.PairSequence; TripleSequence: TYPE ~ G3dBasic.TripleSequence; <> RGB: TYPE ~ G3dRender.RGB; <> Pair: TYPE ~ G3dBasic.Pair; Triple: TYPE ~ G3dBasic.Triple; Quad: TYPE ~ G3dBasic.Quad; -- RECORD [x, y, z, w: REAL]; Matrix: TYPE ~ G3dMatrix.Matrix; -- REF 4 by 4 ARRAY OF REAL <> SampleMap: TYPE ~ G3dRender.SampleMap; PixelMap: TYPE ~ G3dRender.PixelMap; Box: TYPE ~ G3dRender.Box; -- [min, max: Pair] Rectangle: TYPE ~ G3dRender.Rectangle; -- RECORD [x, y, w, h: REAL] <> NatTable: TYPE ~ G3dBasic.NatTable; NatTableRep: TYPE ~ G3dBasic.NatTableRep; <> TextureFunction: TYPE ~ G3dRender.TextureFunction; TextureMap: TYPE ~ G3dRender.TextureMap; SummedTexture: TYPE ~ G3dRender.SummedTexture; TextureStyle: TYPE ~ G3dRender.TextureStyle; TextureInfo: TYPE ~ G3dRender.TextureInfo; <> CtlPoint: TYPE ~ G3dRender.CtlPoint; <> Shape: TYPE ~ G3dShape.Shape; ShapeRep: TYPE ~ G3dShape.ShapeRep; ShapeSequence: TYPE ~ G3dShape.ShapeSequence; ShapeSequenceRep: TYPE ~ G3dShape.ShapeSequenceRep; Vertex: TYPE ~ G3dShape.Vertex; VertexRep: TYPE ~ G3dShape.VertexRep; VertexSequenceRep: TYPE ~ G3dShape.VertexSequenceRep; PatchSequence: TYPE ~ G3dRender.PatchSequence; ShapeClass: TYPE ~ G3dRender.ShapeClass; ShadingClass: TYPE ~ G3dRender.ShadingClass; ShapeProc: TYPE ~ G3dRender.ShapeProc; RenderStyle: TYPE ~ G3dRender.RenderStyle; <> Context: TYPE ~ G3dRender.Context; ContextRep: TYPE ~ G3dRender.ContextRep; ContextClass: TYPE ~ G3dRender.ContextClass; RenderData: TYPE ~ G3dRender.RenderData; DisplayMode: TYPE ~ G3dRender.DisplayMode; <> Transform: PROC [p: Triple, mat: Matrix] RETURNS [Triple] ~ G3dMatrix.Transform; TransformVec: PROC [vec: Triple, mat: Matrix] RETURNS [Triple] ~ G3dMatrix.TransformVec; 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; <> registeredDisplayTypes: PropList _ NIL; -- keeps active display types registeredSurfaceTypes: PropList _ NIL; -- keeps active surface types registeredShadingClasses: PropList _ NIL; -- keeps active shading classes <> RegisterDisplayClass: PUBLIC PROC [class: ContextClass, type: ATOM] ~ { registeredDisplayTypes _ PutProp[registeredDisplayTypes, type, NEW[ContextClass _ class]]; }; GetDisplayClass: PUBLIC PROC [type: ATOM] RETURNS [class: ContextClass] ~ { refClass: REF ContextClass _ NARROW[GetProp[registeredDisplayTypes, type]]; IF refClass # NIL THEN class _ refClass^ ELSE G3dRender.Error[$Unimplemented, "Unregistered display type"] }; LoadDisplayClass: PUBLIC PROC [context: Context, type: ATOM] ~ { class: REF ContextClass _ NARROW[GetProp[registeredDisplayTypes, type]]; IF class = NIL THEN G3dRender.Error[$Unimplemented, "Unregistered display type"]; context.class _ NEW[ContextClass _ class^]; context.pixels _ NIL; --this and next line for saving VM context.displayProps _ Atom.RemPropFromList[context.displayProps, $FullDisplayMemory]; context.class.setUpDisplayType[context]; -- maps in pixels, sets up color map IF GetProp[context.props, $BufferContext] # NIL THEN { G3dRender.Error[$Warning, "Dropping Buffer context"]; -- insufficient info to update context.props _ Atom.RemPropFromList[context.props, $BufferContext]; }; WITH GetProp[context.props, $BackGround] SELECT FROM backGrdCtx: Context => { G3dRender.Error[$Warning, "Dropping BackGround context"]; -- no info for update context.props _ Atom.RemPropFromList[context.props, $BackGround]; }; ENDCASE; }; RegisterShapeClass: PUBLIC PROC [class: ShapeClass, type: ATOM] ~ { registeredSurfaceTypes _ PutProp[registeredSurfaceTypes, type, NEW[ShapeClass _ class]]; }; GetShapeClass: PUBLIC PROC [type: ATOM] RETURNS [class: ShapeClass] ~ { refClass: REF ShapeClass _ NARROW[GetProp[registeredSurfaceTypes, type]]; IF refClass # NIL THEN class _ refClass^ ELSE G3dRender.Error[$Unimplemented, "Unregistered surface type"]; }; LoadShapeClass: PUBLIC PROC [shape: Shape, type: ATOM _ $ConvexPolygon] ~{ shapeClass: REF ShapeClass; class: REF ShapeClass _ NARROW[GetProp[registeredSurfaceTypes, type]]; IF class = NIL THEN G3dRender.Error[$Unimplemented, "Unregistered surface type"]; shapeClass _ ShapeClassFrom[shape]; IF shapeClass = NIL THEN shapeClass _ NEW[ShapeClass _ class^] ELSE { -- inherit previous procedures if no replacements new: REF ShapeClass _ NEW[ShapeClass _ class^]; IF new.validate = NIL THEN new.validate _ shapeClass.validate; IF new.display = NIL THEN new.display _ shapeClass.display; IF new.displayPatch = NIL THEN new.displayPatch _ shapeClass.displayPatch; IF new.doBeforeFrame = NIL THEN new.doBeforeFrame _ shapeClass.doBeforeFrame; shapeClass _ new; }; IF ShadingClassFrom[shape] = NIL THEN LoadShadingClass[shape]; -- load default class shape.renderValid _ FALSE; -- in case we're changing the type on an existing shape shape.screenValid _ FALSE; shape.props _ Atom.RemPropFromList[shape.props, $LinesList]; -- list may not be valid }; RegisterShadingClass: PUBLIC PROC [class: ShadingClass, type: ATOM] ~ { registeredShadingClasses _ PutProp[registeredShadingClasses, type, NEW[ShadingClass _class]]; }; GetShadingClass: PUBLIC PROC [type: ATOM] RETURNS [class: ShadingClass] ~ { ref: REF ShadingClass _ NARROW[GetProp[registeredShadingClasses, type]]; IF ref # NIL THEN class _ ref^ ELSE G3dRender.Error[$Unimplemented, "Unregistered shading class"]; }; LoadShadingClass: PUBLIC PROC [shape: Shape, type: ATOM _ $Default ] ~ { shadingClass: REF ShadingClass; class: REF ShadingClass _ NARROW[GetProp[registeredShadingClasses, type]]; IF class = NIL THEN G3dRender.Error[$Unimplemented, "Unregistered shading class"]; shadingClass _ ShadingClassFrom[shape]; IF shadingClass = NIL THEN shadingClass _ NEW[ShadingClass _ class^] ELSE { new: REF ShadingClass _ NEW[ShadingClass _ class^]; IF new.renderMethod = NIL THEN new.renderMethod _ shadingClass.renderMethod; new.color _ shadingClass.color; new.shininess _ shadingClass.shininess; new.transmittance _ shadingClass.transmittance; IF new.texture = NIL THEN new.texture _ shadingClass.texture; new.textureScale _ shadingClass.textureScale; new.bumpScale _ shadingClass.bumpScale; IF new.cnvrtVtx = NIL THEN new.cnvrtVtx _ shadingClass.cnvrtVtx; IF new.getColor = NIL THEN new.getColor _ shadingClass.getColor; IF new.shadeVtx = NIL THEN new.shadeVtx _ shadingClass.shadeVtx; shadingClass _ new; }; NARROW[shape.renderData, REF RenderData].shadingProps _ NIL; -- WHY??? }; InitStandardShapeClasses: PROC[] ~ { -- register procedures for basic surface types standardClass: ShapeClass _ [ type: $Light, display: NIL, displayPatch: NIL ]; defaultShadingClass: ShadingClass _ [ -- procs for standard shading (no texture) type: $Default, renderMethod: $Faceted, shadeVtx: G3dShadeClipXfm.ShadeVtx ]; G3dRender.RegisterShapeClass[standardClass, $Light]; -- placeholder class for light source standardClass.type _ $ConvexPolygon; standardClass.validate _ G3dSortandDisplay.ValidatePolyhedron; standardClass.displayPatch _ G3dSortandDisplay.OutputPolygon; G3dRender.RegisterShapeClass[standardClass, $ConvexPolygon]; -- ConvexPolygon procs standardClass.type _ $RopeShape; standardClass.validate _ G3dSortandDisplay.ValidateRopeShape; standardClass.displayPatch _ G3dSortandDisplay.RopeDisplay; G3dRender.RegisterShapeClass[standardClass, $RopeShape]; -- RopeShape procs G3dRender.RegisterShadingClass[defaultShadingClass, $Default]; defaultShadingClass.type _ $NoShading; defaultShadingClass.renderMethod _ $Faceted; defaultShadingClass.shadeVtx _ G3dShadeClipXfm.NoShadeVtx; G3dRender.RegisterShadingClass[defaultShadingClass, $NoShading]; }; <> Create: PUBLIC PROC [] RETURNS [Context] ~ { context: Context _ NEW[ContextRep]; wDir: ROPE _ Commander.PrependWorkingDir[" "]; -- add needed space (wierdness) wDir _ Rope.Substr[base: wDir, len: Rope.Length[wDir] - 1]; -- drop space context.props _ PutProp[context.props, $WDir, wDir]; -- keep directory context.eyeSpaceXfm _ G3dMatrix.Identity[]; -- can't do this in initialization, so do it here context.stopMe _ NEW[BOOLEAN _ FALSE]; RETURN[context]; }; InitializeRawColorDisplayContext: PUBLIC PROC [ antiAliasing: BOOL _ TRUE, background: RGB _ [0.2, 0.2, 0.7], displayMode: DisplayMode _ gray] RETURNS [context: Context] ~ { context _ Create[]; context.preferredRenderMode _ $Pixels; LoadDisplayClass[context, AtomFromDisplayMode[displayMode]]; G3dRenderWithPixels.BufferRendering[context, FALSE]; -- , displayType = $FullColor]; SetAntiAliasing[context, antiAliasing]; SetBackgroundColor[context, background]; AddLight[context, "Light0", [-100.0, -200.0, 20.0]]; SetView[context, [3.0, -10.0, 3.0], []]; }; CloseDisplay: PUBLIC PROC [context: Context] ~ { context.pixels _ NIL; -- throw away buffer bits context.displayProps _ Atom.RemPropFromList[context.displayProps, $FullDisplayMemory]; ImagerColorMap.SetStandardColorMap[context.terminal -- restore standard color map ! RuntimeError.BoundsFault => CONTINUE]; }; CloseColorViewers: PUBLIC PROC ~ { EnumProc: ViewerOps.EnumProc ~ { IF v.column = color THEN { ViewerOps.CloseViewer[v]; ViewerOps.ChangeColumn[v, left]; }; }; ViewerOps.EnumerateViewers[EnumProc]; }; KillUntitledColorViewers: PUBLIC PROC ~ { EnumProc: ViewerOps.EnumProc ~ { IF v.column = color AND v.name = NIL THEN ViewerOps.DestroyViewer[v]; }; ViewerOps.EnumerateViewers[EnumProc]; }; GetTmpContext: PUBLIC PROC [srcCtx: REF Context] RETURNS[dstCtx: REF Context] ~ { <> dstCtx _ ThreeDBasics.Create[]; CopyContextData[dstCtx, srcCtx]; dstCtx.pixels _ srcCtx.pixels; }; CopyContextData: PUBLIC PROC [dstCtx, srcCtx: REF Context] ~ { dstCtx.class _ IF srcCtx.class # NIL THEN NEW[ ContextClass _ srcCtx.class^ ] ELSE NIL; dstCtx.stopMe _ srcCtx.stopMe; -- inheriting REF so Stop signals will propagate dstCtx.frameNumber _ srcCtx.frameNumber; dstCtx.shapes _ srcCtx.shapes; dstCtx.visibleShapes _ srcCtx.visibleShapes; dstCtx.lightSources _ srcCtx.lightSources; dstCtx.environment _ srcCtx.environment; dstCtx.viewInValid _ srcCtx.viewInValid; dstCtx.eyePoint _ srcCtx.eyePoint; dstCtx.ptOfInterest _ srcCtx.ptOfInterest; dstCtx.rollAngle _ srcCtx.rollAngle; dstCtx.upDirection _ srcCtx.upDirection; dstCtx.fieldOfView _ srcCtx.fieldOfView; dstCtx.window _ srcCtx.window; dstCtx.hitherLimit _ srcCtx.hitherLimit; dstCtx.yonLimit _ srcCtx.yonLimit; dstCtx.clippingPlanes _ srcCtx.clippingPlanes; dstCtx.eyeSpaceXfm _ srcCtx.eyeSpaceXfm; dstCtx.eyeToNdc _ srcCtx.eyeToNdc; dstCtx.ndcToPixels _ srcCtx.ndcToPixels; IF srcCtx.viewer # NIL THEN { dstCtx.viewer _ NEW[ViewerClasses.ViewerRec _ srcCtx.viewer^]; FOR list: Atom.PropList _ srcCtx.viewer.props, list.rest UNTIL list = NIL DO -- new proplist element: Atom.DottedPair _ NEW[Atom.DottedPairNode _ list.first^]; dstCtx.viewer.props _ CONS[element, dstCtx.viewer.props]; ENDLOOP; dstCtx.viewer.props _ PutProp[ dstCtx.viewer.props, $Context3D, dstCtx ]; }; dstCtx.terminal _ srcCtx.terminal; dstCtx.displayInValid _ srcCtx.displayInValid; <> dstCtx.viewPort _ IF srcCtx.viewPort # NIL THEN NEW[ Imager.Rectangle _ srcCtx.viewPort^] ELSE NIL; dstCtx.preferredViewPort _ srcCtx.preferredViewPort; dstCtx.extentCovered _ srcCtx.extentCovered; dstCtx.preferredRenderMode _ srcCtx.preferredRenderMode; dstCtx.displayProps _ NIL; FOR list: Atom.PropList _ srcCtx.displayProps, list.rest UNTIL list = NIL DO -- new proplist element: Atom.DottedPair _ NEW[Atom.DottedPairNode _ list.first^]; dstCtx.displayProps _ CONS[element, dstCtx.displayProps]; ENDLOOP; dstCtx.autoRedraw _ srcCtx.autoRedraw; dstCtx.delayClear _ srcCtx.delayClear; dstCtx.doVisibly _ srcCtx.doVisibly; dstCtx.antiAliasing _ srcCtx.antiAliasing; dstCtx.depthBuffering _ srcCtx.depthBuffering; dstCtx.depthResolution _ srcCtx.depthResolution; dstCtx.sortSequence _ srcCtx.sortSequence; dstCtx.props _ NIL; FOR list: Atom.PropList _ srcCtx.props, list.rest UNTIL list = NIL DO -- make new proplist element: Atom.DottedPair _ NEW[Atom.DottedPairNode _ list.first^]; dstCtx.props _ CONS[element, dstCtx.props]; ENDLOOP; }; CopyContextShapes: PUBLIC PROC [dstCtx, srcCtx: REF Context] ~ { dstCtx.shapes _ NEW[ ShapeSequence[srcCtx.shapes.length] ]; FOR i: NAT IN [0..srcCtx.shapes.length) DO dstCtx.shapes[i] _ NEW[ ShapeInstance _ srcCtx.shapes[i]^ ]; dstCtx.shapes[i].shadingClass _ NEW[ ShadingClass _ srcCtx.shapes[i].shadingClass^ ]; ENDLOOP; dstCtx.shapes.length _ srcCtx.shapes.length; }; <> SetViewFromParameters: PUBLIC PROC [ context: Context, fieldOfView: REAL _ 40.0, scale: REAL _ 1.0, moves, rotates: Triple _ []] ~ { fov: REAL _ IF fieldOfView = 0.0 THEN 40.0 ELSE fieldOfView; eyePoint, lookAt, upDirection: Triple; [eyePoint, lookAt, upDirection] _ G3dView.FromScaleMovesRots[scale, moves, rotates]; SetView[context, eyePoint, lookAt, fov, 0.0, upDirection]; }; SetView: PUBLIC PROC [ context: Context, eyePoint: Triple, lookAt: Triple, fieldOfView: REAL _ 40.0, rollAngle: REAL _ 0.0, upDirection: Triple _ [0., 0., 1.], hitherLimit: REAL _ .01, yonLimit: REAL _ 1000.0] ~ { context.eyePoint _ eyePoint; context.lookAt _ lookAt; context.fieldOfView _ fieldOfView; context.rollAngle _ rollAngle; context.upDirection _ upDirection; context.hitherLimit _ hitherLimit; context.yonLimit _ yonLimit; context.changed _ TRUE; }; SetViewPort: PUBLIC PROC [context: Context, size: Rectangle] ~{ IF size.w <= 0.0 OR size.h <= 0.0 THEN SIGNAL Error[$MisMatch, "Null rectangle"]; context.preferredViewPort _ size; context.viewPort _ NIL; -- computed by ValidateView GetViewportFromViewer context.window _ NIL; -- resizing viewport forces update of window context.displayInValid _ TRUE; }; <> SetAmbientLight: PUBLIC PROC [context: Context, rgb: RGB] ~ { IF context # NIL THEN { ref: REF RGB _ NEW[RGB _ rgb]; context.environment _ PutProp[context.environment, $AmbientLight, ref]; context.changed _ TRUE; }; }; NameAmbientLight: PUBLIC PROC [context: Context, color: ROPE] ~ { clr: RGB _ ImagerColorFns.RGBFromHSL[NamedColors.RopeToHSL[color]]; SetAmbientLight[context, clr]; }; GetAmbientLight: PUBLIC PROC [context: Context] RETURNS [rgb: RGB] ~ { IF context # NIL THEN { refAny: REF ANY _ GetProp[context.environment, $AmbientLight]; rgb _ IF refAny = NIL THEN [0.0, 0.0, 0.0] ELSE NARROW[refAny, REF RGB]^; }; }; AddLight: PUBLIC PROC [context: Context, name: ROPE, position: Triple, color: RGB _ [1,1,1]] ~ { light: Shape _ FindShape[context, name]; IF light = NIL THEN { light _ NEW [ShapeRep]; -- name not used before, make new light light.name _ name; LoadShapeClass[light, $Light]; -- load light class structures AddShape[context, light]; }; light.position _ position; light.sphereExtent _ [ center: [0.0, 0.0, 0.0], radius: 2 * 93000000.0 * 1609.344 -- twice solar distance in meters ]; ShadingClassFrom[light].color _ color; light.props _ PutProp[light.props, $Hidden, $ok]; -- hide from display routines G3dShape.ComputeMatrix[light]; -- make sure matrix is valid context.changed _ TRUE; }; DeleteLight: PUBLIC PROC [context: Context, name: ROPE] ~ { DeleteShape[context, name]; context.changed _ TRUE; }; <> NameBackgroundColor: PUBLIC PROC [context: Context, color: ROPE] ~ { <> bkgrdColor: RGB _ ImagerColorFns.RGBFromHSL[NamedColors.RopeToHSL[color]]; SetBackgroundColor[context, bkgrdColor]; -- set color }; SetBackgroundColor: PUBLIC PROC [context: Context, color: RGB] ~ { <> context.props _ PutProp[context.props, $BackGround, NEW[RGB _ color]]; }; GetBackgroundColor: PUBLIC PROC [context: Context] RETURNS [rgb: RGB] ~ { <> WITH GetProp[context.props, $BackGround] SELECT FROM x: REF RGB => rgb _ x^; ENDCASE; }; SetBackgroundImage: PUBLIC PROC [context: Context, aisFile: ROPE] ~ { <> bkGrdCtx: Context _ Create[]; bkGrdCtx.depthBuffering _ context.depthBuffering; bkGrdCtx.antiAliasing _ context.antiAliasing; bkGrdCtx.class _ context.class; bkGrdCtx.props _ PutProp[bkGrdCtx.props, $BackGrdImage, aisFile]; SetBackgroundContext[context, bkGrdCtx]; }; GetBackgroundImage: PUBLIC PROC [context: Context] RETURNS [r: ROPE _ NIL] ~ { <> WITH GetProp[context.props, $BackGround] SELECT FROM bkGrdCtx: Context => { name: REF ANY _ GetProp[bkGrdCtx.props, $BackGrdImage]; IF name # NIL THEN r _ NARROW[name]; }; ENDCASE; }; SetBackgroundContext: PUBLIC PROC [context, bkGrdCtx: Context] ~ { <> context.props _ PutProp[context.props, $BackGround, bkGrdCtx]; }; KillBackground: PUBLIC PROC [context: Context] ~ { <> context.props _ Atom.RemPropFromList[context.props, $BackGround]; }; <<>> <> AddShape: PUBLIC PROC [context: Context, shape: Shape] ~ { IF shape = NIL THEN RETURN; DeleteShape[context, shape.name ! G3dRender.Error => CONTINUE]; context.shapes _ G3dShape.AddToShapeSequence[context.shapes, shape]; }; AddShapeFromFile: PUBLIC PROC [ context: Context, shapeName: ROPE, fileName: ROPE, position: Triple _ [0., 0., 0.]] ~ { shape, cloneShape: Shape _ NIL; fileName _ PrependWorkingDirectory[context, fileName]; IF context.shapes # NIL THEN FOR i: NAT IN [0..context.shapes.length) DO IF Rope.Equal[shape.fileName, context.shapes[i].fileName] -- same data as another shape? THEN cloneShape _ context.shapes[i]; ENDLOOP; IF cloneShape # NIL -- save data reads if previously read THEN G3dShape.CloneShape[shape, cloneShape] ELSE shape _ G3dShape.ShapeFromFile[fileName]; shape.name _ shapeName; shape.fileName _ fileName; AddShape[context, shape]; G3dShape.TransformShape[shape: shape, translate: position]; }; FindShape: PUBLIC PROC [context: Context, shapeName: ROPE] RETURNS [shape: Shape _ NIL] ~ { IF context # NIL THEN shape _ G3dShape.FindShape[context.shapes, shapeName ! G3dShape.Error => CONTINUE]; }; ShapeFromRope: PUBLIC PROC [ name: ROPE _ NIL, message: ROPE, color: ROPE _ NIL, size: REAL _ 0.5, font: ROPE _ NIL] RETURNS [Shape] ~ { shape: Shape _ NEW[ShapeRep]; renderData: REF RenderData _ NEW[RenderData]; renderData.fixedProps _ PutProp[renderData.fixedProps, $RopeMessage, message]; renderData.fixedProps _ PutProp[renderData.fixedProps, $RopeFont, font]; shape.renderData _ renderData; LoadShapeClass[shape, $RopeShape]; LoadShadingClass[shape, $NoShading]; renderData.shadingClass.color _ ImagerColorFns.RGBFromHSL[NamedColors.RopeToHSL[color]]; <> shape.vertices _ NEW[VertexSequenceRep[2]]; shape.vertices[0] _ NEW[VertexRep]; shape.vertices[1] _ NEW[VertexRep]; shape.vertices[1].point.z _ size; shape.vertices.length _ 2; shape.surfaces _ NEW[NatTableRep[1]]; shape.surfaces[0] _ NEW[NatSequenceRep[3]]; shape.surfaces[0][0] _ shape.surfaces[0][2] _ 0; shape.surfaces[0][1] _ 1; shape.surfaces.length _ 1; RETURN[shape]; }; ChangeRopeMessage: PUBLIC PROC [context: Context, shapeName: ROPE, newMessage: ROPE] ~ { shape: Shape _ FindShape[context, shapeName]; NARROW[shape.renderData, REF RenderData].fixedProps _ PutProp[ NARROW[shape.renderData, REF RenderData].fixedProps, $RopeMessage, newMessage ]; }; DeleteShape: PUBLIC PROC [context: Context, shapeName: ROPE] ~ { found: BOOL _ FALSE; IF context.shapes = NIL THEN { SIGNAL G3dRender.Error[$MisMatch, "No shapes to delete from"]; RETURN[]; }; FOR i: NAT IN [0..context.shapes.length) DO IF found THEN context.shapes[i] _ context.shapes[i+1] ELSE { found _ Rope.Equal[shapeName, context.shapes[i].name, FALSE]; IF found THEN { context.shapes[i] _ context.shapes[i+1]; context.shapes.length _ context.shapes.length - 1; }; }; ENDLOOP; IF NOT found THEN G3dRender.Error[ $MisMatch, Rope.Cat["Can't delete", shapeName, "- not there"] ]; }; DeleteAllShapes: PUBLIC PROC [context: Context] ~ { IF context # NIL THEN FOR n: NAT IN [0..context.shapes.length) DO IF NARROW[context.shapes[n].renderData, REF RenderData].class.type # $Light THEN DeleteShape[context, context.shapes[n].name ! G3dRender.Error => CONTINUE]; ENDLOOP; }; SetRenderStyle: PUBLIC PROC [shape: Shape, renderStyle: RenderStyle] ~ { shade: REF ShadingClass _ ShadingClassFrom[shape]; IF shade # NIL THEN shade.renderMethod _ NEW[RenderStyle _ renderStyle]; }; SetColor: PUBLIC PROC [shape: Shape, color: RGB] ~ { shade: REF ShadingClass _ ShadingClassFrom[shape]; IF shade # NIL THEN shade.color _ color; }; <<>> SetShininess: PUBLIC PROC [shape: Shape, shininess: REAL] ~ { shade: REF ShadingClass _ ShadingClassFrom[shape]; IF shade # NIL THEN shade.shininess _ shininess; }; SetTransmittance: PUBLIC PROC [shape: Shape, transmittance: REAL] ~ { shade: REF ShadingClass _ ShadingClassFrom[shape]; IF shade # NIL THEN shade.transmittance _ transmittance; }; SetInvisible: PUBLIC PROC [shape: Shape] ~ { NARROW[shape.renderData, REF RenderData].props _ PutProp[ NARROW[shape.renderData, REF RenderData].props, $Hidden, $ok ]; }; SetVisible: PUBLIC PROC [shape: Shape] ~ { NARROW[shape.renderData, REF RenderData].props _ Atom.RemPropFromList[ NARROW[shape.renderData, REF RenderData].props, $Hidden ]; }; ShowBackfaces: PUBLIC PROC [shape: Shape] ~ { IF shape # NIL THEN shape.showBackfaces _ TRUE; }; <<>> HideBackfaces: PUBLIC PROC [shape: Shape] ~ { IF shape # NIL THEN shape.showBackfaces _ FALSE; }; RenderDataFrom: PUBLIC PROC [shape: Shape] RETURNS [REF RenderData] ~ { data: REF RenderData; IF shape.renderData = NIL THEN shape.renderData _ NEW[RenderData]; data _ NARROW[shape.renderData]; RETURN[data]; }; ShapeClassFrom: PUBLIC PROC [shape: Shape] RETURNS [REF ShapeClass] ~ { <> data: REF RenderData _ RenderDataFrom[shape]; IF data.class = NIL THEN data.class _ NEW[ShapeClass]; RETURN[data.class]; }; ShadingClassFrom: PUBLIC PROC [shape: Shape] RETURNS [REF ShadingClass] ~ { <> data: REF RenderData _ RenderDataFrom[shape]; IF data.shadingClass = NIL THEN data.shadingClass _ NEW[ShadingClass]; RETURN[data.shadingClass]; }; PatchesFrom: PUBLIC PROC [shape: Shape] RETURNS [PatchSequence] ~ { <> data: REF RenderData _ RenderDataFrom[shape]; RETURN[data.patch]; }; <> SetTextureMap: PUBLIC PROC [ context: Context, shapeName: ROPE, aisName: ROPE, textureStyle: TextureStyle _ intensity, textureFiltering: BOOL _ FALSE] RETURNS [error: ROPE] ~ { a: ATOM ~ AtomFromTextureStyle[textureStyle]; IF shapeName = NIL THEN RETURN; <> <> IF textureStyle = none THEN G3dMappedAndSolidTexture.RemoveAllTexture[context, shapeName] ELSE IF aisName # NIL THEN { ENABLE G3dRender.Error => {error _ reason; CONTINUE}; m: REF TextureMap _ G3dMappedAndSolidTexture.TextureFromAIS[context, aisName, a]; shape: Shape _ FindShape[context, shapeName]; <> IF shape # NIL THEN SetTextureRange[shape, [1000., 1000.]]; G3dMappedAndSolidTexture.AddMappedTexture[context, shapeName, m]; IF textureFiltering THEN G3dMappedAndSolidTexture.SumAllMappedTextures[context, shapeName]; }; }; OffsetTextureCoords: PUBLIC PROC [shape: Shape, offset: Pair] ~ { ps: PairSequence _ NARROW[GetProp[ NARROW[shape.renderData, REF RenderData].shadingProps, $AuxiliaryVtxData ]]; FOR i: NAT IN [0..ps.length) DO p: Pair _ ps[i]; ps[i] _ [p.x+offset.x, p.y+offset.y]; ENDLOOP; }; GetTexture: PUBLIC PROC [shape: Shape] RETURNS [PairSequence] ~ { RETURN[NARROW[GetProp[ NARROW[shape.renderData, REF RenderData].shadingProps, $AuxiliaryVtxData ]]]; }; GetTextureInfo: PUBLIC PROC [s: Shape] RETURNS [textureInfo: LIST OF TextureInfo] ~ { filtered: BOOL _ FALSE; IF s = NIL OR ShadingClassFrom[s] = NIL THEN RETURN; FOR l: LIST OF REF ANY _ ShadingClassFrom[s].texture, l.rest WHILE l # NIL DO WITH l.first SELECT FROM texture: REF G3dRender.TextureMap => { ref: REF ANY _ GetProp[texture.props, $FileName]; name: ROPE _ IF ref # NIL THEN NARROW[ref] ELSE NIL; type: TextureStyle _ SELECT texture.type FROM $Intensity => intensity, $Color => color, $Bump => bump, ENDCASE => none; WITH texture.pixels SELECT FROM x: PixelMap => filtered _ FALSE; x: REF G3dRender.SummedTexture => filtered _ TRUE; ENDCASE; textureInfo _ CONS[[name, type, filtered], textureInfo]; }; txtrFn: REF TextureFunction => -- solid or other function-based texture textureInfo _ CONS[[NIL, function, FALSE], textureInfo]; ENDCASE; ENDLOOP; }; ScaleTexture: PUBLIC PROC [context: Context, shape: Shape, scale: Pair] ~ { G3dMappedAndSolidTexture.ScaleTxtrCoords[context, shape.name, 1.0, scale.x, scale.y]; }; <> <> <> <> <> <> <> <> <<};>> <<};>> <<>> GetTextureScale: PUBLIC PROC [shape: Shape] RETURNS [scale: Pair _ [1.0, 1.0]] ~ { IF shape # NIL THEN { shade: REF ShadingClass _ ShadingClassFrom[shape]; IF shade # NIL THEN scale _ shade.textureScale; }; }; SetTextureScale: PUBLIC PROC [shape: Shape, scale: Pair _ [1.0, 1.0]] ~ { IF shape # NIL THEN { shade: REF ShadingClass _ ShadingClassFrom[shape]; IF shade # NIL THEN shade.textureScale _ scale; }; }; SetTextureRange: PUBLIC PROC [shape: Shape, textureRange: Pair] ~ { IF shape # NIL THEN NARROW[shape.renderData, REF RenderData].shadingProps _ PutProp[ NARROW[shape.renderData, REF RenderData].shadingProps, $TxtrCoordRange, NEW[Pair _ textureRange] ]; }; SetTextureFiltering: PUBLIC PROC [context: Context, shape: Shape, on: BOOL] ~ { IF shape # NIL THEN { shade: REF ShadingClass _ ShadingClassFrom[shape]; IF shade.texture = NIL THEN RETURN; IF on THEN G3dMappedAndSolidTexture.SumAllMappedTextures[context, shape.name] ELSE FOR l: LIST OF TextureInfo _ GetTextureInfo[shape], l.rest WHILE l # NIL DO [] _ SetTextureMap[context, shape.name, l.first.name, l.first.type]; ENDLOOP; }; }; GetBumpScale: PUBLIC PROC [shape: Shape] RETURNS [scale: REAL _ 1.0] ~ { IF shape # NIL THEN { shade: REF ShadingClass _ ShadingClassFrom[shape]; IF shade # NIL THEN scale _ shade.bumpScale; }; }; SetBumpScale: PUBLIC PROC [shape: Shape, scale: REAL _ 1.0] ~ { IF shape # NIL THEN { shade: REF ShadingClass _ ShadingClassFrom[shape]; IF shade # NIL THEN shade.bumpScale _ scale; }; }; <> renderDone: CONDITION; Render: PUBLIC PROC [context: Context, fork: BOOL _ TRUE] ~ { IF fork THEN { process: Process _ CedarProcess.Fork[ReallyRender, context, [background, TRUE]]; context.props _ PutProp[context.props, $Process, process]; } ELSE [] _ ReallyRender[context]; }; WaitTilRenderDone: PUBLIC ENTRY PROC ~ { ENABLE UNWIND => NULL; WAIT renderDone; }; NotRendering: PUBLIC PROC [context: Context] RETURNS [b: BOOL] ~ { process: Process _ NARROW[GetProp[context.props, $Process]]; RETURN[process = NIL OR CedarProcess.GetStatus[process] # busy]; }; BroadcastRenderDone: ENTRY PROC ~ { BROADCAST renderDone; }; ReallyRender: CedarProcess.ForkableProc ~ { context: Context _ NARROW[data]; context.class.render[context ! ABORTED => CONTINUE]; BroadcastRenderDone[]; <> < CONTINUE];>> }; AbortRender: PUBLIC PROC [context: Context] ~ { IF context # NIL THEN context.stopMe^ _ TRUE; }; GetDisplayMode: PUBLIC PROC [context: Context] RETURNS [DisplayMode] ~ { RETURN[SELECT context.class.displayType FROM $PseudoColor => dither, $Gray => gray, ENDCASE => fullColor]; }; SetAntiAliasing: PUBLIC PROC [context: Context, on: BOOL _ TRUE] ~ { <> G3dRenderWithPixels.AntiAliasing[context, on]; }; AntiAliasingNeeded: PUBLIC PROC [context: Context] RETURNS [BOOL] ~ { <> <> FOR n: NAT IN [0..context.shapes.length) DO FOR l: LIST OF TextureInfo _ GetTextureInfo[context.shapes[n]], l.rest WHILE l #NIL DO IF l.first.type = bump OR l.first.type = function THEN RETURN[TRUE]; ENDLOOP; IF ShadingClassFrom[context.shapes[n]].transmittance > 0.0 THEN RETURN[TRUE]; ENDLOOP; RETURN[FALSE]; }; <<>> GetBuffer: PUBLIC PROC [context: Context, type: ATOM] RETURNS [sm: SampleMap _ NIL] ~ { r: REF _ GetProp[context.displayProps, type]; IF r # NIL AND context.pixels # NIL THEN sm _ context.pixels[NARROW[r, REF NAT]^] }; GetAlphaBuffer: PUBLIC PROC [context: Context] RETURNS [SampleMap] ~ { RETURN[GetBuffer[context, $Alpha]]; }; GetDepthBuffer: PUBLIC PROC [context: Context] RETURNS [SampleMap] ~ { RETURN[GetBuffer[context, $Depth]]; }; <> Sqr: PROCEDURE [number: REAL] RETURNS [REAL] ~ INLINE {RETURN[number*number]; }; GetRenderData: PROCEDURE [context: Context, shapeName: ROPE] RETURNS [REF RenderData] ~ { data: REF RenderData _ NIL; IF context # NIL THEN { shape: Shape _ FindShape[context, shapeName]; IF shape # NIL THEN IF shape.renderData # NIL THEN data _ NARROW[ shape.renderData ! SafeStorage.NarrowRefFault => CONTINUE ]; }; RETURN[data]; }; PrependWorkingDirectory: PUBLIC PROC [context: Context, file: ROPE] RETURNS [ROPE]~{ wDir: ROPE _ NARROW[GetProp[context.props, $WDir]]; IF wDir = NIL THEN RETURN[file] ELSE IF file = NIL OR (Rope.Index[s1: file, s2: "/"] > 0 AND Rope.Index[s1: file, s2: "["] > 0) THEN file _ Rope.Cat[wDir, file]; -- if first char not / or [then prepend wDir RETURN[file]; }; TackOnExtension: PUBLIC PROC[file, extension: ROPE] RETURNS[ROPE] ~ { cp: FS.ComponentPositions; fullFName, fName: ROPE; [fullFName, cp, ] _ FS.ExpandName[file]; IF cp.ext.length = 0 THEN { fName _ Rope.Substr[ fullFName, 0, cp.ext.start]; RETURN[ Rope.Cat[fName, ".", extension] ]; } ELSE RETURN[ file ]; }; IntersectRectangles: PUBLIC PROC [rect1, rect2: Rectangle] RETURNS [Rectangle] ~ { intersection: Rectangle; intersection.x _ MAX[rect1.x, rect2.x]; intersection.y _ MAX[rect1.y, rect2.y]; intersection.w _ MIN[rect1.w - (intersection.x - rect1.x), rect2.w - (intersection.x - rect2.x)]; intersection.h _ MIN[rect1.h - (intersection.y - rect1.y), rect2.h - (intersection.y - rect2.y)]; RETURN [intersection]; }; AtomFromTextureStyle: PUBLIC PROC [textureStyle: TextureStyle] RETURNS [a: ATOM] ~ { a _ SELECT textureStyle FROM bump => $Bump, color => $Color, ENDCASE => $Intensity; }; AtomFromDisplayMode: PUBLIC PROC [displayMode: DisplayMode] RETURNS [a: ATOM] ~ { a _ SELECT displayMode FROM fullColor=>$FullColor, dither=>$PseudoColor, ENDCASE=>$Gray; }; RopeFromDisplayMode: PUBLIC PROC [displayMode: DisplayMode] RETURNS [ROPE] ~ { RETURN[SELECT displayMode FROM gray => "Gray", dither => "Dither", fullColor => "FullColor", ENDCASE => NIL]; }; RopeFromRenderStyle: PUBLIC PROC [renderStyle: RenderStyle] RETURNS [ROPE] ~ { RETURN[SELECT renderStyle FROM faceted => "Faceted", smooth => "Smooth", lines => "Lines", shadedLines => "ShadedLines", hiddenLines => "HiddenLines", ENDCASE => NIL]; }; RopeFromTextureStyle: PUBLIC PROC [textureStyle: TextureStyle] RETURNS [ROPE] ~ { RETURN[SELECT textureStyle FROM intensity => "Intensity", color => "Color", bump => "Bump", ENDCASE => "None"]; }; InitStandardShapeClasses[]; END.