DIRECTORY Ascii, Atom, Commander, CommandTool, FileNames, FS, G3dBasic, G3dRender, G3dShape, G3dScene, G3dVector, IO, MessageWindow, Rope, RopeFile, TiogaAccess, TiogaMenuOps, TiogaOps, ViewerOps, ViewerTools; G3dSceneImpl: CEDAR PROGRAM IMPORTS Atom, CommandTool, FileNames, FS, G3dRender, G3dShape, G3dVector, IO, MessageWindow, Rope, RopeFile, TiogaAccess, TiogaMenuOps, TiogaOps, ViewerOps, ViewerTools EXPORTS G3dScene ~ BEGIN Pair: TYPE ~ G3dBasic.Pair; Triple: TYPE ~ G3dBasic.Triple; RGB: TYPE ~ G3dRender.RGB; Context: TYPE ~ G3dRender.Context; RenderData: TYPE ~ G3dRender.RenderData; RenderStyle: TYPE ~ G3dRender.RenderStyle; TextureStyle: TYPE ~ G3dRender.TextureStyle; TextureInfo: TYPE ~ G3dRender.TextureInfo; LogProc: TYPE ~ G3dScene.LogProc; ViewerSelection: TYPE ~ G3dScene.ViewerSelection; Shape: TYPE ~ G3dShape.Shape; STREAM: TYPE ~ IO.STREAM; ROPE: TYPE ~ Rope.ROPE; Writer: TYPE ~ TiogaAccess.Writer; SelPos: TYPE ~ ViewerTools.SelPos; Viewer: TYPE ~ ViewerTools.Viewer; Item: TYPE ~ RECORD [name: ROPE, value: REAL]; WriteInfo: TYPE ~ RECORD [ writer: Writer _ NIL, fileName: ROPE _ NIL, stream: STREAM _ NIL, ok: BOOL _ TRUE]; GetWriteInfo: PROC RETURNS [i: WriteInfo] ~ { v: Viewer _ ViewerTools.GetSelectedViewer[]; i.writer _ TiogaAccess.Create[]; IF Rope.Length[ViewerTools.GetSelectionContents[]] # 0 THEN i.fileName _ FileNames.ResolveRelativePath[ViewerTools.GetSelectionContents[]] ELSE i.ok _ v # NIL AND (v.class.flavor = $Text OR v.class.flavor = $Typescript); IF NOT i.ok THEN Blink["Make primary selection"]; }; PutWriter: PROC [i: WriteInfo] ~ { WriteToViewer: PROC [root: TiogaOps.Ref] ~ { TiogaAccess.WriteSelection[i.writer ! TiogaAccess.Error => {Blink[expl]; CONTINUE}]; }; SELECT TRUE FROM i.stream # NIL => TiogaAccess.WriteOpenFile[i.writer, FS.OpenFileFromStream[i.stream] ! FS.Error => {Blink[error.explanation]; CONTINUE}]; i.fileName # NIL => TiogaAccess.WriteFile[i.writer, i.fileName ! FS.Error => {Blink[error.explanation]; CONTINUE}] ENDCASE => TiogaOps.CallWithLocks[WriteToViewer]; }; Nest: PROC [w: Writer] ~ {TiogaAccess.Nest[w, 1]}; UnNest: PROC [w: Writer] ~ {TiogaAccess.Nest[w, -1]}; WriteNode: PROC [w: Writer, rope: ROPE, looks: ROPE _ NIL] ~ { tc: TiogaAccess.TiogaChar _ [charSet: 0, char: '\000, looks: ALL[FALSE], format: NIL, comment: FALSE, endOfNode: FALSE, deltaLevel: 0, propList: NIL]; FOR n: INT IN [0..Rope.Length[looks]) DO c: CHAR _ Rope.Fetch[looks, n]; IF c IN TiogaAccess.Look THEN tc.looks[c] _ TRUE; ENDLOOP; FOR n: INT IN [0..Rope.Length[rope]) DO tc.char _ Rope.Fetch[rope, n]; TiogaAccess.Put[w, tc]; ENDLOOP; tc.endOfNode _ TRUE; TiogaAccess.Put[w, tc]; }; WriteItem: PROC [w: Writer, item: Item] ~ {WriteReal[w, item.name, item.value]}; WriteBool: PROC [w: Writer, name: ROPE, bool: BOOL] ~ { WriteNode[w, Rope.Cat[name, ":\t", IF bool THEN "True" ELSE "False"]]; }; WriteReal: PROC [w: Writer, name: ROPE, value: REAL] ~ { WriteNode[w, IO.PutFR["%g:\t%g", IO.rope[name], IO.real[value]]]; }; WritePair: PROC [w: Writer, name: ROPE, p: Pair] ~ { WriteNode[w, IO.PutFR["%g:\t%g, %g", IO.rope[name], IO.real[p.x], IO.real[p.y]]]; }; WriteTriple: PROC [w: Writer, name: ROPE, t: Triple] ~ { WriteNode[w, IO.PutFR["%g:\t(%g, %g, %g)", IO.rope[name], IO.real[t.x], IO.real[t.y], IO.real[t.z]]]; }; WriteRGB: PROC [w: Writer, name: ROPE, rgb: RGB] ~ { WriteTriple[w, name, [rgb.R, rgb.G, rgb.B]]; }; WriteFour: PROC [w: Writer, name: ROPE, v1, v2, v3, v4: REAL] ~ { WriteNode[w, IO.PutFR["%g:\t(%g, %g, %g, %g)", IO.rope[name], IO.real[v1], IO.real[v2], IO.real[v3], IO.real[v4]]]; }; WriteTitle: PROC [w: Writer, title: ROPE] ~ { WriteNode[w, title, "b"]; Nest[w]; }; WriteBlock: PROC [w: Writer, title: ROPE, items: LIST OF Item] ~ { WriteTitle[w, title]; FOR l: LIST OF Item _ items, l.rest WHILE l # NIL DO WriteItem[w, l.first]; ENDLOOP; UnNest[w]; }; WriteShape: PROC [w: Writer, s: Shape] ~ { shade: REF G3dRender.ShadingClass _ G3dRender.ShadingClassFromShape[s]; WriteTitle[w, Rope.Cat["ShapeRead ", s.name]]; WriteBool[w, "ShapeBackFaces", s.showBackfaces]; WriteNode[w, Rope.Cat["ShapeRenderStyle: ", Atom.GetPName[shade.type]]]; WriteRGB[w, "ShapeColor", shade.color]; WriteReal[w, "ShapeShininess", shade.shininess]; IF shade.transmittance # 0.0 THEN WriteReal[w, "ShapeTransmittance", shade.transmittance]; WriteTriple[w, "ShapePosition", s.position]; WritePair[w, "ShapeTextureScale", shade.textureScale]; WriteReal[w, "ShapeBumpScale", shade.bumpScale]; FOR l: LIST OF TextureInfo _ G3dRender.GetTextureInfo[s], l.rest WHILE l # NIL DO WriteNode[w, IO.PutFR["Shape%gMap %g, ShapeTextureFiltering: ", IO.rope[G3dRender.RopeFromTextureStyle[l.first.type]], IO.rope[l.first.name], IO.rope[IF l.first.filtered THEN "True" ELSE "False"]]]; ENDLOOP; UnNest[w]; }; WriteLight: PROC [w: Writer, s: Shape] ~ { shade: REF G3dRender.ShadingClass _ G3dRender.ShadingClassFromShape[s]; WriteNode[w, IO.PutFLR["%g: %g, (%g, %g, %g), (%g, %g, %g)", LIST[ IO.rope["LightAdd"], IO.rope[s.name], IO.real[s.position.x], IO.real[s.position.y], IO.real[s.position.z], IO.real[shade.color.R], IO.real[shade.color.G], IO.real[shade.color.B]]]]; }; WriteCamera: PROC [context: Context, w: Writer] ~ { WriteTitle[w, "Camera Parameters"]; WriteReal[w, "CameraFieldOfView", context.fieldOfView]; WriteTriple[w, "CameraEyePoint", context.eyePoint]; WriteTriple[w, "CameraLookAt", context.lookAt]; WriteTriple[w, "CameraUp", context.upDirection]; WriteReal[w, "CameraRoll", context.rollAngle]; UnNest[w]; }; WriteCameraParameters: PUBLIC PROC [context: Context] ~ { i: WriteInfo _ GetWriteInfo[]; IF NOT i.ok THEN RETURN; WriteCamera[context, i.writer]; WriteNode[i.writer, NIL]; UnNest[i.writer]; PutWriter[i]; }; WriteParameters: PUBLIC PROC [context: Context, fileName: ROPE _ NIL] ~ { i: WriteInfo _ IF fileName = NIL THEN GetWriteInfo[] ELSE [TiogaAccess.Create[], fileName]; WriteParametersToWriter[context, i]; }; WriteParametersToStream: PUBLIC PROC [context: Context, out: STREAM] ~ { WriteParametersToWriter[context, [writer: TiogaAccess.Create[], stream: out]]; }; WriteParametersToWriter: PUBLIC PROC [c: Context, i: WriteInfo] ~ { w: Writer _ i.writer; IF NOT i.ok OR c = NIL THEN RETURN; WriteNode[w, "3d Context Parameters", "bz"]; Nest[w]; WriteCamera[c, w]; WriteTitle[w, "Image Parameters"]; WriteNode[w, Rope.Cat["DisplayMode: ", G3dRender.RopeFromDisplayMode[G3dRender.GetDisplayMode[c]]]]; IF c.window # NIL THEN WriteFour[w, "DisplayRegion", c.window.x, c.window.y, c.window.w, c.window.h]; IF c.preferredViewPort # [0.0, 0.0, 65536.0, 65536.0] THEN WriteFour[w, "Viewport: ", c.preferredViewPort.x, c.preferredViewPort.y, c.preferredViewPort.w, c.preferredViewPort.h]; WriteRGB[w, "Background", G3dRender.GetBackgroundColor[c]]; IF G3dRender.GetBackgroundImage[c] # NIL THEN WriteNode[w, Rope.Cat["BackgroundImage", G3dRender.GetBackgroundImage[c]]]; WriteBool[w, "AntiAliasing", c.antiAliasing]; UnNest[w]; WriteTitle[w, "Lights"]; FOR n: NAT IN [0..c.shapes.length) DO IF G3dRender.ShadingClassFromShape[c.shapes[n]].type = $Light THEN WriteLight[w, c.shapes[n]]; ENDLOOP; WriteTitle[w, "Shapes"]; FOR n: NAT IN [0..c.shapes.length) DO IF G3dRender.ShadingClassFromShape[c.shapes[n]].type # $Light THEN WriteShape[w, c.shapes[n]]; ENDLOOP; WriteRGB[w, "LightAmbience", G3dRender.GetAmbientLight[c]]; UnNest[w]; WriteNode[w, NIL]; UnNest[w]; UnNest[w]; PutWriter[i]; }; ReadInfo: TYPE ~ RECORD [operations: ROPE, v: Viewer, sel: SelPos, fileName: ROPE _ NIL]; GetReaderInfo: PROC RETURNS [i: ReadInfo] ~ { i.operations _ ViewerTools.GetSelectionContents[]; IF Rope.Length[i.operations] = 0 THEN RETURN[[NIL, NIL, NIL]]; IF Rope.Length[i.operations] < 100 THEN { i.fileName _ FileNames.ResolveRelativePath[i.operations]; i.fileName _ FS.FileInfo[i.fileName ! FS.Error => {i.fileName _ NIL; CONTINUE}].fullFName; IF i.fileName # NIL THEN i.operations _ RopeFile.Create[i.fileName]; } ELSE i.sel _ ViewerTools.GetSelection[i.v _ ViewerTools.GetSelectedViewer[]]; }; MakeFrameFromFile: PUBLIC PROC [context: Context, fileName: ROPE] ~ { GetPut: PROC [a: ATOM] ~ { temp.props _ Atom.PutPropOnList[temp.props, a, Atom.GetPropFromList[context.props, a]]; }; temp: Context _ G3dRender.Create[]; temp.pixels _ context.pixels; temp.viewer _ context.viewer; temp.terminal _ context.terminal; temp.class _ context.class; temp.antiAliasing _ context.antiAliasing; GetPut[$WDir]; GetPut[$Log]; [] _ ReadParameters[temp, fileName]; temp.class.render[temp]; temp _ NIL; }; ReadParameters: PUBLIC PROC [context: Context, fileName: ROPE _ NIL, cmdOut: STREAM _ NIL] RETURNS [shouldRepaint: BOOL] ~ { i: ReadInfo _ IF fileName = NIL THEN GetReaderInfo[] ELSE [RopeFile.Create[fileName], NIL, NIL, fileName]; RETURN[Parse[context, i.operations, cmdOut,, TRUE, i.fileName, [i.v, i.sel] ! ParseError => CONTINUE]]; }; Blink: PROC [r: ROPE] ~ { MessageWindow.Append[Rope.Concat["\t\t", r], TRUE]; MessageWindow.Blink[]; }; ParseError: PUBLIC ERROR [position: NAT, fileName: ROPE, viewer: Viewer] = CODE; Parse: PUBLIC PROC [ context: Context, operation: ROPE, cmdOut: STREAM _ NIL, log: LogProc _ NIL, showErrors: BOOL _ TRUE, fileName: ROPE _ NIL, viewerSelection: ViewerSelection _ [NIL, NIL]] RETURNS [shouldRepaint: BOOL _ FALSE] ~ { s: Shape _ NIL; -- the current shape c: Context _ context; in: STREAM _ IO.RIS[operation]; cmdHandle: Commander.Handle _ NIL; directory: ROPE _ FileNames.CurrentWorkingDirectory[]; indent: NAT _ 0; { ENABLE { IO.EndOfStream => CONTINUE; IO.Error => { position: INT _ IO.GetIndex[in]; IF viewerSelection.viewer # NIL AND viewerSelection.selection # NIL THEN { position _ position+viewerSelection.selection.start; viewerSelection.selection^ _ [position, 10]; ViewerTools.SetSelection[viewerSelection.viewer, viewerSelection.selection]; Blink["Error during read"]; } ELSE { Blink[IO.PutFR["Error during read, file position = %g", IO.int[position]]]; IF fileName # NIL THEN { v: Viewer _ ViewerOps.FindViewer[fileName]; IF v = NIL THEN { v _ ViewerOps.CreateViewer[flavor: $Text, paint: FALSE, info: [iconic: TRUE, column: right, openHeight: 140]]; TiogaMenuOps.Load[v, fileName]; }; ViewerOps.OpenIcon[icon: v, bottom: FALSE, paint: FALSE]; TiogaAccess.SetPosition[TiogaAccess.FromViewer[v], position]; }; }; ParseError[position, fileName, viewerSelection.viewer]; }; }; GetRope: PROC RETURNS [r: ROPE] ~ { BreakProc: IO.BreakProc ~ { -- as default IO.TokenProc except '/, '], '[ aren't separators RETURN[SELECT char FROM IN [Ascii.NUL..Ascii.SP], ',, ':, '; => sepr, '[, '], '(, '), '{, '}, '", '+, '-, '*, '@, '_ => break, ENDCASE => other]; }; Test[]; r _ IO.GetTokenRope[in, BreakProc].token; }; GetBool: PROC RETURNS [b: BOOL] ~ {Test[]; b _ IO.GetBool[in]}; GetReal: PROC RETURNS [r: REAL] ~ {Test[]; r _ IO.GetReal[in]}; GetInt: PROC RETURNS [i: INTEGER] ~ {Test[]; i _ IO.GetInt[in]}; GetPair: PROC RETURNS [p: Pair] ~ {p.x _ GetReal[]; p.y _ GetReal[]}; GetTriple: PROC RETURNS [t: Triple] ~ {t.x _ GetReal[]; t.y _ GetReal[]; t.z _ GetReal[]}; GetRGB: PROC RETURNS [t: RGB] ~ {t.R _ GetReal[]; t.G _ GetReal[]; t.B _ GetReal[]}; Test: PROC ~ { DO c: CHAR _ IO.PeekChar[in]; IF c = ') OR c = '( OR c = ': OR c = ', OR c = Ascii.SP OR c = '\t THEN [] _ IO.GetChar[in] ELSE EXIT; ENDLOOP; }; DO Eq: PROC [r1, r2: ROPE] RETURNS [BOOL] ~ {RETURN[Rope.Equal[r1, r2, FALSE]]}; OpEq: PROC [r: ROPE] RETURNS [BOOL] ~ {RETURN[Eq[op, r]]}; ShapeOk: PROC RETURNS [BOOL] ~ { IF s # NIL THEN RETURN[TRUE]; Blink[Rope.Cat["No shape to perform: ", op]]; RETURN[FALSE]; }; Log: PROC [r: ROPE] ~ { IF log = NIL THEN RETURN; THROUGH [0..indent) DO r _ Rope.Concat["*", r]; ENDLOOP; log[r]; }; UpdateCamera: PROC [function: ROPE] ~ { shouldRepaint _ TRUE; SELECT TRUE FROM Eq[function, "fieldOfView"] => Log[IO.PutFR["Set camera roll: %g", IO.real[context.fieldOfView _ GetReal[]]]]; Eq[function, "roll"] => Log[IO.PutFR["Set camera roll: %g", IO.real[context.rollAngle _ GetReal[]]]]; ENDCASE => { t: Triple _ GetTriple[]; Log[IO.PutFR["Set camera %g: (%g, %g, %g)", IO.rope[function], IO.real[t.x], IO.real[t.y], IO.real[t.z]]]; SELECT TRUE FROM Eq[function, "eyePoint"] => context.eyePoint _ t; Eq[function, "lookAt"] => context.lookAt _ t; Eq[function, "up"] => context.upDirection _ t; ENDCASE; }; }; SetRenderStyle: PROC ~ { Set: PROC [r: RenderStyle] ~ { Log[Rope.Cat["Set style of ", s.name, " to: ", word]]; G3dRender.SetRenderStyle[s, r]; }; word: ROPE _ GetRope[]; SELECT TRUE FROM Eq[word, "faceted"] => Set[faceted]; Eq[word, "smooth"] => Set[smooth]; Eq[word, "lines"] => Set[lines]; Eq[word, "shadedLines"] => Set[shadedLines]; Eq[word, "hiddenLines"] => Set[hiddenLines]; ENDCASE => Blink["No such render style"]; }; SetTextureMap: PROC [t: TextureStyle] ~ { IF t = none THEN [] _ G3dRender.SetTextureMap[c, s.name, NIL, none] ELSE { Log[Rope.Cat["Set texture map to: ", name _ GetRope[]]]; IF (err _ G3dRender.SetTextureMap[c, s.name, name, t]) # NIL THEN Blink[err]; }; }; err, name: ROPE; op: ROPE _ GetRope[]; SELECT TRUE FROM OpEq["ReadScene"] => { localShouldRepaint: BOOL; indent _ indent+1; Log[Rope.Cat["Reading scene: ", name _ GetRope[]]]; localShouldRepaint _ Parse[c, name, cmdOut, log]; shouldRepaint _ shouldRepaint OR localShouldRepaint; indent _ indent-1; }; OpEq["Command"] => { result: REF; IF cmdHandle = NIL THEN { cmdHandle _ NEW[Commander.CommandObject]; CommandTool.AddSearchRule[cmdHandle, directory]; CommandTool.AddSearchRule[cmdHandle, "///7.0/Commands/"]; CommandTool.AddSearchRule[cmdHandle, "///7.0/System/"]; cmdHandle.err _ cmdHandle.out _ cmdOut; }; Log[IO.PutFR["Command: %g\n%l", IO.rope[name _ GetRope[]], IO.rope["i"]]]; Log[IO.PutFR["%l", IO.rope["I"]]]; result _ CommandTool.DoCommand[name, cmdHandle]; IF result # NIL THEN Log[IO.PutFR["(%g)", IO.refAny[result]]]; }; OpEq["AddProperty"] => { Log[Rope.Cat["Adding property"]]; c.props _ Atom.PutPropOnList[c.props, IO.GetRefAny[in], IO.GetRefAny[in]]; }; OpEq["DisplayMode"] => { r: ROPE _ GetRope[]; Log[Rope.Cat["Set display mode: ", r]]; G3dRender.LoadDisplayClass[c, SELECT TRUE FROM Eq[r, "fullColor"] => $FullColor, Eq[r, "dither"] => $PseudoColor, ENDCASE => $Gray]; }; OpEq["DisplayRegion"] => { x: REAL _ GetReal[]; y: REAL _ GetReal[]; w: REAL _ GetReal[]; h: REAL _ GetReal[]; Log[IO.PutFR["DisplayRegion %g, %g, %g, %g", IO.real[x], IO.real[y], IO.real[w], IO.real[h]]]; G3dRender.SetViewPort[c, [x, y, w, h]]; }; OpEq["Viewport"] => { xy: Pair _ GetPair[]; wh: Pair _ GetPair[]; Log[IO.PutFR["Viewport: [%g, %g, %g, %g]", IO.real[xy.x], IO.real[xy.y], IO.real[wh.x], IO.real[wh.y]]]; G3dRender.SetViewPort[c, [xy.x, xy.y, wh.x, wh.y]]; }; OpEq["BackgroundEnable"] => { Log["EnableBackground set"]; G3dRender.EnableBackground[context, GetBool[]]; }; OpEq["Background"] => { v: RGB _ GetRGB[]; Log[IO.PutFR["Background: (%g, %g, %g)", IO.real[v.R], IO.real[v.G], IO.real[v.B]]]; G3dRender.SetBackgroundColor[c, v]; }; OpEq["BackgroundImage"] => { Log[Rope.Cat["Background image: ", name _ GetRope[]]]; G3dRender.SetBackgroundImage[c, name]; }; OpEq["AntiAliasing"] => { Log["Anti aliasing set"]; G3dRender.SetAntiAliasing[c, GetBool[]]; }; OpEq["CameraFieldOfView"] => UpdateCamera["fieldOfView"]; OpEq["CameraEyePoint"] => UpdateCamera["eyePoint"]; OpEq["CameraLookAt"] => UpdateCamera["lookAt"]; OpEq["CameraUp"] => UpdateCamera["up"]; OpEq["CameraRoll"] => UpdateCamera["roll"]; OpEq["ShapeRead"] => { Log[Rope.Cat["Read shape: ", name _ GetRope[]]]; IF Rope.Find[name, "/"] = -1 AND Rope.Find[name, ">"] = -1 THEN name _ Rope.Cat[FileNames.CurrentWorkingDirectory[], name]; G3dRender.AddShapeFromFile[c, FileNames.GetShortName[name], name ! G3dShape.Error => {Blink[reason]; name _ NIL; CONTINUE}]; IF name # NIL THEN s _ c.shapes[c.shapes.length-1] }; OpEq["ShapeName"] => { Log[Rope.Cat["Set shape: ", name _ GetRope[]]]; s _ G3dRender.FindShape[c, name]; }; OpEq["ShapeBackFaces"] => IF ShapeOk[] THEN { Log[Rope.Cat["Set back faces: ", s.name]]; IF (s.showBackfaces _ GetBool[]) THEN G3dRender.SetVisible[s] ELSE G3dRender.SetInvisible[s]; }; OpEq["ShapeRenderStyle"] => IF ShapeOk[] THEN SetRenderStyle[]; OpEq["ShapeColor"] => IF ShapeOk[] THEN { color: RGB _ GetRGB[]; G3dRender.SetColor[s, color]; Log[IO.PutFR["Set color of %g to (%g, %g, %g)", IO.rope[s.name], IO.real[color.R], IO.real[color.G], IO.real[color.B]]]; }; OpEq["ShapeShininess"] => IF ShapeOk[] THEN { shininess: REAL _ GetReal[]; Log[IO.PutFR["Set shininess of %g to %g", IO.rope[s.name], IO.real[shininess]]]; G3dRender.SetShininess[s, shininess]; }; OpEq["ShapeTransmittance"] => IF ShapeOk[] THEN { transmit: REAL _ GetReal[]; Log[IO.PutFR["Set transmittance of %g to %g", IO.rope[s.name], IO.real[transmit]]]; G3dRender.SetTransmittance[s, transmit]; }; OpEq["ShapeScale"] => IF ShapeOk[] THEN { scale: REAL _ GetReal[]; Log[IO.PutFR["Set scale of %g to %g", IO.rope[s.name], IO.real[scale]]]; G3dShape.TransformShape[shape: s, scale: scale]; }; OpEq["ShapeTranslate"] => IF ShapeOk[] THEN { trans: Triple _ GetTriple[]; Log[IO.PutFR["%g trans: (%g, %g, %g)", IO.rope[s.name], IO.real[trans.x], IO.real[trans.y], IO.real[trans.z]]]; G3dShape.TransformShape[shape: s, translate: trans]; }; OpEq["ShapeRotate"] => IF ShapeOk[] THEN { p0: Triple _ GetTriple[]; p1: Triple _ GetTriple[]; r: REAL _ GetReal[]; Log[IO.PutFR["%g rotate: %g", IO.rope[s.name], IO.real[r]]]; Log[Rope.Cat["Rotate ", s.name]]; G3dShape.TransformShape[shape: s, axis: [p0, G3dVector.Sub[p1, p0]], rotation: r]; }; OpEq["ShapeDelete"] => { Log[Rope.Cat["Delete ", name _ GetRope[]]]; G3dRender.DeleteShape[c, name]; }; OpEq["ShapeTextureOffset"] => IF ShapeOk[] THEN { i: Pair _ GetPair[]; Log[IO.PutFR["%g texture offset: (%g, %g)", IO.rope[s.name], IO.real[i.x], IO.real[i.y]]]; G3dRender.OffsetTextureCoords[s, i]; }; OpEq["ShapeTextureScale"] => IF ShapeOk[] THEN { p: Pair _ GetPair[]; Log[IO.PutFR["%g texture scale: (%g, %g)", IO.rope[s.name], IO.real[p.x], IO.real[p.y]]]; G3dRender.SetTextureScale[s, p]; }; OpEq["ShapeBumpScale"] => IF ShapeOk[] THEN { scale: REAL _ GetReal[]; Log[IO.PutFR["%g bump scale: %g", IO.rope[s.name], IO.real[scale]]]; G3dRender.SetBumpScale[s, scale]; }; OpEq["ShapeTextureFiltering"] => { Log[Rope.Cat["Set texture filtering for ", s.name]]; G3dRender.SetTextureFiltering[c, s, GetBool[]]; }; OpEq["ShapeNoMapping"] => SetTextureMap[none]; OpEq["ShapeIntensityMap"] => SetTextureMap[intensity]; OpEq["ShapeColorMap"] => SetTextureMap[color]; OpEq["ShapeBumpMap"] => SetTextureMap[bump]; OpEq["ShapeInvertNormals"] => IF ShapeOk[] THEN { Log[Rope.Cat["Negate normals of ", s.name]]; G3dShape.NegateVertexNormals[s]; }; OpEq["PolygonTriangulate"] => { Log[Rope.Cat["Triangulate shape: ", s.name]]; G3dShape.Triangulate[s]; }; OpEq["PolygonReverse"] => IF ShapeOk[] THEN { Log[Rope.Cat["Reverse polygons of ", s.name]]; G3dShape.ReversePolygons[s]; }; OpEq["LightAdd"] => { name: ROPE _ GetRope[]; pos: Triple _ GetTriple[]; rgb: RGB _ GetRGB[]; Log[Rope.Cat["Add light: ", name]]; G3dRender.AddLight[c, name, G3dVector.Normalize[pos], rgb]; }; OpEq["LightDelete"] => { Log[Rope.Cat["Delete light: ", name _ GetRope[]]]; G3dRender.DeleteLight[c, name]; }; OpEq["LightAmbience"] => { rgb: RGB _ GetRGB[]; Log[IO.PutFR["Ambient light: (%g, %g, %g)", IO.real[rgb.R], IO.real[rgb.G], IO.real[rgb.B]]]; G3dRender.SetAmbientLight[c, rgb]; }; ENDCASE; ENDLOOP; }; }; END. †G3dSceneImpl.mesa Copyright c 1988 by Xerox Corporation. All rights reserved. Bloomenthal, March 12, 1989 9:03:00 pm PST Type Declarations Write Scene Descriptions to a Viewer Read Scene Descriptions from a Viewer or a File Parsing a Scene Description Miscellaneous Operations: Line-Drawing and Rendering: Camera Operations: Shape Operations: Polygon Operations: Light Operations: Κe˜™Jšœ Οmœ1™Jš œ=žœžœ žœ žœ žœžœ˜–šžœžœžœž˜(Jšœžœ˜Jšžœžœžœžœ˜1Jšžœ˜—šžœžœžœž˜'J˜J˜Jšžœ˜—Jšœžœ˜J˜J˜J˜—š’ œžœA˜PJ˜—š’ œžœžœžœ˜7Jšœ#žœžœžœ ˜FJ˜J˜—š’ œžœžœ žœ˜8Jšœ žœžœ žœ˜AJ˜J˜—š’ œžœžœ˜4Jš œ žœžœ žœ žœ ˜QJ˜J˜—š’ œžœžœ˜8šœ ‘žœ‘œ‘œ˜*Jš ‘žœ ‘žœ ‘žœ ‘žœ ˜;—J˜J˜—š’œžœžœ˜4Jšœ,˜,J˜J˜—š’ œžœžœžœ˜Ašœ ‘žœ‘œ‘œ ˜.Jš‘žœ ‘žœ ‘žœ ‘žœ žœ ˜E—J˜J˜—š’ œžœžœ˜-J˜Jšœ˜J˜J˜—š ’ œžœžœ žœžœ ˜BJ˜Jšžœžœžœžœžœžœžœ˜TJšœ ˜ J˜J˜—š’ œžœ˜*Jšœžœ=˜GJ˜.J˜0JšœH˜HJšœ'˜'Jšœ0˜0Jšžœžœ9˜ZJ˜,Jšœ6˜6Jšœ0˜0š žœžœžœ3žœžœž˜Qšœ žœ0˜?Jšžœ4˜6Jšžœ˜Jšžœžœžœžœ ˜8—Jšžœ˜—Jšœ ˜ J˜J˜—š’ œžœ˜*Jšœžœ=˜Gšœ žœ.žœ˜BJšžœ˜Jšžœ˜Jšžœžœžœ˜DJšžœžœžœ˜J—J˜J˜—š’ œžœ"˜3J˜#Jšœ7˜7Jšœ3˜3Jšœ/˜/Jšœ0˜0Jšœ.˜.J˜ J˜J˜—š’œž œ˜9J˜Jšžœžœžœžœ˜Jšœ˜Jšœžœ˜J˜J˜ J˜J˜—š ’œžœžœžœžœ˜IJš œžœ žœžœžœ"˜[Jšœ$˜$J˜J˜—š’œžœžœžœ˜HJšœN˜NJ˜J™—š’œž œ˜CJ˜Jš žœžœžœžœžœžœ˜#J˜,Jšœ˜J˜J˜"˜&J˜=—šžœ ž˜Jšžœ ‘œA˜S—šžœ3˜5šžœ˜Jšœ-˜-Jšœ.˜.——J˜;šžœ#ž˜(JšžœL˜P—Jšœ-˜-Jšœ ˜ J˜šžœžœžœž˜%šžœ;˜=Jšžœ˜ —Jšžœ˜—J˜šžœžœžœž˜%šžœ;˜=Jšžœ˜ —Jšžœ˜—Jšœ<˜šžœ ˜"šžœ˜Jšœ9˜9šœ ‘œ‘žœ ‘œ˜#Jšœ‘žœ‘œ‘œ ‘œ‘žœ‘žœ ˜6—Jšžœžœžœ,˜DJ˜—JšžœI˜M—J˜J˜—defaultš’œžœžœžœ˜Eaš’œžœžœ˜MšœW˜WM˜—Mšœ#˜#M˜M˜M˜!M˜M˜)Mšœ˜Mšœ ˜ Lšœ$˜$L˜Lšœžœ˜ L˜—š’œ‘ž‘žœ ‘œ‘œ ‘ž‘œ‘žœ žœžœ˜ZJšžœžœ˜!šœžœ ž˜Jšžœ˜Jšžœžœžœ ˜5—šžœ'žœ˜KJšœžœ˜—J˜J˜—š’œžœžœ˜Jšœ-žœ˜3J˜J˜——š ™š ’ œžœžœ žœ žœžœ˜PJ˜—š’œžœžœ˜Jšœ˜Jšœ žœ˜Jšœžœžœ˜Jšœžœ˜Jšœ žœžœ˜Jšœ žœžœ˜Jšœ$žœžœ˜.Jšžœžœžœ˜%Jšœ˜Jšœ žœΟc˜%J˜Jšœžœžœžœ ˜Jšœžœ˜"Jšœ žœ'˜6Jšœžœ˜Jšœ˜šžœ˜Jšžœžœ˜šžœ ˜ Jšœ žœžœ˜ šžœžœžœž˜Cšžœ˜Jšœ4˜4Jšœ,˜,JšœL˜LJ˜J˜—šžœ˜Jšœžœ0žœ˜Kšžœ žœžœ˜Jšœ+˜+šžœžœžœ˜Jšœ1žœžœ#˜nJšœ˜J˜—Jšœ$žœ žœ˜9J˜=J˜—J˜——Jšœ7˜7J˜—J˜—š’œžœžœžœ˜&codeš’ œžœ£>˜Zšžœžœž˜Nšžœžœžœ˜.Nšœ8˜8Nšžœ ˜—Nšœ˜—Jšœ˜Jšœžœ#˜)Jšœ˜—Jš ’œžœžœžœžœ˜AJš ’œžœžœžœžœ˜BJš ’œžœžœžœžœ ˜BJš’œžœžœ1˜HJš’ œ‘žœžœ‘œ ‘œ‘œ ‘œ‘œ ˜ZJš’œžœžœžœ‘œ‘œ ‘œ‘œ ˜Wš’œ‘ž‘œ‘œ˜šž˜Jšœžœžœ‘˜šž‘œžœžœ‘ž‘œžœ žœžœ˜BJšžœžœ ˜Jšžœžœ˜ —Jšžœ˜—Jšœ˜—šž˜Jš’œžœ žœžœžœžœžœ˜MJš ’œžœžœžœžœžœ ˜:š’œžœžœžœ˜ Jš žœžœžœžœžœ˜J˜-Jšžœžœ˜J˜—š’œžœžœ˜Jšžœžœžœžœ˜Jšžœ žœžœ˜8Jšœ˜Jšœ˜—š’ œžœ žœ˜'Jšœžœ˜šžœžœž˜šœ˜Jšœžœžœ)˜O—šœ˜Jšœžœžœ'˜M—šžœ˜ J˜šœžœ%˜+Jšžœžœ žœ žœ ˜>—šžœžœž˜Jšœ ‘œ$˜1Jšœ.˜.Jšœ0˜0Jšžœ˜—J˜——J˜—š’œžœ˜š’œžœ˜Jšœ6˜6Jšœ˜Jšœ˜—Jšœžœ ˜šžœžœž˜Jšœ&˜&Jšœ$˜$Jšœ"˜"Jšœ,˜,Jšœ,˜,Jšžœ"˜)—J˜—š’ œžœ˜)šžœ ˜ Jšžœ)žœ˜7šžœ˜J˜8Jšžœ7žœ ˜MJ˜——J˜—Jšœ žœ˜Jšœžœ ˜šžœžœž˜šΟz™šœΟb œ˜Jšœžœ˜J˜J˜3Jšœ₯œ₯œ˜1Jšœžœ˜4J˜J˜—šœ₯œ˜Jšœžœ˜ šžœ žœžœ˜Nšœ žœ˜)Nšœ0˜0Nšœ9˜9Nšœ7˜7Nšœ'˜'N˜—Jšœžœžœžœ ˜JJšœžœ žœ ˜"Jšœ0˜0Jš žœ žœžœžœžœ˜>J˜—šœ₯ œ˜J˜!Jšœ&žœžœ˜JJ˜——š€™šœ₯ œ˜Jšœžœ ˜J˜'Jš œžœžœžœCžœ ˜„J˜—šœ₯ œ˜Jšœžœ ˜Jšœžœ ˜Jšœžœ ˜Jšœžœ ˜š œžœ‘œ‘œ‘œ‘œ˜,Jš žœ ‘žœ ‘žœ ‘žœ ˜1—J˜'J˜—šœ₯œ˜J˜J˜šœžœ$˜*Jšžœ žœ žœ žœ˜=—Jšœ3˜3J˜—šœ₯œ˜Jšœ˜Jšœ/˜/J˜—šœ₯ œ˜Jšœžœ ˜Jšœžœ‘œ‘œ‘œ‘žœ ‘žœ ‘žœ ˜TJšœ#˜#J˜—šœ₯œ˜J˜6Jšœ&˜&J˜—šœ₯ œ˜J˜Jšœ(˜(J˜——š€™šœ₯œ˜Jšœ˜—šœ₯œ˜Jšœ˜—šœ₯ œ˜Jšœ˜—šœ₯œ˜Jšœ˜—šœ₯ œ˜Jšœ˜——š€™šœ₯ œ˜Jšœ0˜0šžœžœ˜:Jšžœ<˜@—šœ‘œ‘œ˜@Jšœ+žœž œ˜;—Jšžœžœžœ ˜2J˜—šœ₯ œ˜Jšœ/˜/Jšœ!˜!J˜—šœ₯œ˜šžœ žœ˜Jšœ*˜*šžœ˜ Jšžœ˜Jšžœ˜—J˜——šœ₯œ˜Jšžœ žœ˜#—šœ₯ œžœ žœ˜)Jšœžœ ˜Jšœ˜šœžœ)˜/Jšžœžœžœžœ˜H—J˜—šœ₯œžœ žœ˜-Jšœ žœ˜Jšœžœ#žœžœ˜PJšœ%˜%J˜—šœ₯œžœ žœ˜1Jšœ žœ˜Jšœžœ'žœžœ˜SJšœ(˜(J˜—šœ₯ œžœ žœ˜)Jšœžœ ˜Jšœžœ žœžœ˜HJšœ0˜0J˜—šœ₯œžœ žœ˜-J˜š œžœ‘œ‘œ‘œ˜&Jšžœžœžœžœ˜H—Jšœ4˜4J˜—šœ₯ œžœ žœ˜*J˜J˜Jšœžœ ˜Jš œžœ‘œžœžœ ˜