DIRECTORY Args, Ascii, Atom, Convert, FileNames, G3dBasic, G3dMatrix, G3dRender, G3dScene, G3dShape, G3dSweep, G3dTimeTrees, G3dVector, IO, Random, Real, Rope; G3dSceneProcsImpl: CEDAR PROGRAM IMPORTS Atom, Convert, FileNames, G3dMatrix, G3dScene, G3dShape, G3dRender, G3dTimeTrees, G3dVector, IO, Random, Real, Rope ~ BEGIN Arg: TYPE ~ Args.Arg; PropList: TYPE ~ Atom.PropList; Pair: TYPE ~ G3dBasic.Pair; Triple: TYPE ~ G3dBasic.Triple; Matrix: TYPE ~ G3dMatrix.Matrix; MatrixRep: TYPE ~ G3dMatrix.MatrixRep; Shape: TYPE ~ G3dShape.Shape; ShapeSequence: TYPE ~ G3dShape.ShapeSequence; Context3d: TYPE ~ G3dRender.Context3d; RGB: TYPE ~ G3dRender.RGB; RenderStyle: TYPE ~ G3dRender.RenderStyle; TextureStyle: TYPE ~ G3dRender.TextureStyle; ParseState: TYPE ~ G3dScene.ParseState; Material: TYPE ~ G3dScene.Material; MaterialSequence: TYPE ~ G3dScene.MaterialSequence; MaterialSequenceRep: TYPE ~ G3dScene.MaterialSequenceRep; SceneProc: TYPE ~ G3dScene.SceneProc; SurfaceDescription: TYPE ~ G3dSweep.SurfaceDescription; SurfaceDescriptionRep: TYPE ~ G3dSweep.SurfaceDescriptionRep; Variable: TYPE ~ G3dScene.Variable; VariableSequence: TYPE ~ G3dScene.VariableSequence; VariableSequenceRep: TYPE ~ G3dScene.VariableSequenceRep; SourceText: TYPE ~ G3dScene.SourceText; SourceTextRep: TYPE ~ G3dScene.SourceTextRep; InterpolationType: TYPE ~ G3dTimeTrees.InterpolationType; STREAM: TYPE ~ IO.STREAM; ROPE: TYPE ~ Rope.ROPE; StartBranch: SceneProc ~ { IF ps.inKey THEN { G3dScene.WriteLog[ps, "ERROR: can't StartBranch from within a key definition"]; RETURN; }; G3dTimeTrees.SetLocalTransform[ps.timeTree, ps.ctm]; G3dTimeTrees.PushTimeTree[ps.timeTree]; ps.matrixStack ¬ CONS[ps.ctm, ps.matrixStack]; ps.ctm ¬ G3dMatrix.Identity[]; G3dScene.WriteLog[ps, "Starting a new branch"]; ps.timeTree.activeNode.clientData ¬ NEW[SourceTextRep ¬ [ps.fileName, ps.index]]; }; EndBranch: SceneProc ~ { IF ps.inKey THEN { G3dScene.WriteLog[ps, "ERROR: can't EndBranch from within a key definition"]; RETURN; }; G3dTimeTrees.PopTimeTree[ps.timeTree]; ps.ctm ¬ ps.matrixStack.first; ps.matrixStack ¬ ps.matrixStack.rest; ps.changes ¬ Atom.PutPropOnList[ps.changes, $transform, $true]; G3dScene.WriteLog[ps, "Ending a branch"]; }; IdentityMatrix: SceneProc ~ { ps.ctm ¬ G3dMatrix.Identity[]; G3dScene.WriteLog[ps, "Current transformation set to identity"]; ps.changes ¬ Atom.PutPropOnList[ps.changes, $transform, $true]; }; Translate: SceneProc ~ { t: Triple ¬ [0.0, 0.0, 0.0]; axisA, factorA, yA, zA: Arg; [axisA, factorA, yA, zA] ¬ G3dScene.GetArgs[ps, args, "%sr[rr"]; SELECT TRUE FROM Eq[axisA.rope, "X"] => t.x ¬ factorA.real; Eq[axisA.rope, "Y"] => t.y ¬ factorA.real; Eq[axisA.rope, "Z"] => t.z ¬ factorA.real; Eq[axisA.rope, "XYZ"] => IF yA.ok AND zA.ok THEN t ¬ [factorA.real, yA.real, zA.real] ELSE G3dScene.ParseError["Translate XYZ requires 3 arguments"]; ENDCASE => G3dScene.ParseError["Translate axis must be X, Y, Z, or XYZ"]; UpdateCtm[G3dMatrix.MakeTranslate[t], ps]; G3dScene.WriteLog[ps, IO.PutFR["Translate by (%g %g %g)", [real[t.x]],[real[t.y]],[real[t.z]]]]; }; Scale: SceneProc ~ { t: Triple ¬ [1.0, 1.0, 1.0]; axisA, factorA, yA, zA: Arg; [axisA, factorA, yA, zA] ¬ G3dScene.GetArgs[ps, args, "%sr[rr"]; SELECT TRUE FROM Eq[axisA.rope, "X"] => t.x ¬ factorA.real; Eq[axisA.rope, "Y"] => t.y ¬ factorA.real; Eq[axisA.rope, "Z"] => t.z ¬ factorA.real; Eq[axisA.rope, "Uniform"] => t.x ¬ t.y ¬ t.z ¬ factorA.real; Eq[axisA.rope, "XYZ"] => IF yA.ok AND zA.ok THEN t ¬ [factorA.real, yA.real, zA.real] ELSE G3dScene.ParseError["Scale XYZ requires 3 arguments"]; ENDCASE => G3dScene.ParseError["Scale axis must be X, Y, Z, or XYZ"]; UpdateCtm[G3dMatrix.MakeScale[t], ps]; G3dScene.WriteLog[ps, IO.PutFR["Scaling by (%g %g %g)", [real[t.x]], [real[t.y]], [real[t.z]]]]; }; Shear: SceneProc ~ { ReplaceElementMatrix: PROC [x, y: INT, v: REAL] RETURNS [m: Matrix] ~ { m ¬ G3dMatrix.Identity[]; m[y][x] ¬ v; }; row, column: INT ¬ 0; axis1A, axis2A, factorA: Arg; [axis1A, axis2A, factorA] ¬ G3dScene.GetArgs[ps, args, "%ssr"]; row ¬ SELECT TRUE FROM Eq[axis1A.rope, "X"] => 0, Eq[axis1A.rope, "Y"] => 1, Eq[axis1A.rope, "Z"] => 2, ENDCASE => G3dScene.ParseError["Shear axis must be X, Y, or Z"]; column ¬ SELECT TRUE FROM Eq[axis2A.rope, "X"] => 0, Eq[axis2A.rope, "Y"] => 1, Eq[axis2A.rope, "Z"] => 2, ENDCASE => G3dScene.ParseError["Shear axis must be X, Y, or Z"]; UpdateCtm[ReplaceElementMatrix[row, column, factorA.real], ps]; G3dScene.WriteLog[ps, IO.PutFR["Shearing along axis %g with respect to axis %g by %g", IO.rope[axis1A.rope], IO.rope[axis2A.rope], IO.real[factorA.real]]]; }; Rotate: SceneProc ~ { axis: Triple ¬ [0.0, 0.0, 0.0]; axisA, thetaA, radiansA, ccwA: Arg; theta: REAL; [axisA, thetaA, radiansA, ccwA] ¬ G3dScene.GetArgs[ps, args, "%sr-radians%b-ccw%b"]; axis ¬ SELECT TRUE FROM Eq[axisA.rope, "X"] => [1.0, 0.0, 0.0], Eq[axisA.rope, "Y"] => [0.0, 1.0, 0.0], Eq[axisA.rope, "Z"] => [0.0, 0.0, 1.0], ENDCASE => G3dScene.ParseError["Rotation axis must be X, Y, or Z"]; theta ¬ thetaA.real; IF ccwA.ok THEN theta ¬ -theta; UpdateCtm[G3dMatrix.MakeRotate[axis, theta, NOT radiansA.ok], ps]; G3dScene.WriteLog[ps, IO.PutFR["Rotating around axis (%g %g %g) by %g", IO.real[axis.x], IO.real[axis.y], IO.real[axis.z], IO.real[thetaA.real]]]; }; RotateAxis: SceneProc ~ { axis: Triple ¬ [0.0, 0.0, 1.0]; base: Triple ¬ [0.0, 0.0, 0.0]; xA, yA, zA, tA, rA, bxA, byA, bzA: Arg; [xA, yA, zA, tA, rA, bxA, byA, bzA] ¬ G3dScene.GetArgs[ps, args, "-axis%rrr-angle%r-radians%b-base%rrr"]; axis ¬ [xA.real, yA.real, zA.real]; IF bxA.ok THEN base ¬ [bxA.real, byA.real, bzA.real]; UpdateCtm[G3dMatrix.MakeRotateAbout[axis, tA.real, NOT rA.ok, base], ps]; G3dScene.WriteLog[ps, IO.PutFR["Scaling around axis (%g %g %g) by %g", IO.real[axis.x], IO.real[axis.y], IO.real[axis.z], IO.real[tA.real]]]; }; ExplicitMatrix: SceneProc ~ { m00, m01, m02, m03, m10, m11, m12, m13, m20, m21, m22, m23, m30, m31, m32, m33: Arg; abs: Arg; m: Matrix ¬ G3dMatrix.Identity[]; [m00, m01, m02, m03, m10, m11, m12, m13, m20, m21, m22, m23, m30, m31, m32, m33, abs] ¬ G3dScene.GetArgs[ps, args, "%rrrrrrrrrrrrrrrr-absolute%b"]; m[0][0] ¬ m00.real; m[0][1] ¬ m01.real; m[0][2] ¬ m02.real; m[0][3] ¬ m03.real; m[1][0] ¬ m10.real; m[1][1] ¬ m11.real; m[1][2] ¬ m12.real; m[1][3] ¬ m13.real; m[2][0] ¬ m20.real; m[2][1] ¬ m21.real; m[2][2] ¬ m22.real; m[2][3] ¬ m23.real; m[3][0] ¬ m30.real; m[3][1] ¬ m31.real; m[3][2] ¬ m32.real; m[3][3] ¬ m33.real; IF abs.ok THEN ps.ctm ¬ G3dMatrix.Identity[]; UpdateCtm[m, ps]; G3dScene.WriteLog[ps, "Appended absolute matrix to current transformation"]; }; UpdateCtm: PROC [m: Matrix, ps: ParseState] ~ { ps.ctm ¬ G3dMatrix.Mul[m, ps.ctm]; ps.changes ¬ Atom.PutPropOnList[ps.changes, $transform, $true]; }; SaveMaterial: SceneProc ~ { name: ROPE ¬ GetRope[ps, args]; ps.materials ¬ AddToMaterialSequence[ps.materials, ps.currentMaterial]; ps.materials[ps.materials.length-1].name ¬ name; G3dScene.WriteLog[ps, IO.PutFR["Saved material %g", IO.rope[name]]]; }; UseMaterial: SceneProc ~ { name: ROPE ¬ GetRope[ps, args]; FOR i: INT IN [0..ps.materials.length) DO IF NOT Eq[name, ps.materials[i].name] THEN LOOP; ps.currentMaterial ¬ ps.materials[i]; G3dScene.WriteLog[ps, IO.PutFR["Using material %g", IO.rope[ps.currentMaterial.name]]]; EXIT; ENDLOOP; G3dScene.WriteLog[ps, IO.PutFR["Could not retrieve material %g", IO.rope[name]]]; ps.changes ¬ Atom.PutPropOnList[ps.changes, $diffuse, $true]; ps.changes ¬ Atom.PutPropOnList[ps.changes, $specular, $true]; ps.changes ¬ Atom.PutPropOnList[ps.changes, $metallicity, $true]; ps.changes ¬ Atom.PutPropOnList[ps.changes, $shininess, $true]; ps.changes ¬ Atom.PutPropOnList[ps.changes, $transmittance, $true]; ps.changes ¬ Atom.PutPropOnList[ps.changes, $color, $true]; }; MaterialBackFacesVisible: SceneProc ~ { b: BOOL ¬ ps.currentMaterial.backFaces ¬ Convert.BoolFromRope[GetRope[ps, args]]; G3dScene.WriteLog[ps, IO.PutFR["Back faces visible: %g", IO.bool[b]]]; }; MaterialRenderStyle: SceneProc ~ { style: ROPE ¬ GetRope[ps, args]; ps.currentMaterial.renderStyle ¬ SELECT TRUE FROM Eq[style, "default"], Eq[style, "faceted"] => faceted, Eq[style, "smooth"] => smooth, Eq[style, "lines"] => lines, Eq[style, "shadedLines"] => shadedLines, Eq[style, "hiddenLines"] => hiddenLines, Eq[style, "linesWnormals"] => linesWnormals, Eq[style, "controlPoints"] => controlPoints, ENDCASE => G3dScene.ParseError["no such render style"]; G3dScene.WriteLog[ps, Rope.Cat["Material render style set to: ", style]]; }; MaterialColor: SceneProc ~ { t: Triple; rA, gA, bA, scaleA: Arg; [rA, gA, bA, scaleA] ¬ G3dScene.GetArgs[ps, args, "%rrr-scale%b"]; t ¬ [rA.real, gA.real, bA.real]; ps.currentMaterial.color ¬ IF scaleA.ok THEN G3dVector.MulVectors[ps.currentMaterial.color, t] ELSE t; G3dScene.WriteLog[ps, IO.PutFR["Color set to (%g, %g, %g)", [real[t.x]],[real[t.y]],[real[t.z]]]]; ps.changes ¬ Atom.PutPropOnList[ps.changes, $color, $true]; }; MaterialDiffuse: SceneProc ~ { sA, scaleA: Arg; [sA, scaleA] ¬ G3dScene.GetArgs[ps, args, "%r-scale%b"]; ps.currentMaterial.diffuseReflectivity ¬ IF scaleA.ok THEN ps.currentMaterial.diffuseReflectivity*sA.real ELSE sA.real; G3dScene.WriteLog[ps, IO.PutFR["Diffuse Reflectivity set to %g", IO.real[ps.currentMaterial.diffuseReflectivity]]]; ps.changes ¬ Atom.PutPropOnList[ps.changes, $diffuse, $true]; }; MaterialSpecular: SceneProc ~ { sA, scaleA: Arg; [sA, scaleA] ¬ G3dScene.GetArgs[ps, args, "%r-scale%b"]; ps.currentMaterial.specularReflectivity ¬ IF scaleA.ok THEN ps.currentMaterial.specularReflectivity*sA.real ELSE sA.real; G3dScene.WriteLog[ps, IO.PutFR["Specular Reflectivity set to %g", IO.real[ps.currentMaterial.specularReflectivity]]]; ps.changes ¬ Atom.PutPropOnList[ps.changes, $specular, $true]; }; MaterialMetallicity: SceneProc ~ { sA, scaleA: Arg; [sA, scaleA] ¬ G3dScene.GetArgs[ps, args, "%r-scale%b"]; ps.currentMaterial.metallicity ¬ IF scaleA.ok THEN ps.currentMaterial.metallicity*sA.real ELSE sA.real; G3dScene.WriteLog[ps, IO.PutFR["Metallicity set to %g", IO.real[ps.currentMaterial.metallicity]]]; ps.changes ¬ Atom.PutPropOnList[ps.changes, $metallicity, $true]; }; MaterialShininess: SceneProc ~ { sA, scaleA: Arg; [sA, scaleA] ¬ G3dScene.GetArgs[ps, args, "%r-scale%b"]; ps.currentMaterial.shininess ¬ IF scaleA.ok THEN ps.currentMaterial.shininess*sA.real ELSE sA.real; G3dScene.WriteLog[ps, IO.PutFR["Shininess set to %g", IO.real[ps.currentMaterial.shininess]]]; ps.changes ¬ Atom.PutPropOnList[ps.changes, $shininess, $true]; }; MaterialTransmittance: SceneProc ~ { sA, scaleA: Arg; [sA, scaleA] ¬ G3dScene.GetArgs[ps, args, "%r-scale%b"]; ps.currentMaterial.transmittance ¬ IF scaleA.ok THEN ps.currentMaterial.transmittance*sA.real ELSE sA.real; G3dScene.WriteLog[ps, IO.PutFR["Transmittance set to %g", IO.real[ps.currentMaterial.transmittance]]]; ps.changes ¬ Atom.PutPropOnList[ps.changes, $transmittance, $true]; }; MaterialVisible: SceneProc ~ { b: BOOL ¬ ps.currentMaterial.visible ¬ Convert.BoolFromRope[GetRope[ps, args]]; G3dScene.WriteLog[ps, IO.PutFR["Material visibility: %g", IO.bool[b]]]; }; AddProperty: SceneProc ~ { in: IO.STREAM ¬ IO.RIS[args]; G3dScene.WriteLog[ps, "Adding property"]; ps.context3d.props ¬ Atom.PutPropOnList[ps.context3d.props,IO.GetRefAny[in],IO.GetRefAny[in]]; }; Render: SceneProc ~ { error: ROPE; G3dScene.WriteLog[ps, "Render"]; G3dTimeTrees.ReportTimeTree[ps.timeTree]; error ¬ G3dRender.Render[ps.context3d, NIL, FALSE]; IF error # NIL THEN G3dScene.WriteLog[ps, error]; }; AntiAliasing: SceneProc ~ { in: STREAM ¬ IO.RIS[args]; Skip[in]; G3dScene.WriteLog[ps, "Anti aliasing set"]; G3dRender.SetAntiAliasing[ps.context3d, IO.GetBool[in]]; }; DisplayMode: SceneProc ~ { mode: ROPE ¬ GetRope[ps, args]; G3dScene.WriteLog[ps, Rope.Cat["Set display mode: ", mode]]; }; DepthBuffering: SceneProc ~ { in: STREAM ¬ IO.RIS[args]; Skip[in]; G3dScene.WriteLog[ps, "Depth Buffering set"]; }; NormalCoding: SceneProc ~ { in: STREAM ¬ IO.RIS[args]; Skip[in]; G3dScene.WriteLog[ps, "Depth Buffering set"]; }; DisplayRegion: SceneProc ~ { xy: Pair ¬ GetPair[ps, args]; wh: Pair ¬ GetPair[ps, args]; G3dScene.WriteLog[ps, IO.PutFR["DisplayRegion: [%g, %g, %g, %g]", IO.real[xy.x], IO.real[xy.y], IO.real[wh.x], IO.real[wh.y]]]; G3dRender.SetWindow[ps.context3d, [xy.x, xy.y, wh.x, wh.y]]; }; Viewport: SceneProc ~ { xy: Pair ¬ GetPair[ps, args]; wh: Pair ¬ GetPair[ps, args]; G3dScene.WriteLog[ps, 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[ps.context3d, [xy.x, xy.y, wh.x, wh.y]]; }; BackgroundColor: SceneProc ~ { t: Triple ¬ GetTriple[ps, args]; G3dScene.WriteLog[ps, IO.PutFR["Background: (%g, %g, %g)", [real[t.x]], [real[t.y]], [real[t.z]]]]; G3dRender.SetBackgroundColor[ps.context3d, [t.x, t.y, t.z]]; }; BackgroundImage: SceneProc ~ { name: ROPE ¬ GetRope[ps, args]; G3dScene.WriteLog[ps, Rope.Cat["Background image: ", name]]; G3dRender.SetBackgroundImage[ps.context3d, name]; }; EnableBackground: SceneProc ~ { G3dScene.WriteLog[ps, "EnableBackground set"]; G3dRender.EnableClear[ps.context3d, IO.GetBool[IO.RIS[args]]]; }; UpdateCamera: SceneProc ~ { AddRealToMsg: PROC [r: REAL] ~ {msg ¬ Rope.Cat[msg, IO.PutFR["%g", IO.real[r]]]}; AddTripleToMsg: PROC [t: Triple] ~ { msg ¬ Rope.Cat[msg, IO.PutFR["(%g, %g, %g)", [real[t.x]], [real[t.y]], [real[t.z]]]]; }; msg: ROPE ¬ IO.PutFR["Set camera %g: ", IO.refAny[data]]; ps.shouldRepaint ¬ TRUE; SELECT data FROM $FieldOfView => AddRealToMsg[ps.context3d.fieldOfView ¬ GetReal[ps, args]]; $Roll => AddRealToMsg[ps.context3d.rollAngle ¬ GetReal[ps, args]]; ENDCASE => { t: Triple ¬ GetTriple[ps, args]; AddTripleToMsg[t]; SELECT data FROM $EyePoint => ps.context3d.eyePoint ¬ t; $LookAt => ps.context3d.lookAt ¬ t; $Up => ps.context3d.upDirection ¬ t; ENDCASE; }; G3dScene.WriteLog[ps, msg]; }; ReadShape: SceneProc ~ { name, instanceName: ROPE ¬ NIL; nameA, instanceNameA: Arg; [nameA, instanceNameA] ¬ G3dScene.GetArgs[ps, args, "%s[s"]; name ¬ nameA.rope; IF instanceNameA.ok THEN instanceName ¬ instanceNameA.rope; IF instanceName = NIL THEN { index: INT ¬ IF ps.context3d.shapes # NIL THEN ps.context3d.shapes.length ELSE 0; instanceName ¬ IO.PutFR["%g.%g", IO.rope[FileNames.GetShortName[name]], IO.int[index]]; }; IF Rope.Find[name, "/"] = -1 AND Rope.Find[name, ">"] = -1 THEN name ¬ Rope.Cat[ps.directory, name]; G3dRender.AddShapeFromFile[ps.context3d, instanceName, name ! G3dShape.Error => G3dScene.ParseError[reason]]; ps.currentShape ¬ ps.context3d.shapes[ps.context3d.shapes.length-1]; G3dScene.AssignCtmToShape[ps, ps.currentShape]; G3dScene.InheritMaterial[ps]; G3dScene.WriteLog[ps, Rope.Cat["Read shape: ", name, " [", instanceName, "]"]]; }; WriteShape: SceneProc ~ { fileName: ROPE; shapes: ShapeSequence ¬ ps.context3d.shapes; shapeNameA, fileNameA, transformA: Arg; [shapeNameA, fileNameA, transformA] ¬ G3dScene.GetArgs[ps, args, "%s-fileName%s-transform%b"]; fileName ¬ IF fileNameA.ok THEN fileNameA.rope ELSE Rope.Cat[shapeNameA.rope, ".shape"]; FOR i: NAT IN [0..shapes.length) DO shape: Shape ¬ shapes[i]; IF NOT Eq[shape.name, shapeNameA.rope] THEN LOOP; shape ¬ G3dShape.CopyShape[shapes[i]]; IF transformA.ok THEN G3dShape.TransformVertices[shape, shape.matrix]; G3dShape.ShapeToFile[fileName, shape, TRUE, FALSE, "shape written from context3d"]; EXIT; ENDLOOP; G3dScene.WriteLog[ps, Rope.Cat["Wrote shape ", shapeNameA.rope, " to file ", fileName]]; }; WriteAllShapes: SceneProc ~ { shapes: ShapeSequence ¬ ps.context3d.shapes; FOR i: NAT IN [0..shapes.length) DO fileName: ROPE ¬ Rope.Cat[ps.directory, shapes[i].name]; shape: Shape ¬ G3dShape.CopyShape[shapes[i]]; shape.matrix ¬ shapes[i].matrix; G3dShape.TransformVertices[shape, shape.matrix]; G3dShape.UnitizeVertexNormals[shape]; G3dShape.ShapeToFile[fileName, shape, TRUE, FALSE, "shape written from context3d"]; ENDLOOP; G3dScene.WriteLog[ps, "Wrote all shapes to files"]; }; DeleteShape: SceneProc ~ { shapeName: ROPE ¬ GetRope[ps, args]; G3dRender.DeleteShape[ps.context3d, shapeName]; }; DeleteAllShapes: SceneProc ~ { G3dRender.DeleteAllShapes[ps.context3d]; }; InvertNormals: SceneProc ~ { IF ps.currentShape # NIL THEN { G3dScene.WriteLog[ps, Rope.Cat["Negate normals of ", ps.currentShape.name]]; G3dShape.NegateVertexNormals[ps.currentShape]; }; }; Triangulate: SceneProc ~ { G3dScene.WriteLog[ps, Rope.Cat["Triangulate shape: ", ps.currentShape.name]]; G3dShape.Triangulate[ps.currentShape]; }; ReversePolygons: SceneProc ~ { G3dScene.WriteLog[ps, Rope.Cat["Reverse polygons of ", ps.currentShape.name]]; G3dShape.ReversePolygons[ps.currentShape]; }; OpenContours: SceneProc ~ { sd: SurfaceDescription ¬ NEW[SurfaceDescriptionRep ¬ []]; sd.open ¬ TRUE; FOR i: INT IN [0 .. ps.currentShape.surfaces.length) DO ps.currentShape.surfaces[i].clientData ¬ sd; ENDLOOP; G3dScene.WriteLog[ps, Rope.Cat["Making an open surface of ", ps.currentShape.name]]; }; AddAxes: SceneProc ~ { nReticles: NAT ¬ 20; size: REAL ¬ 1.0; scale: Triple ¬ [1, 1, 1]; origin: Triple ¬ [0, 0, 0]; x, y, z, s, sx, sy, sz, n: Arg; [x, y, z, s, sx, sy, sz, n] ¬ G3dScene.GetArgs[ps, args, "-origin%rrr-size%r-scale%rrr-nReticles%i"]; IF x.ok AND y.ok AND z.ok THEN origin ¬ [x.real, y.real, z.real]; IF sx.ok AND sy.ok AND sz.ok THEN scale ¬ [sx.real, sy.real, sz.real]; IF s.ok THEN size ¬ s.real; IF n.ok THEN nReticles ¬ n.int; G3dScene.WriteLog[ps, "Adding axes"]; G3dRender.AddAxes[ps.context3d, origin, size, scale, nReticles]; }; SetTexture: SceneProc ~ { typeA, filenameA: Arg; [typeA, filenameA] ¬ G3dScene.GetArgs[ps, args, "%ss"]; SELECT TRUE FROM Eq[typeA.rope, "intensity"] => ps.currentMaterial.textureIntensityName ¬ filenameA.rope; Eq[typeA.rope, "color"] => ps.currentMaterial.textureColorName ¬ filenameA.rope; Eq[typeA.rope, "bump"] => ps.currentMaterial.textureBumpName ¬ filenameA.rope; ENDCASE => G3dScene.ParseError["Texture type must be intensity, color, or bump"]; G3dScene.WriteLog[ps, Rope.Cat["Enabled texture of type ", typeA.rope, " from file ", filenameA.rope]]; }; DisableAllTextures: SceneProc ~ { ps.currentMaterial.textureIntensityName ¬ NIL; ps.currentMaterial.textureColorName ¬ NIL; ps.currentMaterial.textureBumpName ¬ NIL; G3dScene.WriteLog[ps, "Disabled all textures"]; }; DisableTexture: SceneProc ~ { type: ROPE ¬ GetRope[ps, args]; SELECT TRUE FROM Eq[type, "intensity"] => ps.currentMaterial.textureIntensityName ¬ NIL; Eq[type, "color"] => ps.currentMaterial.textureColorName ¬ NIL; Eq[type, "bump"] => ps.currentMaterial.textureBumpName ¬ NIL; ENDCASE => G3dScene.ParseError["Texture type must be intensity, color, or bump"]; G3dScene.WriteLog[ps, Rope.Concat["Disabled texture of type ", type]]; }; OffsetTexture: SceneProc ~ { p: Pair ¬ ps.currentMaterial.textureOffset ¬ GetPair[ps, args]; G3dScene.WriteLog[ps, IO.PutFR["Set texture offset to %g %g", [real[p.x]], [real[p.y]]]]; }; ScaleTexture: SceneProc ~ { p: Pair ¬ ps.currentMaterial.textureScale ¬ GetPair[ps, args]; G3dScene.WriteLog[ps, IO.PutFR["Set texture scale to %g %g", [real[p.x]], [real[p.y]]]]; }; ScaleBumps: SceneProc ~ { scale: REAL ¬ Convert.RealFromRope[GetRope[ps, args]]; ps.currentMaterial.bumpScale ¬ scale; G3dScene.WriteLog[ps, IO.PutFR["Set bump scale to %g", IO.real[scale]]]; }; FilterTexture: SceneProc ~ { b: BOOL ¬ ps.currentMaterial.textureFiltering ¬ Convert.BoolFromRope[GetRope[ps, args]]; G3dScene.WriteLog[ps, IO.PutFR["Texture filtering set to %b", IO.bool[b]]]; }; AmbientLight: SceneProc ~ { t: Triple ¬ GetTriple[ps, args]; G3dRender.SetAmbientLight[ps.context3d, [t.x, t.y, t.z]]; G3dScene.WriteLog[ps, IO.PutFR["Ambient light set to (%g %g %g)", IO.real[t.x], IO.real[t.y], IO.real[t.z]]]; }; AddLight: SceneProc ~ { AutoLightName: PROC [context3d: Context3d, type: ROPE] RETURNS [ROPE] ~ { index: INT ¬ IF context3d.lightSources = NIL THEN 0 ELSE context3d.lightSources.length; RETURN[IO.PutFR["%g%g", IO.rope[type], IO.int[index]]]; }; name: ROPE ¬ AutoLightName[ps.context3d, "AutoLight"]; nameA, xA, yA, zA, rA, gA, bA: Arg; rgb: RGB ¬ [1.0, 1.0, 1.0]; [xA, yA, zA, rA, gA, bA, nameA] ¬ G3dScene.GetArgs[ps, args, "-position%rrr-color%rrr-name%s"]; IF nameA.ok THEN name ¬ nameA.rope; IF rA.ok THEN rgb ¬ [rA.real, gA.real, bA.real]; IF xA.ok AND rA.ok THEN G3dRender.AddLight[ps.context3d, name, [xA.real, yA.real, zA.real], rgb]; G3dScene.WriteLog[ps, IO.PutFLR["Light %g placed at (%g %g %g) with color (%g %g %g)", LIST[IO.rope[name], IO.real[xA.real], IO.real[yA.real], IO.real[zA.real], IO.real[rgb.R], IO.real[rgb.G], IO.real[rgb.B]]]]; }; SetVariable: SceneProc ~ { Translate: Rope.TranslatorType ~ {RETURN[IF old = '\t THEN ' ELSE old]}; v: Variable; cleanArgs: ROPE ¬ Rope.Translate[StripLeadingBlanks[args],,, Translate]; endOfName: INT ¬ Rope.Find[cleanArgs, " "]; IF endOfName < 0 THEN RETURN; v.name ¬ Rope.Substr[cleanArgs, 0, endOfName]; v.value ¬ Rope.Substr[cleanArgs, endOfName+1]; IF ps.variables = NIL THEN { ps.variables ¬ AddToVariableSequence[NIL, v]; RETURN; }; FOR i: INT IN [0..ps.variables.length) DO IF NOT Eq[ps.variables[i].name, v.name] THEN LOOP; ps.variables[i].value ¬ v.value; RETURN; ENDLOOP; ps.variables ¬ AddToVariableSequence[ps.variables, v]; G3dScene.WriteLog[ps, IO.PutFR["Set variable <%g> to value <%g>", IO.rope[v.name], IO.rope[v.value]]]; }; UnSetVariable: SceneProc ~ { key: ROPE ¬ GetRope[ps, args]; IF ps.variables # NIL AND ps.variables.length > 0 THEN FOR i: INT IN [0..ps.variables.length) DO IF NOT Eq[ps.variables[i].name, key] THEN LOOP; FOR j: INT IN [i+1..ps.variables.length) DO ps.variables[j-1] ¬ ps.variables[j]; ENDLOOP; ps.variables.length ¬ ps.variables.length-1; EXIT; ENDLOOP; G3dScene.WriteLog[ps, Rope.Cat["Unset variable <", key, ">"]]; }; RandomSeed: SceneProc ~ { seed: INT ¬ GetInt[ps, args]; ps.randomStream ¬ Random.Create[0, seed]; }; LockNode: SceneProc ~ { G3dTimeTrees.LockActiveNode[ps.timeTree]; }; UnlockNode: SceneProc ~ { G3dTimeTrees.UnlockActiveNode[ps.timeTree]; }; GetInterpolationType: PROC [r: ROPE] RETURNS [InterpolationType] ~ { SELECT TRUE FROM Rope.Equal[r, "constant", FALSE] => RETURN[constant]; Rope.Equal[r, "linear", FALSE] => RETURN[linear]; Rope.Equal[r, "smooth", FALSE] => RETURN[smooth]; ENDCASE => RETURN[smooth]; }; DiffuseInterpolation: SceneProc ~ { type: ROPE ¬ GetRope[ps, args]; G3dTimeTrees.SetDiffuseInterpolationType[ps.timeTree, GetInterpolationType[type]]; }; SpecularInterpolation: SceneProc ~ { type: ROPE ¬ GetRope[ps, args]; G3dTimeTrees.SetSpecularInterpolationType[ps.timeTree, GetInterpolationType[type]]; }; MetallicityInterpolation: SceneProc ~ { type: ROPE ¬ GetRope[ps, args]; G3dTimeTrees.SetMetallicityInterpolationType[ps.timeTree, GetInterpolationType[type]]; }; ShininessInterpolation: SceneProc ~ { type: ROPE ¬ GetRope[ps, args]; G3dTimeTrees.SetShininessInterpolationType[ps.timeTree, GetInterpolationType[type]]; }; TransmittanceInterpolation: SceneProc ~ { type: ROPE ¬ GetRope[ps, args]; G3dTimeTrees.SetTransmittanceInterpolationType[ps.timeTree, GetInterpolationType[type]]; }; ColorInterpolation: SceneProc ~ { type: ROPE ¬ GetRope[ps, args]; G3dTimeTrees.SetColorInterpolationType[ps.timeTree, GetInterpolationType[type]]; }; TransformInterpolation: SceneProc ~ { type: ROPE ¬ GetRope[ps, args]; G3dTimeTrees.SetTransformInterpolationType[ps.timeTree, GetInterpolationType[type]]; }; StartKeys: SceneProc ~ { IF ps.inKey THEN { G3dScene.WriteLog[ps, "ERROR: can't StartKey from within a key definition"]; RETURN; }; ps.inKey ¬ TRUE; ps.ctm ¬ G3dMatrix.Identity[]; ps.changes ¬ NIL; }; EndKeys: SceneProc ~ { ps.inKey ¬ FALSE; ps.changes ¬ NIL; ps.ctm ¬ G3dMatrix.Identity[]; }; Time: SceneProc ~ { time: REAL ¬ GetReal[ps, args]; IF Atom.GetPropFromList[ps.changes, $diffuse] # NIL THEN G3dTimeTrees.AssignDiffuse[ps.timeTree, time, ps.currentMaterial.diffuseReflectivity]; IF Atom.GetPropFromList[ps.changes, $specular] # NIL THEN G3dTimeTrees.AssignSpecular[ps.timeTree, time, ps.currentMaterial.specularReflectivity]; IF Atom.GetPropFromList[ps.changes, $metallicity] # NIL THEN G3dTimeTrees.AssignMetallicity[ps.timeTree, time, ps.currentMaterial.metallicity]; IF Atom.GetPropFromList[ps.changes, $shininess] # NIL THEN G3dTimeTrees.AssignShininess[ps.timeTree, time, ps.currentMaterial.shininess]; IF Atom.GetPropFromList[ps.changes, $transmittance] # NIL THEN G3dTimeTrees.AssignTransmittance[ps.timeTree, time, ps.currentMaterial.transmittance]; IF Atom.GetPropFromList[ps.changes, $color] # NIL THEN G3dTimeTrees.AssignColor[ps.timeTree, time, ps.currentMaterial.color]; IF Atom.GetPropFromList[ps.changes, $transform] # NIL THEN G3dTimeTrees.AssignTransform[ps.timeTree, time, ps.ctm]; }; StrobeScene: SceneProc ~ { time: REAL ¬ GetReal[ps, args]; G3dTimeTrees.StrobeTimeTree[ps.timeTree, time]; }; Skip: PROC [in: STREAM] ~ { 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; }; RealFromStream: PROC [in: STREAM] RETURNS [r: REAL] ~ {Skip[in]; r ¬ IO.GetReal[in]}; IntFromStream: PROC [in: STREAM] RETURNS [i: INT] ~ {Skip[in]; i ¬ IO.GetInt[in]}; GetInt: PROC [ps: ParseState, args: ROPE] RETURNS [i: INT] ~ { i ¬ IntFromStream[IO.RIS[G3dScene.SubstituteVariables[ps.variables, args]]]; }; GetReal: PROC [ps: ParseState, args: ROPE] RETURNS [r: REAL] ~ { r ¬ RealFromStream[IO.RIS[G3dScene.SubstituteVariables[ps.variables, args]]]; }; GetPair: PROC [ps: ParseState, args: ROPE] RETURNS [p: Pair] ~ { in: STREAM ¬ IO.RIS[G3dScene.SubstituteVariables[ps.variables, args]]; p.x ¬ RealFromStream[in]; p.y ¬ RealFromStream[in]; }; GetTriple: PROC [ps: ParseState, args: ROPE] RETURNS [t: Triple] ~ { in: STREAM ¬ IO.RIS[G3dScene.SubstituteVariables[ps.variables, args]]; t.x ¬ RealFromStream[in]; t.y ¬ RealFromStream[in]; t.z ¬ RealFromStream[in]; }; GetRope: PROC [ps: ParseState, args: ROPE] RETURNS [r: ROPE] ~ { in: STREAM ¬ IO.RIS[G3dScene.SubstituteVariables[ps.variables, args]]; Skip[in]; r ¬ IO.GetTokenRope[in, IO.IDProc].token; }; StripLeadingBlanks: PROC [input: ROPE] RETURNS [ROPE] ~ { RETURN[Rope.Substr[input, IO.SkipWhitespace[IO.RIS[input]]]]; }; Eq: PROC [r1, r2: ROPE] RETURNS [b: BOOL] ~ {b ¬ Rope.Equal[r1, r2, FALSE]}; AddToVariableSequence: PROC [variables: VariableSequence, variable: Variable] RETURNS [VariableSequence] ~ { IF variables = NIL THEN variables ¬ NEW[VariableSequenceRep[1]]; IF variables.length = variables.maxLength THEN variables ¬ LengthenVariables[variables]; variables[variables.length] ¬ variable; variables.length ¬ variables.length+1; RETURN[variables]; }; LengthenVariables: PROC [variables: VariableSequence, amount: REAL ¬ 1.3] RETURNS [new: VariableSequence] ~ { newLength: NAT ¬ MAX[Real.Ceiling[amount*variables.maxLength], 3]; new ¬ NEW[VariableSequenceRep[newLength]]; FOR i: NAT IN [0..variables.length) DO new[i] ¬ variables[i]; ENDLOOP; new.length ¬ variables.length; }; AddToMaterialSequence: PROC [materials: MaterialSequence, material: Material] RETURNS [MaterialSequence] ~ { IF materials = NIL THEN materials ¬ NEW[MaterialSequenceRep[1]]; IF materials.length = materials.maxLength THEN materials ¬ LengthenMaterials[materials]; materials[materials.length] ¬ material; materials.length ¬ materials.length+1; RETURN[materials]; }; LengthenMaterials: PROC [materials: MaterialSequence, amount: REAL ¬ 1.3] RETURNS [new: MaterialSequence] ~ { newLength: NAT ¬ MAX[Real.Ceiling[amount*materials.maxLength], 3]; new ¬ NEW[MaterialSequenceRep[newLength]]; FOR i: NAT IN [0..materials.length) DO new[i] ¬ materials[i]; ENDLOOP; new.length ¬ materials.length; }; RegisterProcs: PROC ~ { G3dScene.RegisterProc["Identity", IdentityMatrix]; G3dScene.RegisterProc["StartBranch", StartBranch]; G3dScene.RegisterProc["{", StartBranch]; G3dScene.RegisterProc["EndBranch", EndBranch]; G3dScene.RegisterProc["}", EndBranch]; G3dScene.RegisterProc["Translate", Translate]; G3dScene.RegisterProc["T", Translate]; G3dScene.RegisterProc["Scale", Scale]; G3dScene.RegisterProc["S", Scale]; G3dScene.RegisterProc["Shear", Shear]; G3dScene.RegisterProc["Rotate", Rotate]; G3dScene.RegisterProc["R", Rotate]; G3dScene.RegisterProc["RotateAxis", RotateAxis]; G3dScene.RegisterProc["ExplicitMatrix", ExplicitMatrix]; G3dScene.RegisterProc["AmbientLight", AmbientLight]; G3dScene.RegisterProc["AddLight", AddLight]; G3dScene.RegisterProc["AddProperty", AddProperty]; G3dScene.RegisterProc["Render", Render]; G3dScene.RegisterProc["AntiAliasing", AntiAliasing]; G3dScene.RegisterProc["DisplayMode", DisplayMode]; G3dScene.RegisterProc["DepthBuffering", DepthBuffering]; G3dScene.RegisterProc["NormalCoding", NormalCoding]; G3dScene.RegisterProc["DisplayRegion", DisplayRegion]; G3dScene.RegisterProc["Viewport", Viewport]; G3dScene.RegisterProc["BackgroundColor", BackgroundColor]; G3dScene.RegisterProc["BackgroundImage", BackgroundImage]; G3dScene.RegisterProc["EnableBackground", EnableBackground]; G3dScene.RegisterProc["FieldOfView", UpdateCamera, $FieldOfView]; G3dScene.RegisterProc["EyePoint", UpdateCamera, $EyePoint]; G3dScene.RegisterProc["LookAt", UpdateCamera, $LookAt]; G3dScene.RegisterProc["Up", UpdateCamera, $Up]; G3dScene.RegisterProc["Roll", UpdateCamera, $Roll]; G3dScene.RegisterProc["ReadShape", ReadShape]; G3dScene.RegisterProc["WriteShape", WriteShape]; G3dScene.RegisterProc["WriteAllShapes", WriteAllShapes]; G3dScene.RegisterProc["DeleteShape", DeleteShape]; G3dScene.RegisterProc["DeleteAllShapes", DeleteAllShapes]; G3dScene.RegisterProc["InvertNormals", InvertNormals]; G3dScene.RegisterProc["Triangulate", Triangulate]; G3dScene.RegisterProc["ReversePolygons", ReversePolygons]; G3dScene.RegisterProc["OpenContours", OpenContours]; G3dScene.RegisterProc["AddAxes", AddAxes]; G3dScene.RegisterProc["SaveMaterial", SaveMaterial]; G3dScene.RegisterProc["UseMaterial", UseMaterial]; G3dScene.RegisterProc["BackFacesVisible", MaterialBackFacesVisible]; G3dScene.RegisterProc["RenderStyle", MaterialRenderStyle]; G3dScene.RegisterProc["Color", MaterialColor]; G3dScene.RegisterProc["Diffuse", MaterialDiffuse]; G3dScene.RegisterProc["Specular", MaterialSpecular]; G3dScene.RegisterProc["Metallicity", MaterialMetallicity]; G3dScene.RegisterProc["Shininess", MaterialShininess]; G3dScene.RegisterProc["Transmittance", MaterialTransmittance]; G3dScene.RegisterProc["Visible", MaterialVisible]; G3dScene.RegisterProc["OffsetTexture", OffsetTexture]; G3dScene.RegisterProc["ScaleTexture", ScaleTexture]; G3dScene.RegisterProc["ScaleBumps", ScaleBumps]; G3dScene.RegisterProc["FilterTexture", FilterTexture]; G3dScene.RegisterProc["SetTexture", SetTexture]; G3dScene.RegisterProc["DisableTexture", DisableTexture]; G3dScene.RegisterProc["DisableAllTextures", DisableAllTextures]; G3dScene.RegisterProc["Set", SetVariable]; G3dScene.RegisterProc["UnSet", UnSetVariable]; G3dScene.RegisterProc["RandomSeed", RandomSeed]; G3dScene.RegisterProc["StartKeys", StartKeys]; G3dScene.RegisterProc["EndKeys", EndKeys]; G3dScene.RegisterProc["Time", Time]; G3dScene.RegisterProc["StrobeScene", StrobeScene]; G3dScene.RegisterProc["DiffuseInterpolation", DiffuseInterpolation]; G3dScene.RegisterProc["SpecularInterpolation", SpecularInterpolation]; G3dScene.RegisterProc["MetallicityInterpolation", MetallicityInterpolation]; G3dScene.RegisterProc["ShininessInterpolation", ShininessInterpolation]; G3dScene.RegisterProc["TransmittanceInterpolation", TransmittanceInterpolation]; G3dScene.RegisterProc["ColorInterpolation", ColorInterpolation]; G3dScene.RegisterProc["TransformInterpolation", TransformInterpolation]; G3dScene.RegisterProc["LockNode", LockNode]; G3dScene.RegisterProc["UnlockNode", UnlockNode]; }; RegisterProcs[]; END. .. † G3dSceneProcsImpl.mesa Copyright Σ 1985, 1992 by Xerox Corporation. All rights reserved. Glassner, July 5, 1990 1:48:22 pm PDT Bloomenthal, July 15, 1992 11:31 pm PDT Imported Types Matrix Procedures Material Procedures Context3d Procedures Rendering Procedures G3dRender.LoadDisplayClass[ps.context3d, SELECT TRUE FROM Eq[mode, "fullColor"] => $FullColor, Eq[mode, "dither"] => $PseudoColor, ENDCASE => $Gray]; G3dRenderWithPixels.DepthBuffering[ps.context3d, IO.GetBool[in]]; G3dRenderWithPixels.NormalBuffering[ps.context3d, IO.GetBool[in]]; Backgound Procedures Camera Procedures Shape Procedures Shape Processing Texturing Procedures Lighting Procedures Variable Procedures v.value _ G3dScene.SubstituteVariables[ps.variables, v.value]; Animation Procedures G3dScene.MakeTransformNode[ps]; G3dScene.MakeKeysNode[ps]; attach the relevant information to the timeTree, based on changes field in ps Support Procedures Sequence Support Initialization matrix stack control translation scaling shearing rotation experts lighting control context3d rendering background camera shape io shapes materials texturing variables animation Start Procedures ΚQ•NewlineDelimiter –"cedarcode" style™šœ™Jšœ Οeœ5™AJšœ%™%J™'J™JšΟk œžœ˜ŸJ˜—šΡblnœžœž˜ Jšžœ^žœ˜|J˜—Jšœž˜headšΟl™Jšœ žœ ˜Jšœ žœ˜#Jšœ žœ˜ Jšœ žœ˜#Jšœ žœ˜$Jšœžœ˜)Jšœ žœ˜!Jšœžœ˜/Jšœžœ˜)Jšžœžœ žœ˜Jšœžœ˜-Jšœžœ˜/Jšœžœ˜*Jšœžœ˜'Jšœžœ˜4Jšœžœ ˜9Jšœžœ˜(Jšœžœ˜8Jšœžœ"˜=Jšœžœ˜'Jšœžœ˜4Jšœžœ ˜9Jšœžœ˜*Jšœžœ˜/Jšœžœ"˜:Jšžœžœžœžœ˜Jšžœžœžœ˜—š ™šΟn œ˜šžœ žœ˜JšœO˜OJšžœ˜J˜—J˜4J˜'Jšœžœ˜.J˜JšœΟsœ˜/Jšœ$žœ*˜QJ˜J˜—š‘ œ˜šžœ žœ˜JšœM˜MJšžœ˜J˜—J˜&J˜J˜%J˜?Jšœ’œ˜)J˜J˜—š‘œ˜J˜Jšœ’œ*˜@J˜?J˜J˜—š‘ œ˜J˜J˜J˜@šžœžœž˜J˜*J˜*J˜*šœžœžœ˜+Jšžœ%˜)Jšžœ;˜?—JšžœB˜I—Jšœ*˜*Jšœ’žœ’œ’œ’œ’œ’œ&˜`J˜J˜—š‘œ˜J˜J˜J˜@šžœžœž˜J˜*J˜*J˜*J˜<šœžœžœ˜+Jšžœ%˜)Jšžœ7˜;—Jšžœ>˜E—Jšœ&˜&Jšœ’žœ’œ’œ’œ ’œ ’œ˜`J˜J˜—š‘œ˜š ‘œžœžœžœžœ˜GJ˜J˜ J˜—Jšœ žœ˜J˜J˜?šœžœžœž˜Jšœ˜Jšœ˜Jšœ˜Jšžœ9˜@—šœ žœžœž˜Jšœ˜Jšœ˜Jšœ˜Jšžœ9˜@—Jšœ?˜?šœ’žœ>˜VJšžœžœžœ˜D—J˜J˜—š‘œ˜J˜J˜#Jšœžœ˜ J˜Tšœžœžœž˜Jšœ'˜'Jšœ'˜'Jšœ'˜'Jšžœ<˜C—J˜Jšžœ žœ˜Jšœ,žœ˜BJš œ’žœ0žœžœžœžœ˜’J˜J˜—š‘ œ˜J˜J˜J˜'šœ#’œ˜%JšœC˜C—J˜#Jšžœžœ'˜5Jšœ3žœ˜Išœ’žœ.˜FJšžœžœžœžœ˜F—J˜J˜—š‘œ˜J˜TJ˜ J˜!šœU’œ˜WJšœ;˜;—J˜OJ˜OJ˜OJ˜OJšžœžœ˜-Jšœ˜Jšœ’œ6˜LJ˜J˜—š‘ œžœ ˜/J˜"J˜?J˜——š ™š‘ œ˜Jšœžœ˜J˜GJ˜0Jš œ’žœ’œ’žœ˜DJ˜J˜—š‘ œ˜Jšœžœ˜šžœžœžœžœ˜*Jšžœžœ žœžœ˜0J˜%Jš œ’žœ’œ’žœ!˜WJšžœ˜Jšžœ˜—Jš œ’žœ#’œ’žœ˜QJ˜=J˜>J˜AJ˜?J˜CJ˜;J˜J˜—š‘œ˜'JšœžœJ˜QJš œ’žœ’œ’žœ ˜FJ˜J˜—š‘œ˜"Jšœžœ˜ šœ žœžœž˜1Jšœ6˜6Jšœ˜Jšœ˜Jšœ(˜(Jšœ(˜(Jšœ,˜,Jšœ,˜,Jšžœ0˜7—JšœI˜IJ˜J˜—š‘ œ˜J˜ J˜J˜BJ˜ šœžœ ˜(Jšžœ2žœ˜>—Jšœ’žœ ’œ’œ’œ’œ’œ’œ&˜bJ˜;J˜J˜—š‘œ˜J˜J˜8˜(Jšžœ žœ/žœ ˜N—Jš œ’žœ ’œ’œ’žœ0˜sJ˜=J˜J˜—š‘œ˜J˜J˜8˜)Jšžœ žœ0žœ ˜O—Jš œ’žœ!’œ’œ’žœ1˜uJ˜>Jšœ˜J˜—š‘œ˜"J˜J˜8˜ Jšžœ žœ'žœ ˜F—Jš œ’žœ’œ’œ’žœ(˜bJ˜AJ˜J˜—š‘œ˜ J˜J˜8˜Jšžœ žœ%žœ ˜D—Jš œ’žœ’œ’œ’žœ&˜^J˜?J˜J˜—š‘œ˜$J˜J˜8šœ#žœ ˜0Jšžœ)žœ ˜;—Jš œ’žœ’œ’œ’žœ*˜fJ˜CJ˜J˜—š‘œ˜JšœžœH˜OJš œ’žœ’œ’žœ ˜GJ˜——š ™šΠbn œ˜Jšœž œžœžœ˜Jšœ)˜)Jšœ;žœžœ˜^J˜——š ™š£œ˜Jšœžœ˜ Jšœ ˜ Jšœ)˜)Jšœ'žœžœ˜3Jšžœ žœžœ˜1J˜J˜—š£ œ˜Jšœžœžœžœ˜J˜ Jšœ+˜+Jšœ(žœ˜8J˜J˜—š£ œ˜Jšœžœ˜Jšœ<˜J˜——š ™š£œ˜J˜ š œžœ’œ’œ’œ˜:Jšœ’œ˜(—Jšœ<˜J˜——š ™š‘ œ˜Jš ‘ œžœžœžœ žœ ˜Qš‘œžœ˜$Jšœžœ?˜UJ˜—Jšœžœžœžœ˜9Jšœžœ˜šžœž˜J˜KJ˜Bšžœ˜ J˜ J˜šžœž˜J˜'J˜$J˜&Jšžœ˜—J˜——Jšœ˜J˜——š ™š‘ œ˜Jšœžœžœ˜J˜J˜Jšœ’žœ ’œ’œ’œ’œ’œ’œ ’œ˜XJ˜J˜—š£ œ˜Jšœžœ+˜6J˜%Jšœžœžœ˜HJ˜J˜—š£ œ˜JšœžœQ˜XJš œ’žœ ’œ’žœ ˜KJ˜——š ™š£‘œ˜ J˜ Jšœ9˜9šœžœ)˜AJšžœ žœ žœ ˜+—Jšœ˜J˜—š‘œ˜š ‘ œžœžœžœžœ˜IJš œžœžœžœžœžœ˜WJšžœžœžœ žœ˜7J˜—Jšœžœ,˜6J˜#Jšœžœ˜J˜_Jšžœ žœ˜#Jšžœžœ#˜0šžœžœ˜JšžœJ˜N—šœžœ’œ’œ’œ’œ’œ’œ’œ’œ’œ’œ’œ˜VJš žœžœ žœžœžœ˜IJšžœžœžœ˜2—J˜——š ™š‘ œ˜Jš ‘ œžœžœ žœžœ˜IJ˜ Jšœ žœ9˜HJšœ žœ˜+Jšžœžœžœ˜J˜.J˜/J™>šžœžœžœ˜Jšœ%žœ˜-Jšžœ˜J˜—šžœžœžœž˜)Jšžœžœ"žœžœ˜2J˜ Jšžœ˜Jšžœ˜—J˜6šœžœ)˜AJšžœžœ˜$—J˜J˜—š‘ œ˜Jšœžœ˜šžœžœžœž˜6šžœžœžœž˜)Jšžœžœžœžœ˜/Jš žœžœžœžœ&žœ˜YJ˜,Jšžœ˜Jšžœ˜——Jšœ>˜>J˜J˜—š‘ œ˜Jšœžœ˜J˜)J˜——š ™š‘œ˜Jšœ)˜)J˜J˜—š‘ œ˜Jšœ+˜+J˜J˜—š‘œžœžœžœ˜Dšžœžœž˜Jšœžœžœ ˜5Jšœžœžœ ˜1Jšœžœžœ ˜1Jšžœžœ ˜—J˜—J˜š‘œ˜#Jšœžœ˜JšœR˜RJ˜J˜—š‘œ˜$Jšœžœ˜JšœS˜SJ˜J˜—š‘œ˜'Jšœžœ˜JšœV˜VJ˜J˜—š‘œ˜%Jšœžœ˜JšœT˜TJ˜J˜—š‘œ˜)Jšœžœ˜JšœX˜XJ˜J˜—š‘œ˜!Jšœžœ˜JšœP˜PJ˜J˜—š‘œ˜%Jšœžœ˜JšœT˜TJ˜—J˜š‘ œ˜šžœ žœ˜JšœL˜LJšžœ˜J˜—J™Jšœ žœ˜J˜Jšœ žœ˜J˜J˜—š‘œ˜J™Jšœ žœ˜Jšœ žœ˜J˜J˜J˜—š‘œ˜Jšœžœ˜JšœM™MJ˜šžœ.žœž˜8JšœV˜V—J˜šžœ/žœž˜9JšœX˜X—J˜šžœ2žœž˜JšœV˜V—J˜šžœ,žœž˜6JšœF˜F—J˜šžœ0žœž˜:Jšœ8˜8—J˜J˜—š‘ œ˜Jšœžœ˜J˜/J˜——š ™š ‘œ’žœžœ’œ’œ˜šž˜Jšœžœžœ’˜Jšž’œžœžœ’ž’œžœ žœžœžœžœ žœžœ˜ZJšžœ˜—J˜J˜—š ‘œžœžœžœžœžœ˜UJ˜—š ‘ œžœžœžœžœžœ ˜RJ˜—š ‘œžœžœžœžœ˜>Jšœžœžœ4˜LJ˜J˜—š ‘œžœžœžœžœ˜@Jšœžœžœ4˜MJ˜J˜—š‘œžœžœžœ˜@Jšœžœžœžœ3˜FJ˜3J˜J˜—š‘ œžœžœžœ˜DJšœžœžœžœ3˜FJ˜MJ˜J˜—š ‘œžœžœžœžœ˜@Jšœžœžœžœ3˜FJ˜ Jšœžœžœ˜)J˜J˜—š ‘œžœ žœžœžœ˜9Jšžœžœžœžœ ˜=J˜J˜—Jš ‘œžœ žœžœžœžœ˜L—š ™š‘œžœ2˜MJšžœ˜Jšžœ žœžœ žœ˜@Jšžœ(žœ*˜XJ˜'J˜&Jšžœ ˜J˜J™—š‘œžœ'žœ˜IJšžœ˜#Jšœ žœžœ.˜BJšœžœ!˜*Jš žœžœžœžœžœ˜FJ˜J˜J˜—š‘œžœ2˜MJšžœ˜Jšžœ žœžœ žœ˜@Jšžœ(žœ*˜XJ˜'J˜&Jšžœ ˜J˜J™—š‘œžœ'žœ˜IJšžœ˜#Jšœ žœžœ.˜BJšœžœ!˜*Jš žœžœžœžœžœ˜FJ˜J˜——š ™š‘ œžœ˜šœ™Jšœ8˜8Jšœ7˜7Jšœ0˜0Jšœ3˜3Jšœ.˜.—™ Jšœ3˜3Jšœ.˜.—™Jšœ-˜-Jšœ*˜*—™Jšœ,˜,—™Jšœ.˜.Jšœ+˜+Jšœ5˜5—™Jšœ<˜<—™Jšœ8˜8Jšœ1˜1—™ Jšœ6˜6—šœ ™ J˜(Jšœ8˜8Jšœ6˜6Jšœ<˜