DIRECTORY Controls, G2dBasic, G3dBasic, G3dControl, G3dLight, G3dMatrix, G3dRender, G3dShape, G3dTimeTrees, G3dTool, G3dVector, G3dView, Imager, IO, MessageWindow, Rope; G3dToolRenderImpl: CEDAR PROGRAM IMPORTS Controls, G3dControl, G3dLight, G3dMatrix, G3dRender, G3dVector, G3dView, IO, MessageWindow, Rope EXPORTS G3dTool ~ BEGIN ROPE: TYPE ~ Rope.ROPE; STREAM: TYPE ~ IO.STREAM; ClickProc: TYPE ~ Controls.ClickProc; Typescript: TYPE ~ Controls.Typescript; Pair: TYPE ~ G2dBasic.Pair; Triple: TYPE ~ G3dBasic.Triple; RealSequence: TYPE ~ G3dBasic.RealSequence; CameraControl: TYPE ~ G3dControl.CameraControl; Light: TYPE ~ G3dLight.Light; LightSequence: TYPE ~ G3dLight.LightSequence; Context3d: TYPE ~ G3dRender.Context3d; RGB: TYPE ~ G3dRender.RGB; TextureStyle: TYPE ~ G3dRender.TextureStyle; Tool: TYPE ~ G3dTool.Tool; ViewProc: TYPE ~ G3dTool.ViewProc; ShapeProc: TYPE ~ G3dShape.ShapeProc; Blink: PROC [r: ROPE] ~ { MessageWindow.Append[Rope.Concat["\t\t", r], TRUE]; MessageWindow.Blink[]; }; UpdateCamera: PUBLIC PROC [tool: Tool] ~ { moves, rots: Triple; c: Context3d ¬ tool.context3d; [moves, rots] ¬ G3dView.FromEyeLookUp[c.eyePoint, c.lookAt, c.upDirection, c.fieldOfView]; G3dControl.UpdateControl[tool.camera, tool.camera.par.xMov, moves.x]; G3dControl.UpdateControl[tool.camera, tool.camera.par.yMov, moves.y]; G3dControl.UpdateControl[tool.camera, tool.camera.par.zMov, moves.z]; G3dControl.UpdateControl[tool.camera, tool.camera.par.xRot, rots.x]; G3dControl.UpdateControl[tool.camera, tool.camera.par.yRot, rots.y]; G3dControl.UpdateControl[tool.camera, tool.camera.par.zRot, rots.z]; G3dControl.UpdateControl[tool.camera, tool.camera.scale, 1.0]; G3dControl.UpdateControl[tool.camera, tool.camera.fieldOfView, c.fieldOfView]; }; EnableClear: PUBLIC PROC [tool: Tool, on: BOOL] ~ {}; AbortButton: PUBLIC ClickProc ~ {}; SetRenderView: PUBLIC PROC [context3d: Context3d, camera: CameraControl] ~ { G3dRender.SetView[ context3d, camera.eyePoint, camera.lookAt, camera.fieldOfView.value, 0, camera.up]; context3d.view ¬ G3dMatrix.CopyMatrix[camera.matrix, context3d.view]; context3d.scale ¬ camera.scale.value; }; RenderFromCamera: PUBLIC PROC [ context3d: Context3d, context: Imager.Context, camera: CameraControl, fork: BOOL ¬ TRUE] ~ {}; RenderToFile: PUBLIC PROC [ context3d: Context3d, camera: CameraControl, fileName: ROPE, width: NAT ¬ 1024, height: NAT ¬ 768, fork: BOOL ¬ TRUE] ~ {}; SetAntiAliasing: PUBLIC PROC [tool: Tool, antiAliasing: BOOL] ~ {}; SetDepthBuffering: PUBLIC PROC [tool: Tool, depthBuffering: BOOL] ~ {}; SetNormalCoding: PUBLIC PROC [tool: Tool, normalBuffering: BOOL] ~ {}; TextureOpsButton: PUBLIC ClickProc ~ {}; SceneOpsButton: PUBLIC ClickProc ~ {}; AnimateOpsButton: PUBLIC ClickProc ~ {}; TTNode: TYPE ~ G3dTimeTrees.Node; TransformAndPropagateNode: PUBLIC PROC [node: TTNode, matrix: G3dMatrix.Matrix, order: G3dMatrix.TransformOrder] ~ {}; ChooseLight: PROC [lights: LightSequence, header: ROPE] RETURNS [choice: INT ¬ 0] ~ { l: LIST OF Controls.Request ¬ NIL; IF lights = NIL THEN RETURN; FOR n: NAT IN [1..lights.length] DO l ¬ CONS[[lights[lights.length-n].name], l]; ENDLOOP; choice ¬ Controls.PopUpRequest[[header], l]; }; GetSelectedLight: PUBLIC PROC [t: Tool] RETURNS [l: Light] ~ { IF t.selectedLight # -1 AND t.lights # NIL THEN l ¬ t.lights[t.selectedLight]; }; LightOptions: PUBLIC PROC [ lights: LightSequence, eyeView: Triple, ts: Typescript] RETURNS [LightSequence] ~ { AddLight: PROC [type: {infinite, local}] ~ { ENABLE IO.Error, IO.EndOfStream => {Blink["Bad Format"]; CONTINUE}; adjective: ROPE ¬ IF type = local THEN "local" ELSE "infinite"; s: IO.STREAM ¬ IO.RIS[Controls.TypescriptRead[ts, Rope.Concat[adjective, " light [color: r,g,b]: "]]]; name: ROPE ¬ IO.GetTokenRope[s, IO.IDProc ! IO.EndOfStream => GOTO Eof].token; position: Triple ¬ [IO.GetReal[s], IO.GetReal[s], IO.GetReal[s]]; vector: Triple ¬ G3dVector.Negate[G3dVector.Unit[position]]; r, g, b: REAL ¬ 1.0; r ¬ IO.GetReal[s ! IO.EndOfStream => CONTINUE]; g ¬ IO.GetReal[s ! IO.EndOfStream => {b ¬ g ¬ r; CONTINUE}]; b ¬ IO.GetReal[s ! IO.EndOfStream => {b ¬ g; CONTINUE}]; lights ¬ G3dLight.AddLight[lights, name, position, vector, [r, g, b]]; EXITS Eof => NULL; }; IF lights = NIL THEN lights ¬ NEW[G3dLight.LightSequenceRep[1]]; SELECT Controls.PopUpRequest[["Light Options"], LIST[ -- 1 -- [IO.PutFR1["Display lights (presently %g)", IO.rope[IF lights.drawLights THEN "on" ELSE "off"]], "List lights"], -- 2 -- ["List the lights", "List lights"], -- 3 -- ["Delete a light", "Delete a light"], -- 4 -- ["Add/Move a local light", "Add a local light"], -- 5 -- ["Add/Move an infinite light", "Add a light at infinity"], -- 6 -- ["Set ambient light", "Adjust ambient lighting (will prompt)"], -- 7 -- ["Set shadow attenuation", "0 for no attenuation, 1 for total"]]] FROM 1 => lights.drawLights ¬ NOT lights.drawLights; 2 => IF lights.length > 3 THEN G3dLight.AnnotateLightsToViewer[lights, "LightList.tioga"] ELSE Controls.TypescriptWrite[ts, G3dLight.RopeFromLights[lights]]; 3 => { n: INT ¬ ChooseLight[lights, "Delete Light"]-1; IF n >= 0 THEN G3dLight.DeleteLight[lights, lights[n].name]; }; 4 => AddLight[local]; 5 => AddLight[infinite]; 6 => { rgb: RGB ¬ [0.7, 0.7, 0.7]; r: G3dBasic.RealSequence ¬ Controls.TypescriptReadValues[ts,, LIST[["r", rgb.R], ["g", rgb.G], ["b", rgb.B]]]; lights.ambient ¬ [r[0], r[1], r[2]]; }; 7 => lights.shadowDarken ¬ Controls.GetReal[ts, "shadow darkening: ", lights.shadowDarken]; ENDCASE; RETURN[lights]; }; LightOpsButton: PUBLIC ClickProc ~ { t: Tool ¬ NARROW[clientData]; eyeView: Triple ¬ G3dControl.EyeViewFromCameraControl[t.camera]; t.lights ¬ LightOptions[t.lights, eyeView, t.typescript]; t.drawLights ¬ t.lights.drawLights; }; END. 9x G3dToolRenderImpl.mesa Copyright Σ 1985, 1992 by Xerox Corporation. All rights reserved. Bloomenthal, February 19, 1993 4:37 pm PST Heckbert, August 9, 1988 5:51:51 pm PDT Glassner, July 19, 1990 12:21:59 pm PDT Shoemake, November 23, 1989 3:43:56 am PST Wyvill, September 19, 1989 10:34:42 am PDT Crow, November 15, 1990 1:12 pm PST 3d Tool: Rendering, Texturing, Lighting Imported Types Rendering Ops RenderButton: PUBLIC ClickProc ~ {G3dTool.Repaint[NARROW[clientData], $Render]}; RenderOpsButton: PUBLIC ClickProc ~ {}; t: Tool _ NARROW[clientData]; context3d: Context3d _ G3dTool.GetFirstActiveContext3d[t]; depthBuffering: BOOL _ FALSE; IF G3dTool.Context3dOk[t] THEN { choice: INT _ Controls.PopUpRequest[["Render Ops"], LIST[ -- 1 -- ["Change Display Mode", Rope.Cat["Mode now ", G3dRender.RopeFromDisplayMode[context3d.displayMode]]], -- 2 -- Controls.BoolRequest[t.antiAliasing, "Anti Aliasing"], -- 3 -- Controls.BoolRequest[depthBuffering, "Depth Buffering"], -- 4 -- Controls.BoolRequest[context3d.clear, "Enable Clear Before Render"], -- 5 -- Controls.BoolRequest[t.normalCoding, "Normal Encoding"], -- 6 -- ["Background", "r, g, b <0..1> background color"], -- 7 -- ["Background Image", "AIS name of background picture"], -- 8 -- ["Viewport", "Set Screen Viewport"], -- 8 -- ["Render to AIS File(s)", "Render an arbitrarily sized image to ais file(s)"], -- 9 -- ["Render to RGB File", "Render arbitrarily sized image to rgb (Abekas) file"], -- 10 -- Controls.BoolRequest[t.autoRender, "Auto Rendering"], -- 11 -- Controls.BoolRequest[t.drawAxes, "Axes"], -- 12 -- Controls.BoolRequest[t.annotation, "Annotation"]]]; G3dTool.SetCursor[t, TRUE]; SELECT choice FROM 1 => context3d.displayMode _ SELECT Controls.PopUpRequest[["Render Ops"], LIST[ -- 1 -- ["Gray", "Set display mode to gray (8 bits/pixel, no color)"], -- 2 -- ["Dither", "Set display mode to dither (8 bits/pixel, with color)"], -- 3 -- ["Full Color", "Set display mode to full color (24 bits/pixel)"]]] FROM 1 => gray, 2 => dither, 3 => fullColor, ENDCASE => context3d.displayMode; 2 => SetAntiAliasing[t, t.antiAliasing _ NOT t.antiAliasing]; 3 => SetDepthBuffering[t, NOT depthBuffering]; 4 => EnableClear[t, NOT context3d.clear]; 5 => SetNormalCoding[t, NOT t.normalCoding]; 6 => SetBackground[t]; 7 => SetBackgroundImage[t]; -- 8 => SetViewport[t]; 8 => RenderImageToFile[t, ais]; 9 => RenderImageToFile[t, rgb]; 10 => t.autoRender _ NOT t.autoRender; 11 => IF (t.drawAxes _ NOT t.drawAxes) THEN KillAxes[context3d] ELSE G3dRender.AddAxes[context3d,,,, 0]; 12 => t.annotation _ NOT t.annotation; ENDCASE; G3dTool.SetCursor[t, FALSE]; IF choice = 12 THEN G3dTool.Repaint[t, $DrawOps]; }; }; KillAxes: PROC [context3d: Context3d] ~ { FOR l: LIST OF ROPE _ LIST["x", "y", "z", "x-axis", "y-axis", "z-axis"], l.rest WHILE l # NIL DO G3dRender.DeleteShape[context3d, l.first ! G3dRender.Error => CONTINUE]; ENDLOOP; }; RenderImageToFile: PROC [t: Tool, op: {ais, rgb}] ~ { Fix: PROC [r: REAL] RETURNS [i: INT] ~ {i _ Real.Fix[r]}; context3d: Context3d _ G3dTool.GetFirstActiveContext3d[t]; v: Imager.Rectangle _ context3d.viewport; w: INT _ IF op = rgb THEN 720 ELSE Fix[v.w]; h: INT _ IF op = rgb THEN 486 ELSE Fix[v.h]; prompt: ROPE _ IO.PutFR["<%g root> [width, height (defaults %g %g)]: ", IO.rope[IF op = rgb THEN "RGB (Abekas)" ELSE "AIS"], IO.int[w], IO.int[h]]; reply: ROPE _ Controls.TypescriptRead[t.typescript, prompt]; IF reply # NIL THEN { ENABLE IO.Error => {Blink["Bad Format"]; CONTINUE}; GetInt: PROC [default: INT] RETURNS [i: INT] ~ { i _ default; i _ IO.GetInt[s ! IO.EndOfStream => CONTINUE]; }; s: STREAM _ IO.RIS[reply]; name: ROPE _ FileNames.ResolveRelativePath[IO.GetTokenRope[s, IO.IDProc].token]; width: INT _ GetInt[w]; height: INT _ GetInt[h]; n: INT _ Rope.FindBackward[name, "."]+1; ext: ROPE _ IF n # 0 THEN Rope.Substr[name, n, Rope.Length[name]-n] ELSE NIL; IF ext # NIL AND (Rope.Equal[ext, "ais", FALSE] OR Rope.Equal[ext, "rgb", FALSE]) THEN name _ Rope.Substr[name, 0, n-1]; IF op = rgb THEN name _ Rope.Concat[name, ".rgb"]; RenderToFile[context3d, t.camera, name, width, height, TRUE]; }; }; Action: ViewProc _ {G3dRender.EnableClear[view.context3d, on]}; G3dTool.DoWithViews[tool, Action, FALSE]; }; SetBackground: PROC [t: Tool] ~ { Action: ViewProc _ {G3dRender.SetBackgroundColor[view.context3d, rgb]}; rgb: RGB _ G3dTool.GetFirstActiveContext3d[t].backgroundColor; reals: RealSequence _ Controls.TypescriptReadValues[t.typescript,, LIST[["r", rgb.R], ["g", rgb.G], ["b", rgb.B]]]; IF reals # NIL THEN rgb _ [reals[0], reals[1], reals[2]]; EnableClear[t, TRUE]; G3dTool.DoWithViews[t, Action, FALSE]; }; SetBackgroundImage: PROC [t: Tool] ~ { Action: ViewProc _ {G3dRender.SetBackgroundImage[view.context3d, filename]}; filename: ROPE _ Controls.TypescriptReadFileName[t.typescript]; EnableClear[t, TRUE]; IF filename # NIL THEN G3dTool.DoWithViews[t, Action, FALSE]; }; SetViewport: PROC [t: Tool] ~ { IF G3dTool.Context3dOk[t] THEN { r: REF Imager.Rectangle _ t.context3d.viewPort; reals: RealSequence; IF r = NIL THEN r _ NEW[Imager.Rectangle _ [0., 0., 640., 480.]]; reals _ Controls.TypescriptReadValues[ t.typescript,, LIST[["xmin", r.x], ["ymin", r.y], ["width", r.w], ["height", r.h]]]; IF reals # NIL AND reals.length = 4 THEN G3dRender.SetViewPort[t.context3d, [reals[0], reals[1], reals[2], reals[3]]] ELSE G3dTool.TSWrite[t, " . . . aborted."]; }; }; Action: ViewProc ~ {G3dRender.AbortRender[view.context3d]}; G3dTool.DoWithViews[NARROW[clientData], Action, FALSE]; }; FiltersNeeded: TYPE ~ RECORD [antiAliasing, textureFiltering: BOOL _ FALSE]; FilteringNeeded: PROC [tool: Tool] RETURNS [f: FiltersNeeded] ~ { IF tool.shapes # NIL THEN FOR n: NAT IN [0..tool.shapes.length) DO r: G3dRender.RenderData _ G3dRender.RenderDataFrom[tool.shapes[n]]; FOR l: LIST OF G3dRender.TextureMap _ r.textures, l.rest WHILE l # NIL DO IF l.first.style = bump THEN RETURN[[TRUE, TRUE]]; ENDLOOP; IF r.transmittance > 0.0 THEN f.antiAliasing _ TRUE; ENDLOOP; }; Render: PUBLIC PROC [tool: Tool, context: Imager.Context, fork: BOOL _ TRUE] ~ {}; Action: ViewProc ~ { IF G3dRender.IsRendering[view.context3d] THEN { Blink["Already rendering!"]; RETURN[FALSE]; }; -- r: Imager.Rectangle _ tool.context3d.preferredViewPort; -- IF ((r.x+r.w > 1024 OR r.y+r.h > 768) AND tooldisplayMode = gray) OR -- ((r.x+r.w > 640 OR r.y+r.h > 480) AND tooldisplayMode # gray) THEN { -- Blink["size too large; try RenderToFile "]; -- RETURN; -- }; RenderFromCamera[view.context3d, context, tool.camera, fork ! G3dRender.Error => {Blink[reason]; GOTO Bad}]; IF fork THEN [] _ CedarProcess.Fork[WaitAndDoPostRendering, tool, [background, TRUE]] ELSE PostRendering[tool]; EXITS Bad => NULL; }; f: FiltersNeeded _ FilteringNeeded[tool]; IF tool.timing THEN G3dTool.StartTimer[tool]; IF f.antiAliasing AND NOT tool.antiAliasing THEN { Blink["antiAliasing must be on"]; RETURN; }; IF f.textureFiltering AND NOT tool.textureFiltering THEN { Blink["texture filtering must be on"]; RETURN; }; IF tool.normalCoding AND (NOT tool.antiAliasing) THEN { Blink["To normal encode, antiAliasing must be on and background must be off"]; RETURN; }; G3dTool.DoWithViews[tool, Action]; }; WaitAndDoPostRendering: CedarProcess.ForkableProc ~ { G3dRender.WaitTilRenderDone[]; PostRendering[NARROW[data]]; }; PostRendering: PROC [tool: Tool] ~ { IF tool.annotation THEN { Print: PROC [rope: ROPE, p: Pair, color: Imager.Color _ NIL, font: ROPE _ NIL, size: REAL _ 14] ~ { context3d: Imager.Context3d _ ImagerSmoothContext3d.FromTerminal[Terminal.Current[], TRUE]; IF font = NIL THEN font _ "helvetica-mrr"; Imager.SetFont[context3d, Imager.FindFontScaled[Rope.Concat["xerox/pressfonts/", font], size]]; IF color # NIL THEN Imager.SetColor[context3d, color]; Draw2d.Label[context3d, [p.x, ImagerBackdoor.GetBounds[context3d].h-p.y], rope]; }; CRStrip: PROC [in: ROPE] RETURNS [ROPE] ~ { Translator: Rope.TranslatorType ~ {RETURN[IF old = '\n THEN Ascii.SP ELSE old]}; RETURN[Rope.Translate[in,,, Translator]]; }; h: NAT _ IF ColorDisplayManager.NextState[].resolution = standard THEN 480 ELSE 768; Print[G3dControl.CameraMessage[tool.camera], [10, h-30], Imager.black]; Print[CRStrip[G3dLight.RopeFromLights[tool.lights]], [10, h-15], Imager.black]; }; IF tool.normalCoding THEN G3dNormalCoding.EncodeAllNormals[G3dTool.GetFirstActiveContext3d[tool]]; IF tool.timing THEN G3dTool.PrintElapsedTime[tool, 0.0, "Rendering"]; }; IF G3dRender.IsRendering[context3d] THEN RETURN; SetRenderView[context3d, camera]; G3dRender.PrepareShapes[context3d.shapes]; -- causes duplicated effort, being fixed [] _ G3dRender.Render[context3d, context, fork]; }; RenderData: TYPE ~ REF RenderDataRep; RenderDataRep: TYPE ~ RECORD [ context3d: Context3d, fileName: ROPE, width, height: NAT ]; hiQ: BOOL _ TRUE; DoRenderToFile: CedarProcess.ForkableProc ~ { rd: RenderData _ NARROW[data]; c: Context3d _ G3dRender.Create[]; c.viewport _ [0, 0, rd.width, rd.height]; G3dRender.RenderToFile[c, rd.fileName]; }; renderData: RenderData _ NEW[RenderDataRep _ [context3d, fileName, width, height]]; SetRenderView[context3d, camera]; IF NOT G3dRender.IsRendering[context3d] AND fork THEN { process: CedarProcess.Process _ CedarProcess.Fork[DoRenderToFile, renderData, [background, TRUE]]; context3d.props _ Atom.PutPropOnList[context3d.props, $Process, process]; } ELSE [] _ DoRenderToFile[renderData]; }; Action: ViewProc _ {G3dRender.SetAntiAliasing[view.context3d, antiAliasing]}; G3dTool.DoWithViews[tool, Action, FALSE]; }; A: ViewProc _ {G3dRenderWithPixels.DepthBuffering[view.context3d, depthBuffering]}; G3dTool.DoWithViews[tool, A, FALSE]; }; A: ViewProc _ {G3dRenderWithPixels.NormalBuffering[view.context3d, normalBuffering]}; tool.normalCoding _ normalBuffering; G3dTool.DoWithViews[tool, A, FALSE]; }; Texture Ops TextureMap: TYPE ~ G3dRender.TextureMap; t: Tool _ NARROW[clientData]; choice: INT _ Controls.PopUpRequest[["Texture Ops"], LIST[ -- 1 -- ["Scale 2d Texture", "Scale texture coordinates of Shape (will prompt)"], -- 2 -- ["Offset 2d Texture", "Offset texture coordinates of Shape (will prompt)"], -- 3 -- ["Set Bump Factor", "Change Bump Scale Factor (default = 1.0)"], -- 4 -- Controls.BoolRequest[t.textureFiltering, "Texture Filtering"], -- 5 -- ["Set intensity texture map", "Read Texture from File, use for surface intensity"], -- 6 -- ["Set color texture map", "Read Texture from File, use for surface color"], -- 7 -- ["Set bump map", "Read Texture from File, use for bumps"], -- 8 -- ["Remove Texture Map", "Remove texture from shape"]]]; G3dTool.SetCursor[t, TRUE]; SELECT choice FROM 1 => SetTextureScale[t]; 2 => SetTextureOffset[t]; 3 => SetBumpScale[t]; 4 => ToggleTextureFiltering[t]; 5 => SetMapping[t, intensity]; 6 => SetMapping[t, color]; 7 => SetMapping[t, bump]; 8 => SetMapping[t, none]; ENDCASE; G3dTool.SetCursor[t, FALSE]; }; SetTextureOffset: PROC [t: Tool] ~ { choice: INT _ G3dTool.ChooseShape[t, "Set Texture Offset of Shape"]; IF choice # -2 THEN { Action: ShapeProc ~ {G3dRender.OffsetTextureCoords[shape, off]}; off: Pair _ GetPairFromTypescript[t, "Offset : "]; IF off = [0, 0] THEN {G3dTool.TSWrite[t, " . . . aborted."]; RETURN}; G3dTool.DoWithSelectedShapes[t.shapes, Action, choice]; }; }; GetPairFromTypescript: PROC [t: Tool, prompt: ROPE] RETURNS [out: Pair _ [0, 0]] ~ { ENABLE IO.EndOfStream, IO.Error => GOTO Bad; reply: ROPE _ Controls.TypescriptRead[t.typescript, prompt]; IF reply # NIL THEN { s: IO.STREAM _ IO.RIS[reply]; out _ [IO.GetReal[s], IO.GetReal[s]]; }; EXITS Bad => G3dTool.TSWrite[t, ". . . bad format.\n"]; }; DoWithTextureMaps: PROC [s: G3dShape.Shape, proc: PROC [m: TextureMap]] ~ { r: G3dRender.RenderData _ G3dRender.RenderDataFrom[s]; FOR l: LIST OF TextureMap _ r.textures, l.rest WHILE l # NIL DO proc[l.first]; ENDLOOP; }; SetTextureScale: PROC [t: Tool] ~ { Action: ShapeProc ~ {DoWithTextureMaps[shape, Proc]}; Proc: PROC [m: TextureMap] ~ {m.scale _ [r[0], r[1]]}; r: RealSequence; v: Pair _ [1.0, 1.0]; choice: INT _ G3dTool.ChooseShape[t, "Set Texture Scale of Shape"]; IF choice = -2 THEN RETURN; IF choice # -1 THEN { d: G3dRender.RenderData _ G3dRender.RenderDataFrom[t.shapes[choice]]; IF d.textures # NIL THEN v _ d.textures.first.scale; }; r _ Controls.TypescriptReadValues[t.typescript,, LIST[["xScale", v.x], ["yScale", v.y]]]; IF r = NIL THEN {G3dTool.TSWrite[t, " . . . aborted."]; RETURN}; G3dTool.DoWithSelectedShapes[t.shapes, Action, choice]; }; SetBumpScale: PROC [t: Tool] ~ { Action: ShapeProc ~ {DoWithTextureMaps[shape, Proc]}; Proc: PROC [m: TextureMap] ~ {m.bumpHeight _ scale}; scale: REAL _ 1.0; choice: INT _ G3dTool.ChooseShape[t, "Set Bump Scale of Shape"]; IF choice = -2 THEN RETURN; IF choice # -1 THEN { d: G3dRender.RenderData _ G3dRender.RenderDataFrom[t.shapes[choice]]; IF d.textures # NIL THEN scale _ d.textures.first.bumpHeight; }; scale _ Controls.TypescriptReadValue[t.typescript, "Bump scale factor", scale]; G3dTool.DoWithSelectedShapes[t.shapes, Action, choice]; }; ToggleTextureFiltering: PROC [t: Tool] ~ { Action: ShapeProc ~ {DoWithTextureMaps[shape, Proc]}; Proc: PROC [m: TextureMap] ~ {m.filter _ t.textureFiltering}; t.textureFiltering _ NOT t.textureFiltering; FOR n: NAT IN [0..t.shapes.length) DO [] _ Action[t.shapes[n]]; ENDLOOP; }; SetMapping: PROC [t: Tool, textureStyle: TextureStyle] ~ { Action: ShapeProc ~ { IF textureStyle # none AND NOT shape.vertices.valid.texture THEN G3dTool.TSWrite[t, Rope.Cat["Operation not performed for ", FileNames.GetShortName[shape.name], " (no texture coordinates!)"]] ELSE { error: ROPE _ G3dRender.SetTextureMap[shape, textureName, textureStyle, t.textureFiltering]; IF error # NIL THEN G3dTool.TSWrite[t, error]; }; }; textureName: ROPE; header: ROPE _ SELECT textureStyle FROM intensity => "Set intensity texture map for shape", color => "Set color texture map for shape", bump => "Set bump map for shape", ENDCASE => "Remove all texture from shape"; choice: INT _ G3dTool.ChooseShape[t, header]; IF choice = -2 THEN RETURN; IF textureStyle # none THEN { prompt: ROPE _ NIL; IF choice # -1 THEN { prompt: ROPE _ NIL; textures: LIST OF TextureMap _ G3dRender.RenderDataFrom[t.shapes[choice]].textures; FOR l: LIST OF TextureMap _ textures, l.rest WHILE l # NIL DO IF l.first.name # NIL THEN prompt _ Rope.Cat[prompt, ", ", l.first.name]; ENDLOOP; IF prompt # NIL THEN prompt _ Rope.Cat["(currently", prompt, ")"]; }; IF prompt = NIL THEN prompt _ "filename: "; IF (textureName _ Controls.TypescriptRead[t.typescript, prompt]) = NIL THEN { G3dTool.TSWrite[t, " . . . aborted."]; RETURN; }; }; G3dTool.DoWithSelectedShapes[t.shapes, Action, choice]; }; Temporary Ops Lighting Ops Κ •NewlineDelimiter –"cedarcode" style™™Jšœ Οeœ6™BJ™*J™'J™'J™*J™*J™#—headšΟl'™'JšΟk œˆŸœ˜©J˜—šΡblnœŸœŸ˜ JšŸœKŸœ˜iJšŸœ˜J˜—JšœŸ˜šž™JšŸœŸœŸœ˜JšŸœŸœŸœŸœ˜JšœŸœ˜(JšœŸœ˜*Jšœ Ÿœ˜ Jšœ Ÿœ˜#JšœŸœ˜-JšœŸœ˜1Jšœ Ÿœ˜"JšœŸœ˜/JšœŸœ˜)JšŸœŸœ Ÿœ˜JšœŸœ˜/Jšœ Ÿœ˜Jšœ Ÿœ˜%JšœŸœ˜(—šž ™ šΠbn œŸœŸœ™PJ˜—šΟnœŸœ™'Jšœ Ÿœ ™J™:JšœŸœŸœ™šŸœŸœ™ šœŸœ)Ÿœ™9šΟcœ.™6Jšœ9™9—Jš£œ7™?Jš£œ9™AJš£œE™MJš£œ9™AJš£œ3™;Jš£œ8™@Jš£œ%™-Jš£œO™WJš£œO™WJš£ œ6™?Jš£œ*™2Jš£œ4™<—JšœŸœ™šŸœŸ™šœŸœ'Ÿœ™OJšœ£œ?™HJšœ£œE™Nšœ£œDŸ™QJšœ*Ÿœ™K——Jšœ*Ÿœ™>JšœŸœ™/JšœŸœ™*JšœŸœ™-J™J™J™J™ J™ JšœŸœ™&šœŸΟsœŸœ ™&JšŸ€œ€Ÿ€œ#™A—JšœŸœ™&JšŸœ™—JšœŸœ™JšŸœ Ÿœ™1J™—J™J™—š’œŸœŸœ˜Jšœ-Ÿœ˜3J˜J˜J˜—š’œŸœ™)šŸœ€Ÿ€Ÿ€ŸœŸœ6Ÿœ€œ€ŸœŸ™`Jšœ>Ÿœ™HJšŸœ™—J™J™—š’ œŸœŸœ˜*J˜J˜Jš œ€œ€œ€œ!€œ €œ€œ˜ZJ˜EJ˜EJ˜EJ˜DJ˜DJ˜DJ˜>J˜NJ˜J˜—š‘œŸœ™5Jš ’œŸœŸœŸœŸœ™9J™:Jšœ)™)Jšœ€Ÿ€œ€Ÿ€œ€Ÿ€œ€Ÿœ ™-Jšœ€Ÿ€œ€Ÿ€œ€Ÿ€œ€Ÿ€œ ™-šœŸœŸœ6™GJš ŸœŸœ ŸœŸœ Ÿœ Ÿœ ™K—JšœŸœ1™<šŸœ ŸœŸœ™JšŸœŸœ Ÿœ™3š ’œŸœ ŸœŸœŸœ™0JšœŸœ ŸœŸœ™;J™—JšœŸœŸœŸœ™JšœŸœ!ŸœŸœ™PJšœŸœ ™JšœŸœ ™JšœŸœ"™(Jš œŸœŸœŸœ+ŸœŸœ™Mš ŸœŸœŸœŸœŸœŸœ™QJšŸœ"™&—JšŸœ Ÿœ"™2Jšœ7Ÿœ™=J™—J™J™—š’ œŸœŸœŸœ˜5Jš’œ9™?Jšœ"Ÿœ™)J™J™—š‘ œŸœ™!Jš’œA™GJšœŸœ6™>™Jšœ-Ÿœ,™]—JšŸœ ŸœŸœ&™9JšœŸœ™JšœŸœ™&J™J™—š‘œŸœ™&Jš’œF™LJšœ Ÿœ1™?JšœŸœ™JšŸœ ŸœŸœ Ÿœ™=J™J™—š‘ œŸœ™šŸœŸœ™ JšœŸœ)™/J™JšŸœŸœŸœŸœ*™A™&JšœŸœA™T—šŸœ ŸœŸœ™#JšŸœM™QJšŸœ'™+—J™—J™J™—š‘ œŸœ˜#Jš’œ5™;JšœŸœŸœ™7J™J˜—š œŸœŸœ"ŸœŸœ™LJ™—š’œŸœŸœ™Aš ŸœŸœŸœŸœŸœŸœŸ™BJ™CšŸ€œ€Ÿ€Ÿ€œ€œ €œ€Ÿ€œ€œŸœŸ™Iš ŸœŸœŸœŸœŸœ™2JšŸœ™——JšŸœŸœŸœ™4JšŸœ™—J™J™—š ’œŸœŸœ-ŸœŸœ™Rš’œ™šŸœ'Ÿœ™/J™JšŸœŸœ™J™—J™:šŸœŸœŸœŸ™GšœŸœŸœŸœ™GJ™4JšŸ œ™ J™——™;Jšœ%Ÿœ™0—šŸœ™JšŸœCŸœ™MJšŸœ™—JšŸœŸœ™J™—J™)JšŸœ Ÿœ™-šŸœŸœŸœŸœ™2J™!JšŸœ™J™—šŸœŸœŸœŸœ™:J™&JšŸœ™J™—šŸœŸœŸœŸœ™7J™NJšŸœ™J™—J™"J™J™—š’œ™5J™JšœŸœ™J™J™—š’ œŸœ™$šŸœŸœ™š(’œ€Ÿ€œ€Ÿœ€œ€œ€œ€œ €œ€Ÿœ€œ€Ÿ€œ€Ÿœ€œŸ€œ€œ€œ™cJšœUŸœ™[JšŸœŸœŸœ™*J™_JšŸœ ŸœŸœ#™6J™PJ™—š ’œŸœŸœŸœŸœ™+Jš ’ œ Ÿœ ŸœŸœŸœ™PJšŸœ#™)J™—Jš œŸœŸœ7ŸœŸœ™TJ™GJ™OJ™—šŸœŸ™JšœH™H—JšŸœ Ÿœ2™EJ™J™—š’ œŸœŸœ2˜L˜J˜S—J˜EJ˜%J˜J™—š’œ€Ÿ€Ÿ€œ˜Jšœ €œ ˜Jšœ˜Jšœ€œ˜Jšœ€Ÿ€œ€Ÿœ˜Jšœ€œ˜JšŸœ"ŸœŸœ™0J™!JšœS™SJšœ0™0J™J™—Jšœ ŸœŸœ™&šœŸœŸœ™J™JšœŸœ™JšœŸ™J™J™—šœŸœŸœ™J™—š’œ™-JšœŸœ™J™"J™)J™'J™—š’ œŸœŸœ˜J˜J˜Jšœ Ÿœ˜JšœŸœ˜JšœŸœ˜JšœŸœŸœ˜J˜JšœŸœ7™SJ™!šŸœŸœ"Ÿœ™0šŸœ™šœ€œ™Jšœ!€œ €œ €Ÿœ™B—J™IJ™—JšŸœ!™%—J™J™—š ‘œΟbŸœŸœŸœ˜CJš’œG™MJšœ"Ÿœ™)J™J™—š ‘œ₯ŸœŸœŸœ˜GJš’œR™SJšœŸœ™$J™J™—š ‘’ œ₯ŸœŸœŸœ˜FJš’œT™UJ™$JšœŸœ™$J™——šž ™ šœ Ÿœ™(J™—š’œŸœ˜(Jšœ Ÿœ ™šœŸœ*Ÿœ™:Jš£œJ™QJš£œL™SJš£œA™HJš£œ?™FJš£œT™[Jš£œL™SJš£œ;™BJš£œ7™>—JšœŸœ™šŸœŸ™J™J™J™J™J™J™J™J™JšŸœ™—JšœŸœ™J™J™—š’œŸœ™$JšœŸœ9™DšŸœ Ÿœ™Jš’œ:™@J™9JšŸœŸœ)Ÿœ™EJ™7J™—J™J™—š’œŸœŸœŸœ™TJšŸœŸœŸœ Ÿœ™,JšœŸœ1™<šŸœ ŸœŸœ™Jš œŸœŸœŸœŸœ™JšœŸœ Ÿœ ™%J™—JšŸœ2™7J™J™—š’œŸœŸœ™KJ™6JšŸœŸœŸœ!ŸœŸœŸœŸœ™WJ™J™—š’œŸœ™#Jš’œ/™5Jš’œŸœ,™6J™J™JšœŸœ8™CJšŸœ ŸœŸœ™šŸœ Ÿœ™J™EJšŸœŸœŸœ™4J™—Jšœ1Ÿœ$™YJšŸœŸœŸœ)Ÿœ™@J™7J™J™—š’ œŸœ™ Jš’œ/™5Jš’œŸœ*™4JšœŸœ™JšœŸœ5™@JšŸœ ŸœŸœ™šŸœ Ÿœ™J™EJšŸœŸœŸœ%™=J™—J™OJ™7J™J™—š‘œ₯Ÿœ™*Jš’œ/™5Jš’œŸœ3™=JšœŸœ™,Jš ŸœŸœŸœŸœŸœ™HJ™J™—š’ œŸœ*™:š’œ™šŸœŸœŸœ™;JšŸœ™ƒšŸœ™šœŸœ™ JšœN™N—JšŸœ ŸœŸœ™.J™——J™—Jšœ Ÿœ™šœŸœŸœŸ™'J™3J™,J™"JšŸœ$™+—JšœŸœ"™-JšŸœ ŸœŸœ™šŸœŸœ™JšœŸœŸœ™šŸœ Ÿœ™JšœŸœŸœ™Jšœ ŸœŸœ€œ*™SšŸœ€Ÿ€Ÿ€œ €œ€œ €œ€Ÿ€œ€œ€Ÿ€Ÿ™=JšŸœŸœŸœ/™IJšŸœ™—JšŸœ ŸœŸœ.™BJ™—JšŸœ ŸœŸœ™+šŸœAŸœŸœ™MJ™&JšŸœ™J™—J™—J™7J™——šž ™ Jš’œŸœ˜&Jš’œŸœ˜(JšœŸœ˜!Jš’œŸœŸœP˜v—šž ™ š ’ œŸœ!ŸœŸœ Ÿœ ˜UJšœŸœŸœŸœ˜"JšŸœ ŸœŸœŸœ˜Jš ŸœŸœŸœŸœŸœ$Ÿœ˜YJ˜,J˜J˜—š’œŸœŸœ Ÿœ˜>JšŸœŸœ ŸœŸœ˜NJ˜J˜—š’ œŸœŸœ˜J˜J˜Jšœ˜JšŸœ˜J˜š’œŸœ˜,JšŸœŸœŸœ%Ÿ œ˜CJš œ ŸœŸœŸœ Ÿœ ˜?š œŸœŸœŸœŸœ˜1J˜M—Jš œŸœŸœŸœ ŸœŸœ ˜NJšœŸœ Ÿœ Ÿœ ˜AJ˜