DIRECTORY Args, Ascii, Commander, Draw2d, FileNames, FS, G2dBasic, G3dBasic, G3dBuild, G3dDraw, G3dModel, G3dPlane, G3dPolygon, G3dQuaternion, G3dRender, G3dScene, G3dShape, G3dSpline, G3dSweep, G3dVector, Imager, IO, MessageWindow, Process, Random, RealFns, RefTab, Rope, RopeFile, RuntimeError, TiogaAccess, TiogaMenuOps, ViewerOps, ViewerTools; G3dBuildBImpl: CEDAR PROGRAM IMPORTS G2dBasic, G3dBasic, G3dBuild, G3dModel, G3dRender, G3dScene, G3dShape, G3dSweep, G3dVector, Random, RealFns EXPORTS G3dBuild ~ BEGIN Arg: TYPE ~ Args.Arg; AxisAngle: TYPE ~ G3dQuaternion.AxisAngle; BlendType: TYPE ~ G3dSweep.BlendType; BoolSequence: TYPE ~ G3dBasic.BoolSequence; Context3d: TYPE ~ G3dRender.Context3d; NatSequence: TYPE ~ G3dBasic.NatSequence; NatSequenceRep: TYPE ~ G3dBasic.NatSequenceRep; ParseState: TYPE ~ G3dScene.ParseState; RandomStream: TYPE ~ Random.RandomStream; RealSequence: TYPE ~ G3dBasic.RealSequence; ROPE: TYPE ~ Rope.ROPE; SceneProc: TYPE ~ G3dScene.SceneProc; Shape: TYPE ~ G3dShape.Shape; ShapeRep: TYPE ~ G3dShape.ShapeRep; ShapeSequence: TYPE ~ G3dShape.ShapeSequence; SurfaceDescription: TYPE ~ G3dSweep.SurfaceDescription; SurfaceDescriptionRep: TYPE ~ G3dSweep.SurfaceDescriptionRep; SurfaceSequence: TYPE ~ G3dBasic.SurfaceSequence; Triple: TYPE ~ G3dBasic.Triple; TripleSequence: TYPE ~ G3dBasic.TripleSequence; Vertex: TYPE ~ G3dShape.Vertex; VertexRep: TYPE ~ G3dShape.VertexRep; VertexSequence: TYPE ~ G3dShape.VertexSequence; Error: PUBLIC SIGNAL [code: ATOM, reason: ROPE] = CODE; SweepPaths: TYPE ~ G3dBuild.SweepPaths; SweepPathsRep: TYPE ~ G3dBuild.SweepPathsRep; Field: TYPE ~ G3dBuild.Field; FieldRep: TYPE ~ G3dBuild.FieldRep; State: TYPE ~ G3dBuild.State; StateRep: TYPE ~ G3dBuild.StateRep; pi: REAL = 3.141593; piOver2: REAL = 1.570796; piTimes2: REAL = 6.283186; degToRad: REAL = 1.745329e-2; radToDeg: REAL = 57.29577; PolyStellate: PUBLIC SceneProc ~ { state: State ¬ G3dBuild.GetBuildState[ps]; factorA, basesA: Arg; [factorA, basesA] ¬ G3dScene.GetArgs[ps, args, "%r-bases%b"]; StellateShape[ps.currentShape, factorA.real, basesA.ok]; }; PolyFrame: PUBLIC SceneProc ~ { state: State ¬ G3dBuild.GetBuildState[ps]; factorA: Arg; [factorA] ¬ G3dScene.GetArgs[ps, args, "%r"]; FrameShape[ps.currentShape, factorA.real]; }; PolyDilate: PUBLIC SceneProc ~ { state: State ¬ G3dBuild.GetBuildState[ps]; factorA: Arg; [factorA] ¬ G3dScene.GetArgs[ps, args, "%r"]; DilateShape[ps.currentShape, factorA.real]; }; PolyRotate: PUBLIC SceneProc ~ { state: State ¬ G3dBuild.GetBuildState[ps]; cyclesA: Arg; [cyclesA] ¬ G3dScene.GetArgs[ps, args, "%r"]; RotateShape[ps.currentShape, cyclesA.real]; }; PolyExplode: PUBLIC SceneProc ~ { state: State ¬ G3dBuild.GetBuildState[ps]; factorA: Arg; [factorA] ¬ G3dScene.GetArgs[ps, args, "%r"]; ExplodePShape[ps.currentShape, factorA.real, state.field]; }; PolyInscribe: PUBLIC SceneProc ~ { state: State ¬ G3dBuild.GetBuildState[ps]; factorA: Arg; [factorA] ¬ G3dScene.GetArgs[ps, args, "%r"]; InscribeShape[ps.currentShape, factorA.real]; }; PolyCorners: PUBLIC SceneProc ~ { state: State ¬ G3dBuild.GetBuildState[ps]; alphaA: Arg; [alphaA] ¬ G3dScene.GetArgs[ps, args, "%r"]; CutCornersShape[ps.currentShape, alphaA.real, TRUE]; }; PolyCutCorners: PUBLIC SceneProc ~ { state: State ¬ G3dBuild.GetBuildState[ps]; alphaA: Arg; [alphaA] ¬ G3dScene.GetArgs[ps, args, "%r"]; CutCornersShape[ps.currentShape, alphaA.real, FALSE]; }; PolySplotch: PUBLIC SceneProc ~ { state: State ¬ G3dBuild.GetBuildState[ps]; sidesA, sizeA: Arg; [sidesA, sizeA] ¬ G3dScene.GetArgs[ps, args, "%i-size%r"]; SplotchShape[ps.currentShape, sidesA.int, IF sizeA.ok THEN sizeA.real ELSE 1.0]; }; PolyFan: PUBLIC SceneProc ~ { state: State ¬ G3dBuild.GetBuildState[ps]; factorA: Arg; [factorA] ¬ G3dScene.GetArgs[ps, args, "%r"]; FanShape[ps.currentShape, factorA.real]; }; PolyStar: PUBLIC SceneProc ~ { state: State ¬ G3dBuild.GetBuildState[ps]; factorA: Arg; [factorA] ¬ G3dScene.GetArgs[ps, args, "%r"]; StarShape[ps.currentShape, factorA.real]; }; StellateShape: PUBLIC PROC [shape: Shape, factor: REAL ¬ 1.0, bases: BOOL ¬ TRUE] ~ { newSurfaces: SurfaceSequence ¬ NIL; IF shape = NIL OR shape.surfaces = NIL THEN RETURN; G3dModel.IsolateVertices[shape]; G3dShape.SetFaceNormals[shape]; FOR i: NAT IN [0..shape.surfaces.length) DO tip: Vertex ¬ NEW[VertexRep ¬ []]; tipIndex: INT; poly: NatSequence ¬ shape.surfaces[i].vertices; center: Triple ¬ FindPolygonCenter[shape, i]; tip.point ¬ G3dVector.Add[center, G3dVector.SetVectorLength[shape.faces[i].normal, factor]]; tip.normal ¬ shape.faces[i].normal; tipIndex ¬ shape.vertices.length; shape.vertices ¬ G3dShape.AddToVertexSequence[shape.vertices, tip]; FOR j: NAT IN [0..poly.length) DO k: INT ¬ (j+1) MOD poly.length; nSequence: NatSequence ¬ NEW[NatSequenceRep[3]]; nSequence.length ¬ 3; nSequence[0] ¬ poly[j]; nSequence[1] ¬ poly[k]; nSequence[2] ¬ tipIndex; newSurfaces ¬ G3dBasic.AddToSurfaceSequence[newSurfaces, [NIL, nSequence]]; ENDLOOP; IF bases THEN { nSequence: NatSequence ¬ G2dBasic.CopyNatSequence[poly]; newSurfaces ¬ G3dBasic.AddToSurfaceSequence[newSurfaces, [NIL, nSequence]]; }; ENDLOOP; shape.surfaces ¬ newSurfaces; shape.faces ¬ NIL; -- necessary when replacing the surfaces }; FrameShape: PUBLIC PROC [shape: Shape, factor: REAL ¬ 1.0] ~ { newVertices: VertexSequence ¬ NIL; newSurfaces: SurfaceSequence ¬ NIL; IF shape = NIL OR shape.surfaces = NIL THEN RETURN; G3dModel.IsolateVertices[shape]; FOR i: NAT IN [0..shape.surfaces.length) DO poly: NatSequence ¬ shape.surfaces[i].vertices; FOR j: NAT IN [0..poly.length) DO pv: Vertex ¬ shape.vertices[poly[j]]; v: Vertex ¬ NEW[VertexRep ¬ pv­]; newVertices ¬ G3dShape.AddToVertexSequence[newVertices, v]; ENDLOOP; ENDLOOP; FOR i: NAT IN [0..shape.surfaces.length) DO poly: NatSequence ¬ shape.surfaces[i].vertices; center: Triple ¬ FindPolygonCenter[shape, i]; FOR j: NAT IN [0..poly.length) DO pv: Vertex ¬ shape.vertices[poly[j]]; v: Vertex ¬ NEW[VertexRep ¬ pv­]; relativePos: Triple ¬ G3dVector.Sub[pv.point, center]; relativePos ¬ G3dVector.Mul[relativePos, factor]; relativePos ¬ G3dVector.Add[relativePos, center]; v.point ¬ relativePos; newVertices ¬ G3dShape.AddToVertexSequence[newVertices, v]; ENDLOOP; ENDLOOP; FOR i: NAT IN [0..shape.surfaces.length) DO poly: NatSequence ¬ shape.surfaces[i].vertices; FOR j: NAT IN [0..poly.length) DO nSequence: NatSequence; k: INT ¬ (j+1) MOD poly.length; v0: INT ¬ poly[j]; v1: INT ¬ poly[k]; v1p: INT ¬ v1+shape.vertices.length; v0p: INT ¬ v0+shape.vertices.length; nSequence ¬ NEW[NatSequenceRep[3]]; nSequence.length ¬ 3; nSequence[0] ¬ v0; nSequence[1] ¬ v1; nSequence[2] ¬ v1p; newSurfaces ¬ G3dBasic.AddToSurfaceSequence[newSurfaces, [NIL, nSequence]]; nSequence ¬ NEW[NatSequenceRep[3]]; nSequence.length ¬ 3; nSequence[0] ¬ v0; nSequence[1] ¬ v1p; nSequence[2] ¬ v0p; newSurfaces ¬ G3dBasic.AddToSurfaceSequence[newSurfaces, [NIL, nSequence]]; ENDLOOP; ENDLOOP; shape.vertices ¬ newVertices; shape.surfaces ¬ newSurfaces; shape.faces ¬ NIL; }; DilateShape: PUBLIC PROC [shape: Shape, factor: REAL ¬ 1.0] ~ { IF shape = NIL OR shape.surfaces = NIL THEN RETURN; G3dModel.IsolateVertices[shape]; FOR i: NAT IN [0..shape.surfaces.length) DO poly: NatSequence ¬ shape.surfaces[i].vertices; center: Triple ¬ FindPolygonCenter[shape, i]; FOR j: NAT IN [0..poly.length) DO relativePos: Triple ¬ G3dVector.Sub[shape.vertices[poly[j]].point, center]; relativePos ¬ G3dVector.Mul[relativePos, factor]; relativePos ¬ G3dVector.Add[relativePos, center]; shape.vertices[poly[j]].point ¬ relativePos; ENDLOOP; ENDLOOP; }; RotateShape: PUBLIC PROC [shape: Shape, theta: REAL ¬ piOver2] ~ { IF shape = NIL OR shape.surfaces = NIL THEN RETURN; G3dModel.IsolateVertices[shape]; IF shape.faces = NIL OR NOT shape.faces.valid.normal THEN G3dShape.SetFaceNormals[shape]; FOR i: NAT IN [0..shape.surfaces.length) DO poly: NatSequence ¬ shape.surfaces[i].vertices; normal: Triple ¬ shape.faces[i].normal; center: Triple ¬ FindPolygonCenter[shape, i]; FOR j: NAT IN [0..poly.length) DO relativePos: Triple ¬ G3dVector.Sub[shape.vertices[poly[j]].point, center]; relativePos ¬ G3dVector.RotateAbout[relativePos, normal, theta, FALSE]; shape.vertices[poly[j]].point ¬ G3dVector.Add[relativePos, center]; ENDLOOP; ENDLOOP; }; ExplodePShape: PUBLIC PROC [shape: Shape, factor: REAL ¬ 1.0, f: Field] ~ { IF shape = NIL OR shape.surfaces = NIL THEN RETURN; G3dModel.IsolateVertices[shape]; FOR i: NAT IN [0..shape.surfaces.length) DO poly: NatSequence ¬ shape.surfaces[i].vertices; move, newCenter, relCenter, center: Triple ¬ [0.0, 0.0, 0.0]; center ¬ FindPolygonCenter[shape, i]; relCenter ¬ G3dVector.Sub[center, f.center]; newCenter ¬ G3dVector.Mul[relCenter, factor]; move ¬ G3dVector.Sub[newCenter, relCenter]; FOR j: NAT IN [0..poly.length) DO shape.vertices[poly[j]].point ¬ G3dVector.Add[move, shape.vertices[poly[j]].point]; ENDLOOP; ENDLOOP; }; InscribeShape: PUBLIC PROC [shape: Shape, alpha: REAL ¬ 0.5] ~ { IF shape = NIL OR shape.surfaces = NIL THEN RETURN; G3dModel.IsolateVertices[shape]; FOR i: NAT IN [0..shape.surfaces.length) DO poly: NatSequence ¬ shape.surfaces[i].vertices; oldV0: Triple ¬ shape.vertices[poly[0]].point; FOR j: NAT IN [0..poly.length-1) DO shape.vertices[poly[j]].point ¬ G3dVector.Interp[alpha, shape.vertices[poly[j]].point, shape.vertices[poly[(j+1) MOD poly.length]].point]; ENDLOOP; shape.vertices[poly[poly.length-1]].point ¬ G3dVector.Interp[alpha, shape.vertices[poly[poly.length-1]].point, oldV0]; ENDLOOP; }; CutCornersShape: PUBLIC PROC [shape: Shape, alpha: REAL ¬ 0.5, corners: BOOL ¬ TRUE] ~ { newVertices: VertexSequence ¬ NIL; newSurfaces: SurfaceSequence ¬ NIL; IF shape = NIL OR shape.surfaces = NIL THEN RETURN; G3dModel.IsolateVertices[shape]; FOR i: NAT IN [0..shape.surfaces.length) DO firstVertex: INT ¬ IF newVertices # NIL THEN newVertices.length ELSE 0; poly: NatSequence ¬ shape.surfaces[i].vertices; polyLen: INT ¬ poly.length; polyLen2: INT ¬ 2*polyLen; polyLen3: INT ¬ 3*polyLen; FOR j: INT IN [0 .. polyLen) DO ov0: Vertex ¬ DuplicateVertex[shape.vertices[poly[j]]]; v0: Vertex ¬ DuplicateVertex[shape.vertices[poly[j]]]; v1: Vertex ¬ DuplicateVertex[shape.vertices[poly[(j+1) MOD polyLen]]]; lo: Triple ¬ G3dVector.Interp[alpha, v0.point, v1.point]; hi: Triple ¬ G3dVector.Interp[alpha, v1.point, v0.point]; newVertices ¬ G3dShape.AddToVertexSequence[newVertices, ov0]; v0.point ¬ lo; v1.point ¬ hi; newVertices ¬ G3dShape.AddToVertexSequence[newVertices, v0]; newVertices ¬ G3dShape.AddToVertexSequence[newVertices, v1]; ENDLOOP; IF corners THEN { FOR j: INT IN [0 .. polyLen) DO p: INT ¬ 3*j; nSequence: NatSequence ¬ NEW[NatSequenceRep[3]]; nSequence.length ¬ 3; nSequence[0] ¬ firstVertex + (p); nSequence[1] ¬ firstVertex + ((p+1) MOD polyLen3); nSequence[2] ¬ firstVertex + ((p-1) MOD polyLen3); newSurfaces ¬ G3dBasic.AddToSurfaceSequence[newSurfaces, [NIL, nSequence]]; ENDLOOP; } ELSE { nSequence: NatSequence ¬ NEW[NatSequenceRep[polyLen2]]; index: INT ¬ 0; nSequence.length ¬ polyLen2; FOR j: INT IN [0 .. polyLen3) DO IF (j MOD 3) # 0 THEN { nSequence[index] ¬ firstVertex + j; index ¬ index + 1; }; ENDLOOP; newSurfaces ¬ G3dBasic.AddToSurfaceSequence[newSurfaces, [NIL, nSequence]]; }; ENDLOOP; shape.vertices ¬ newVertices; shape.surfaces ¬ newSurfaces; shape.faces ¬ NIL; }; SplotchShape: PUBLIC PROC [shape: Shape, sides: INT ¬ 10, size: REAL ¬ 1.0] ~ { newVertices: VertexSequence ¬ NIL; newSurfaces: SurfaceSequence ¬ NIL; basis1, basis2: Triple; IF shape = NIL OR shape.surfaces = NIL OR sides < 3 THEN RETURN; G3dModel.IsolateVertices[shape]; G3dShape.SetFaceNormals[shape]; G3dShape.SetFaceCenters[shape]; FOR i: NAT IN [0..shape.surfaces.length) DO poly: NatSequence ¬ shape.surfaces[i].vertices; radius: REAL ¬ 0.0; firstVertex: INT ¬ 0; nSequence: NatSequence; center: Triple ¬ FindPolygonCenter[shape, i]; FOR j: NAT IN [0..poly.length) DO p0: Triple ¬ shape.vertices[poly[j]].point; p1: Triple ¬ shape.vertices[poly[(j+1) MOD poly.length]].point; dist: REAL ¬ G3dVector.Distance[G3dVector.NearestToSegment[p0, p1, center].point, center]; IF j=0 THEN radius ¬ dist ELSE radius ¬ MIN[radius, dist]; ENDLOOP; basis1 ¬ G3dVector.Unit[G3dVector.Sub[shape.vertices[poly[0]].point, center]]; basis2 ¬ G3dVector.Unit[G3dVector.Cross[basis1, shape.faces[i].normal]]; firstVertex ¬ IF newVertices = NIL THEN 0 ELSE newVertices.length; IF size < 1.0 THEN { wiggle: REAL ¬ radius * (1.0-size); theta: REAL ¬ piTimes2 * GetRandom[NIL]; length: REAL ¬ wiggle * GetRandom[NIL]; l1: REAL ¬ length * RealFns.Cos[theta]; l2: REAL ¬ length * RealFns.Sin[theta]; offset: Triple ¬ G3dVector.Add[G3dVector.Mul[basis1, l1], G3dVector.Mul[basis2, l2]]; center ¬ G3dVector.Add[center, offset]; }; radius ¬ radius * size; FOR j: INT IN [0 .. sides) DO theta: REAL ¬ piTimes2 * REAL[j] / REAL[sides-1]; l1: REAL ¬ radius * RealFns.Cos[theta]; l2: REAL ¬ radius * RealFns.Sin[theta]; v: Vertex ¬ NEW[VertexRep ¬ []]; offset: Triple ¬ G3dVector.Add[G3dVector.Mul[basis1, l1], G3dVector.Mul[basis2, l2]]; v.point ¬ G3dVector.Add[center, offset]; v.normal ¬ shape.faces[i].normal; newVertices ¬ G3dShape.AddToVertexSequence[newVertices, v]; ENDLOOP; nSequence ¬ NEW[NatSequenceRep[sides]]; nSequence.length ¬ sides; FOR j: INT IN [0 .. sides) DO nSequence[j] ¬ firstVertex + j; ENDLOOP; newSurfaces ¬ G3dBasic.AddToSurfaceSequence[newSurfaces, [NIL, nSequence]]; ENDLOOP; shape.vertices ¬ newVertices; shape.surfaces ¬ newSurfaces; shape.faces ¬ NIL; }; FanShape: PUBLIC PROC [shape: Shape, alpha: REAL ¬ 0.5] ~ { newVertices: VertexSequence ¬ NIL; newSurfaces: SurfaceSequence ¬ NIL; centerVertex: Vertex; firstVertex: INT ¬ 0; IF shape = NIL OR shape.surfaces = NIL THEN RETURN; G3dModel.IsolateVertices[shape]; G3dShape.SetFaceNormals[shape]; FOR i: NAT IN [0..shape.surfaces.length) DO poly: NatSequence ¬ shape.surfaces[i].vertices; radius: REAL ¬ 0.0; center: Triple ¬ FindPolygonCenter[shape, i]; centerVertex ¬ NEW[VertexRep ¬ []]; centerVertex.point ¬ center; centerVertex.normal ¬ shape.faces[i].normal; firstVertex ¬ IF newVertices = NIL THEN 0 ELSE newVertices.length; newVertices ¬ G3dShape.AddToVertexSequence[newVertices, centerVertex]; FOR j: NAT IN [0..poly.length) DO p: Triple ¬ G3dVector.Interp[alpha, shape.vertices[poly[j]].point, shape.vertices[poly[(j+1) MOD poly.length]].point]; v0: Vertex ¬ DuplicateVertex[centerVertex]; v1: Vertex ¬ DuplicateVertex[centerVertex]; v0.point ¬ shape.vertices[poly[j]].point; v1.point ¬ p; newVertices ¬ G3dShape.AddToVertexSequence[newVertices, v0]; newVertices ¬ G3dShape.AddToVertexSequence[newVertices, v1]; ENDLOOP; FOR j: NAT IN [0..poly.length) DO nSequence: NatSequence ¬ NEW[NatSequenceRep[3]]; nSequence.length ¬ 3; nSequence[0] ¬ firstVertex; nSequence[1] ¬ firstVertex + 1 + (2*j); nSequence[2] ¬ nSequence[1] + 1; newSurfaces ¬ G3dBasic.AddToSurfaceSequence[newSurfaces, [NIL, nSequence]]; ENDLOOP; ENDLOOP; shape.vertices ¬ newVertices; shape.surfaces ¬ newSurfaces; shape.faces ¬ NIL; }; StarShape: PUBLIC PROC [shape: Shape, factor: REAL ¬ 0.5] ~ { newVertices: VertexSequence ¬ NIL; newSurfaces: SurfaceSequence ¬ NIL; centerVertex: Vertex; firstVertex: INT ¬ 0; IF shape = NIL OR shape.surfaces = NIL THEN RETURN; G3dModel.IsolateVertices[shape]; G3dShape.SetFaceNormals[shape]; FOR i: NAT IN [0..shape.surfaces.length) DO poly: NatSequence ¬ shape.surfaces[i].vertices; polyLen2: INT ¬ 2 * poly.length; radius: REAL ¬ 0.0; center: Triple ¬ FindPolygonCenter[shape, i]; centerVertex ¬ NEW[VertexRep ¬ []]; centerVertex.point ¬ center; centerVertex.normal ¬ shape.faces[i].normal; firstVertex ¬ IF newVertices = NIL THEN 0 ELSE newVertices.length; newVertices ¬ G3dShape.AddToVertexSequence[newVertices, centerVertex]; FOR j: NAT IN [0..poly.length) DO p: Triple ¬ G3dVector.Interp[0.5, shape.vertices[poly[j]].point, shape.vertices[poly[(j+1) MOD poly.length]].point]; newp: Triple ¬ G3dVector.Add[G3dVector.Mul[G3dVector.Sub[p, center], factor], center]; v0: Vertex ¬ DuplicateVertex[shape.vertices[poly[j]]]; v1: Vertex ¬ DuplicateVertex[shape.vertices[poly[j]]]; v1.point ¬ newp; newVertices ¬ G3dShape.AddToVertexSequence[newVertices, v0]; newVertices ¬ G3dShape.AddToVertexSequence[newVertices, v1]; ENDLOOP; FOR j: INT IN [0..polyLen2+1) DO nSequence: NatSequence ¬ NEW[NatSequenceRep[3]]; nSequence.length ¬ 3; nSequence[0] ¬ firstVertex + (1 + j); nSequence[1] ¬ firstVertex + ((2 + j) MOD polyLen2); nSequence[2] ¬ firstVertex; newSurfaces ¬ G3dBasic.AddToSurfaceSequence[newSurfaces, [NIL, nSequence]]; ENDLOOP; ENDLOOP; shape.vertices ¬ newVertices; shape.surfaces ¬ newSurfaces; shape.faces ¬ NIL; }; VertexExplode: PUBLIC SceneProc ~ { state: State ¬ G3dBuild.GetBuildState[ps]; factorA: Arg; [factorA] ¬ G3dScene.GetArgs[ps, args, "%r"]; ExplodeVShape[ps.currentShape, factorA.real, state.field]; }; ExplodeVShape: PUBLIC PROC [shape: Shape, factor: REAL ¬ 1.0, f: Field] ~ { IF shape = NIL OR shape.surfaces = NIL THEN RETURN; G3dModel.IsolateVertices[shape]; FOR i: NAT IN [0..shape.surfaces.length) DO poly: NatSequence ¬ shape.surfaces[i].vertices; FOR j: NAT IN [0..poly.length) DO relVertex: Triple ¬ G3dVector.Sub[shape.vertices[poly[j]].point, f.center]; relVertex ¬ G3dVector.Mul[relVertex, factor]; shape.vertices[poly[j]].point ¬ G3dVector.Add[relVertex, f.center]; ENDLOOP; ENDLOOP; G3dShape.SetFaceNormals[shape]; }; FieldCenter: PUBLIC SceneProc ~ { state: State ¬ G3dBuild.GetBuildState[ps]; xA, yA, zA: Arg; [xA, yA, zA] ¬ G3dScene.GetArgs[ps, args, "%rrr"]; state.field.center ¬ [xA.real, yA.real, zA.real]; }; FieldAmplitude: PUBLIC SceneProc ~ { state: State ¬ G3dBuild.GetBuildState[ps]; vA: Arg; [vA] ¬ G3dScene.GetArgs[ps, args, "%r"]; state.field.amplitude ¬ vA.real; }; FieldRadius: PUBLIC SceneProc ~ { state: State ¬ G3dBuild.GetBuildState[ps]; vA: Arg; [vA] ¬ G3dScene.GetArgs[ps, args, "%r"]; state.field.radius ¬ vA.real; }; FieldPower: PUBLIC SceneProc ~ { state: State ¬ G3dBuild.GetBuildState[ps]; vA: Arg; [vA] ¬ G3dScene.GetArgs[ps, args, "%r"]; state.field.power ¬ vA.real; }; FieldOffset: PUBLIC SceneProc ~ { state: State ¬ G3dBuild.GetBuildState[ps]; vA: Arg; [vA] ¬ G3dScene.GetArgs[ps, args, "%r"]; state.field.offset ¬ vA.real; }; Extrude: PUBLIC SceneProc ~ { state: State ¬ G3dBuild.GetBuildState[ps]; shape: Shape ¬ ps.currentShape; axisXA, axisYA, axisZA, newNameA, distanceA: Arg; axis: Triple ¬ [0.0, 0.0, 1.0]; distance: REAL ¬ 1.0; name: ROPE ¬ G3dBuild.AutoName[ps.context3d, "AutoExtrusion"]; [distanceA, axisXA, axisYA, axisZA, newNameA] ¬ G3dScene.GetArgs[ps, args, "-distance%r-axis%rrr-name%s"]; IF axisXA.ok THEN axis ¬ [axisXA.real, axisYA.real, axisZA.real]; IF distanceA.ok THEN distance ¬ distanceA.real; shape ¬ G3dBuild.TranslateShape[ps.currentShape, [0.0, 0.0, 0.0], G3dVector.Mul[axis, distance], TRUE]; IF newNameA.ok THEN name ¬ newNameA.rope; shape.name ¬ name; G3dBuild.LoadShape[ps, state, shape]; }; Revolve: PUBLIC SceneProc ~ { state: State ¬ G3dBuild.GetBuildState[ps]; shape: Shape ¬ ps.currentShape; contourA, stepsA, axisXA, axisYA, axisZA, minThetaA, maxThetaA, radiansA, nameA: Arg; steps: INT ¬ 10; axis: Triple ¬ [0.0, 1.0, 0.0]; vertexCnt: INT ¬ shape.vertices.length; newTotal: INT; contour: BOOL ¬ FALSE; minTheta: REAL ¬ 0.0; maxTheta: REAL ¬ piTimes2; vSequence: NatSequence ¬ NEW[NatSequenceRep]; [contourA, stepsA, axisXA, axisYA, axisZA, minThetaA, maxThetaA, radiansA, nameA] ¬ G3dScene.GetArgs[ps, args, "-contour%b-steps%i-axis%rrr-minTheta%r-maxTheta%r-radians%r-name%s"]; IF axisXA.ok AND axisYA.ok AND axisZA.ok THEN axis ¬ [axisXA.real, axisYA.real, axisZA.real]; IF minThetaA.ok THEN minTheta ¬ IF radiansA.ok THEN minThetaA.real ELSE minThetaA.real*degToRad; IF maxThetaA.ok THEN maxTheta ¬ IF radiansA.ok THEN maxThetaA.real ELSE maxThetaA.real*degToRad; IF contourA.ok THEN contour ¬ TRUE; IF stepsA.ok THEN steps ¬ stepsA.int; newTotal ¬ vertexCnt * steps; FOR step: INT IN [1 .. steps) DO theta: REAL ¬ minTheta + ((maxTheta-minTheta) * step / REAL[steps]); FOR i: INT IN [0 .. vertexCnt) DO vtx: Vertex ¬ DuplicateVertex[shape.vertices[i]]; vtx.point ¬ G3dVector.RotateAbout[vtx.point, axis, theta, FALSE]; IF shape.vertices.valid.normal THEN { -- use the same transform on the normal - this is only valid for rotations! vtx.normal ¬ G3dVector.RotateAbout[vtx.normal, axis, theta, FALSE]; }; shape.vertices ¬ G3dShape.AddToVertexSequence[shape.vertices, vtx]; ENDLOOP; ENDLOOP; IF contour THEN shape.surfaces ¬ NIL; FOR step: INT IN [0 .. steps) DO base: INT ¬ step * vertexCnt; FOR i: INT IN [0 .. vertexCnt-1) DO a: INT ¬ base+i; b: INT ¬ base+i+1; c: INT ¬ (a + vertexCnt) MOD newTotal; d: INT ¬ (b + vertexCnt) MOD newTotal; IF a >= newTotal OR b >= newTotal OR c >= newTotal OR d >= newTotal THEN d ¬ d; G3dSweep.AddGeneralQuadrilateralToShape[shape, a, b, d, c]; ENDLOOP; ENDLOOP; shape.name ¬ IF nameA.ok THEN nameA.rope ELSE G3dBuild.AutoName[ps.context3d, "AutoRevolve"]; }; MakeNormals: PUBLIC SceneProc ~ {G3dShape.SetVertexNormals[ps.currentShape]}; Isolate: PUBLIC SceneProc ~ { state: State ¬ G3dBuild.GetBuildState[ps]; G3dModel.IsolateVertices[ps.currentShape]; }; DuplicateVertex: PUBLIC PROC [old: Vertex] RETURNS [new: Vertex] ~ { new ¬ NEW[VertexRep]; new­ ¬ old­; }; FindPolygonCenter: PUBLIC PROC [shape: Shape, polyIndex: NAT] RETURNS [Triple] ~ { center: Triple ¬ [0.0, 0.0, 0.0]; poly: NatSequence ¬ shape.surfaces[polyIndex].vertices; FOR j: NAT IN [0..poly.length) DO center ¬ G3dVector.Add[shape.vertices[poly[j]].point, center]; ENDLOOP; center ¬ G3dVector.Div[center, poly.length]; RETURN[center]; }; GetRandom: PUBLIC PROC [rs: RandomStream] RETURNS [REAL] ~ { RETURN[REAL[Random.NextInt[rs]]/REAL[LAST[INT]]]; }; MergeShapes: PUBLIC SceneProc ~ { state: State ¬ G3dBuild.GetBuildState[ps]; newShape: Shape ¬ NEW[ShapeRep ¬ []]; nameA, s1A, s2A, s3A, s4A, s5A: Arg; [nameA, s1A, s2A, s3A, s4A, s5A] ¬ G3dScene.GetArgs[ps, args, "%s[sssss"]; IF NOT s1A.ok THEN RETURN; newShape ¬ G3dShape.CopyShape[G3dShape.FindShape[ps.context3d.shapes, s1A.rope]]; newShape.name ¬ nameA.rope; IF s2A.ok THEN newShape ¬ G3dSweep.Merge2Shapes[newShape, G3dShape.FindShape[ps.context3d.shapes, s2A.rope]]; IF s3A.ok THEN newShape ¬ G3dSweep.Merge2Shapes[newShape, G3dShape.FindShape[ps.context3d.shapes, s3A.rope]]; IF s4A.ok THEN newShape ¬ G3dSweep.Merge2Shapes[newShape, G3dShape.FindShape[ps.context3d.shapes, s4A.rope]]; IF s5A.ok THEN newShape ¬ G3dSweep.Merge2Shapes[newShape, G3dShape.FindShape[ps.context3d.shapes, s5A.rope]]; G3dBuild.LoadShape[ps, state, newShape]; }; MergeAllShapes: PUBLIC SceneProc ~ { Inner: PROC [context3d: Context3d, name: ROPE] ~ { vertexNumber: INT ¬ 0; shapes: ShapeSequence ¬ context3d.shapes; newShape: Shape ¬ NEW[ShapeRep ¬ []]; newShape.name ¬ name; newShape.type ¬ $ConvexPolygon; FOR shapeNumber: INT IN [0 .. shapes.length) DO thisShape: Shape ¬ G3dShape.CopyShape[shapes[shapeNumber]]; vertexList: VertexSequence ¬ thisShape.vertices; G3dShape.TransformVertices[thisShape, thisShape.matrix]; FOR i: INT IN [0 .. vertexList.length) DO newShape.vertices ¬ G3dShape.AddToVertexSequence[newShape.vertices, vertexList[i]]; ENDLOOP; FOR surface: INT IN [0 .. thisShape.surfaces.length) DO seq: NatSequence ¬ thisShape.surfaces[surface].vertices; vSequence: NatSequence ¬ NEW[NatSequenceRep[seq.length]]; vSequence.length ¬ seq.length; FOR j: INT IN [0 .. seq.length) DO vSequence[j] ¬ seq[j] + vertexNumber; ENDLOOP; newShape.surfaces ¬ G3dBasic.AddToSurfaceSequence[newShape.surfaces, [NIL, vSequence]]; ENDLOOP; vertexNumber ¬ vertexNumber + vertexList.length; ENDLOOP; newShape.vertices.valid ¬ [TRUE, FALSE, TRUE, FALSE]; G3dRender.AddShape[context3d, newShape]; }; state: State ¬ G3dBuild.GetBuildState[ps]; newNameA: Arg; [newNameA] ¬ G3dScene.GetArgs[ps, args, "%s"]; Inner[ps.context3d, newNameA.rope]; }; RegisterProcs: PROC ~ { G3dScene.RegisterProc["PolyStellate", PolyStellate]; G3dScene.RegisterProc["PolyFrame", PolyFrame]; G3dScene.RegisterProc["PolyDilate", PolyDilate]; G3dScene.RegisterProc["PolyRotate", PolyRotate]; G3dScene.RegisterProc["PolyExplode", PolyExplode]; G3dScene.RegisterProc["PolyInscribe", PolyInscribe]; G3dScene.RegisterProc["PolyCorners", PolyCorners]; G3dScene.RegisterProc["PolyCutCorners", PolyCutCorners]; G3dScene.RegisterProc["PolySplotch", PolySplotch]; G3dScene.RegisterProc["PolyFan", PolyFan]; G3dScene.RegisterProc["PolyStar", PolyStar]; G3dScene.RegisterProc["VertexExplode", VertexExplode]; G3dScene.RegisterProc["FieldCenter", FieldCenter]; G3dScene.RegisterProc["FieldAmplitude", FieldAmplitude]; G3dScene.RegisterProc["FieldRadius", FieldRadius]; G3dScene.RegisterProc["FieldPower", FieldPower]; G3dScene.RegisterProc["FieldOffset", FieldOffset]; G3dScene.RegisterProc["Extrude", Extrude]; G3dScene.RegisterProc["Revolve", Revolve]; G3dScene.RegisterProc["MakeNormals", MakeNormals]; }; RegisterProcs[]; END. ` G3dBuildBImpl.mesa Copyright Σ 1985, 1992 by Xerox Corporation. All rights reserved. Glassner, November 17, 1989 11:59:20 am PST Bloomenthal, July 15, 1992 11:31 pm PDT Imported Types Local Types Constants Calls for Polygon-by-polygon Procedures Impls for Polygon-by-polygon Procedures place a pyramid on every polygon find the point at the tip of the pyramid append this vertex now build the new polygons add the base polys if desired dilate the polygon and replace it with the difference from the original append the old vertices to the new vertex list append the new vertices to the new vertex list append the new polygons to the new polygon list scale all polygons by the given factor wrt their center of gravity now move the vertices rotate all polygons by the given number of cycles wrt their center of gravity now move the vertices move all polygons away from the field center by factor find center of this poly create the new vertices create the new polygons replace each poly by a new ngon somewhere within the poly find the closest approach of each edge to the center find an orthonormal basis in the plane move the center if allowed buid the ngon vertices build the polygon build new vertices build new polygons build new vertices build new polygons Calls for Vertex-by-vertex Procedures Impls for Vertex-by-vertex Procedures move all vertices away from the field center by factor and reset the normals Calls for Field Procedures Shape Modification Procedures add new vertices add new polygons Utility Procedures Shape Merging Procs Start Procedures polygon procs vertex procs field procs modification procs Κf•NewlineDelimiter –"cedarcode" style™™Jšœ Οeœ6™BJ™+J™'J™JšΟk œ,žœŸžœƒ˜ΫJ˜—šΡbln œžœž˜Jšžœm˜tJšžœ ˜J˜—Jšœž˜headšΟl™Jšœ žœ ˜Jšœžœ˜-Jšœžœ˜(Jšœžœ˜-Jšœžœ˜)Jšœžœ˜,Jšœžœ˜1Jšœžœ˜*Jšœžœ˜+Jšœžœ˜-Jšžœžœžœ˜Jšœžœ˜(Jšœ žœ˜!Jšœ žœ˜&Jšœžœ˜/Jšœžœ˜8Jšœžœ"˜=Jšœžœ˜2Jšœ žœ˜#Jšœžœ˜1Jšœ žœ˜#Jšœžœ˜(šœžœ˜1J˜—Jš Οnœžœžœžœ žœžœ˜;—š  ™ Jšœžœ˜*Jšœžœ˜/Jšœ žœ˜"Jšœžœ˜'Jšœ žœ˜"Jšœžœ˜'—š  ™ Jšœžœ ˜Jšœ žœ ˜Jšœ žœ ˜Jšœ žœ˜Jšœ žœ ˜—š '™'š‘ œžœ˜"J˜*J˜J˜=J˜8J˜J˜—š‘ œžœ˜J˜*J˜ J˜-J˜*J˜J˜—š‘ œžœ˜ J˜*J˜ J˜-J˜+J˜J˜—š‘ œžœ˜ J˜*J˜ J˜-J˜+J˜J˜—š‘ œžœ˜!J˜*J˜ J˜-J˜:J˜J˜—š‘ œžœ˜"J˜*J˜ J˜-J˜-J˜J˜—š‘ œžœ˜!J˜*J˜ J˜,Jšœ.žœ˜4J˜J˜—š‘œžœ˜$J˜*J˜ J˜,Jšœ.žœ˜5J˜J˜—š‘ œžœ˜!J˜*J˜J˜:Jšœ*žœ žœ žœ˜PJ˜J˜—š‘œžœ˜J˜*J˜ J˜-J˜(J˜J˜—š‘œžœ˜J˜*J˜ J˜-J˜)J˜J˜——š '™'J™ š ‘ œžœžœžœžœžœ˜UJšœžœ˜#Jš žœ žœžœžœžœžœ˜3J˜ J˜šžœžœžœž˜+Jšœžœ˜"Jšœ žœ˜J˜/J˜-J™(J˜\J˜#J™J˜!J˜CJ™šžœžœžœž˜!Jšœžœ žœ ˜Jšœžœ˜0J˜J˜J˜J˜J˜KJšžœ˜—J™˜J˜8J˜KJ˜—Jšžœ˜—J˜JšœžœΟc(˜=J˜J˜—J™Gš‘ œžœžœžœ ˜>Jšœžœ˜"Jšœžœ˜#Jš žœ žœžœžœžœžœ˜3J˜ J™J™.šžœžœžœž˜+J˜/šžœžœžœž˜!J˜%Jšœ žœ˜!J˜;Jšžœ˜—Jšžœ˜J˜—J™.šžœžœžœž˜+J˜/J˜-šžœžœžœž˜!J˜%Jšœ žœ˜!J˜6J˜1J˜1J˜J˜;Jšžœ˜—Jšžœ˜J™—J™/šžœžœžœž˜+J˜/šžœžœžœž˜!J˜Jšœžœ žœ ˜Jšœžœ ˜Jšœžœ ˜Jšœžœ˜$Jšœžœ˜$J˜Jšœ žœ˜#J˜J˜J˜J˜J˜KJ˜Jšœ žœ˜#J˜J˜J˜J˜J˜KJ˜Jšžœ˜—Jšžœ˜J˜—J˜J˜Jšœžœ˜J˜J˜—J™Bš‘ œžœžœžœ ˜?Jš žœ žœžœžœžœžœ˜3J˜ šžœžœžœž˜+J˜/J˜-J™šžœžœžœž˜!J˜KJ˜1J˜1J˜,Jšžœ˜—Jšžœ˜—J˜J˜—J™Mš‘ œžœžœžœ˜BJš žœ žœžœžœžœžœ˜3J˜ Jš žœžœžœžœžœ ˜Yšžœžœžœž˜+J˜/J˜'J˜-J™šžœžœžœž˜!J˜KJšœ@žœ˜GJ˜CJšžœ˜—Jšžœ˜—J˜J˜—J™6š‘ œžœžœžœ˜KJš žœ žœžœžœžœžœ˜3J˜ šžœžœžœž˜+J˜/J™J˜=J˜%J˜,J˜-J˜+šžœžœžœž˜!J˜SJšžœ˜—Jšžœ˜—J˜J˜—š‘ œžœžœ&˜@Jš žœ žœžœžœžœžœ˜3J˜ šžœžœžœž˜+J˜/J˜.šžœžœžœž˜#˜J˜j—Jšžœ˜—J˜vJšžœ˜—J˜J˜—š ‘œžœžœžœžœžœ˜XJšœžœ˜"Jšœžœ˜#Jš žœ žœžœžœžœžœ˜3J˜ šžœžœžœž˜+Jš œ žœžœžœžœžœ˜GJ˜/Jšœ žœ˜Jšœ žœ ˜Jšœ žœ ˜J™šžœžœžœž˜J˜7J˜6Jšœ7žœ ˜FJ˜9J˜9J˜=J˜J˜J˜J˜jJ˜J˜AJ˜/˜1J˜6—J˜J˜)J˜J˜%J˜J˜—š‘œžœ˜J˜*J˜J˜UJšœžœ˜J˜Jšœ žœ˜'Jšœ žœ˜Jšœ žœžœ˜Jšœ žœ˜Jšœ žœ ˜Jšœžœ˜-J˜΅šžœ žœ žœ ž˜-J˜/—šžœž˜Jšœ žœ žœžœ˜K—šžœž˜Jšœ žœ žœžœ˜K—Jšžœ žœ žœ˜#Jšžœ žœ˜%J˜J™šžœžœžœž˜ Jšœžœ,žœ ˜Dšžœžœžœž˜!J˜1Jšœ:žœ˜Ašžœžœ˜'Jš’K˜KJšœ<žœ˜CJ˜—J˜CJšžœ˜—Jšžœ˜—J™Jšžœ žœžœ˜%šžœžœžœž˜ Jšœžœ˜šžœžœžœž˜#Jšœžœ ˜Jšœžœ ˜Jšœžœžœ ˜&Jšœžœžœ ˜&š žœžœžœžœž˜HJ˜—J˜;Jšžœ˜—Jšžœ˜—˜ Jšžœ žœ žœ0˜P—J˜J˜—Jš‘ œžœ:˜M—š ™š‘œžœ˜J˜*J˜*J˜J˜—š‘œžœžœžœ˜DJšœžœ ˜J˜ J˜J˜—š ‘œžœžœžœžœ ˜RJ˜!J˜7šžœžœžœž˜!J˜>Jšžœ˜—J˜,Jšžœ ˜J˜J˜—š ‘ œžœžœžœžœ˜