<<>> <> <> <> <> <<>> 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]]; < $FullColor, Eq[mode, "dither"] => $PseudoColor, ENDCASE => $Gray];>> }; 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. ..