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
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;
Imported Types
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;
Calls for Polygon-by-polygon Procedures
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];
};
Impls for Polygon-by-polygon Procedures
place a pyramid on every polygon
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];
find the point at the tip of the pyramid
tip.point ¬ G3dVector.Add[center, G3dVector.SetVectorLength[shape.faces[i].normal, factor]];
tip.normal ¬ shape.faces[i].normal;
append this vertex
tipIndex ¬ shape.vertices.length;
shape.vertices ¬ G3dShape.AddToVertexSequence[shape.vertices, tip];
now build the new polygons
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;
add the base polys if desired
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
};
dilate the polygon and replace it with the difference from the original
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];
append the old vertices to the new vertex list
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;
append the new vertices to the new vertex list
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;
append the new polygons to the new polygon list
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;
};
scale all polygons by the given factor wrt their center of gravity
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];
now move the vertices
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;
};
rotate all polygons by the given number of cycles wrt their center of gravity
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];
now move the vertices
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;
};
move all polygons away from the field center by factor
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;
find center of this poly
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;
create the new vertices
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;
create the new polygons
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;
};
replace each poly by a new ngon somewhere within the poly
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];
find the closest approach of each edge to the center
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;
find an orthonormal basis in the plane
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;
move the center if allowed
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];
};
buid the ngon vertices
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;
build the polygon
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];
build new vertices
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;
build new polygons
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];
build new vertices
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;
build new polygons
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;
};
Calls for Field Procedures
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;
};
Shape Modification Procedures
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;
add new vertices
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;
add new polygons
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]};
Shape Merging Procs
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];
};