MakeSweepShape:
PUBLIC PROC [
shapeProc: ShapeBlendProc,
shapeData: REF ANY ¬ NIL,
shapeBlend: BlendType ¬ smooth,
pathProc: PathProc ¬ NIL,
pathData: REF ANY ¬ NIL,
pathBlend: BlendType ¬ smooth,
scaleProc: ScaleProc ¬ NIL,
scaleData: REF ANY ¬ NIL,
scaleBlend: BlendType ¬ smooth,
rotateProc: RotateProc ¬ NIL,
rotateData: REF ANY ¬ NIL,
rotateBlend: BlendType ¬ smooth,
translateProc: TranslateProc ¬ NIL,
translateData: REF ANY ¬ NIL,
translateBlend: BlendType ¬ smooth,
xformProc: XformProc ¬ NIL,
xformData: REF ANY ¬ NIL,
xformBlend: BlendType ¬ smooth,
steps: INT ¬ 10,
tLo: REAL ¬ 0.0,
tHi: REAL ¬ 1.0,
firstInstance: BOOL ¬ FALSE,
lastInstance: BOOL ¬ FALSE,
reverseFirstInstance: BOOL ¬ FALSE,
reverseLastInstance: BOOL ¬ TRUE,
anchor: BOOL ¬ FALSE,
instance: BOOL ¬ TRUE,
connect: BOOL ¬ TRUE,
localXSections: BOOL ¬ FALSE,
tubeTexture: BOOL ¬ TRUE,
close: BOOL ¬ FALSE
]
RETURNS [Shape] ~ {
sweepShape: Shape ¬ NIL;
protoShape, thisInstance: Shape;
pathXSection, scaleXSection, rotateXSection, translateXSection, xformXSection: Matrix;
anchorMat: Matrix ¬ NIL;
firstShape, lastShape: Shape ¬ NIL;
IF shapeProc = NIL THEN protoShape ¬ NARROW[shapeData];
steps ¬ ABS[steps];
FOR step:
INT
IN [0 .. steps)
DO
localalpha:
REAL ¬
IF close
THEN IF steps > 0 THEN REAL[step]/REAL[steps] ELSE 0.0
ELSE IF steps > 1 THEN REAL[step]/REAL[steps-1] ELSE 0.0;
alpha: REAL ¬ tLo + localalpha * (tHi - tLo);
final: Matrix;
build the appropriate transformation matrices for this step
pathXSection ¬
IF pathProc #
NIL
THEN pathProc[alpha, pathBlend, pathData]
ELSE G3dMatrix.Identity[];
scaleXSection ¬
IF scaleProc #
NIL
THEN G3dMatrix.MakeScale[scaleProc[alpha, scaleBlend, scaleData]]
ELSE G3dMatrix.Identity[];
IF rotateProc #
NIL
THEN {
aa: AxisAngle ¬ rotateProc[alpha, rotateBlend, rotateData];
rotateXSection ¬ G3dMatrix.MakeRotate[axis: aa.unitAxis, theta: aa.theta, degrees: FALSE];
}
ELSE rotateXSection ¬ G3dMatrix.Identity[];
translateXSection ¬
IF translateProc #
NIL
THEN G3dMatrix.MakeTranslate[translateProc[alpha, translateBlend, translateData]]
ELSE G3dMatrix.Identity[];
xformXSection ¬
IF xformProc #
NIL
THEN xformProc[alpha, xformBlend, xformData]
ELSE G3dMatrix.Identity[];
if localXSections, then use only the translation component along the path
IF localXSections
THEN {
trans: Triple ¬ [pathXSection[3][0], pathXSection[3][1], pathXSection[3][2]];
pathXSection ¬ G3dMatrix.MakeTranslate[trans];
};
if anchored, then always undo the very first path transformation
IF anchor
THEN {
IF anchorMat =
NIL
THEN {
trans: Triple ¬ [pathXSection[3][0], pathXSection[3][1], pathXSection[3][2]];
tmat: Matrix ¬ G3dMatrix.MakeTranslate[trans];
anchorMat ¬ G3dMatrix.Invert[tmat];
pathXSection[3][0] ¬ pathXSection[3][1] ¬ pathXSection[3][2] ¬ 0.0;
}
ELSE pathXSection ¬ G3dMatrix.Mul[pathXSection, anchorMat];
};
build the final transform, in the order: path, scale, rotate, translate, xform
final ¬
G3dMatrix.Mul[xformXSection,
G3dMatrix.Mul[translateXSection,
G3dMatrix.Mul[rotateXSection,
G3dMatrix.Mul[scaleXSection, pathXSection]]]];
determine the new shape and transform it under the final transform
IF shapeProc #
NIL
THEN
protoShape ¬ shapeProc[alpha, shapeBlend, shapeData];
thisInstance ¬ G3dShape.CopyShape[protoShape];
G3dShape.TransformVertices[thisInstance, final];
IF tubeTexture
THEN
FOR i:
INT
IN [0 .. thisInstance.vertices.length)
DO
thisInstance.vertices[i].texture.y ¬ localalpha;
ENDLOOP;
save this shape if it's the first or last
IF firstInstance
AND (step = 0)
THEN {
firstShape ¬ G3dShape.CopyShape[thisInstance];
IF reverseFirstInstance THEN G3dShape.ReversePolygons[firstShape];
};
IF lastInstance
AND (step = steps-1)
THEN {
lastShape ¬ G3dShape.CopyShape[thisInstance];
IF reverseLastInstance THEN G3dShape.ReversePolygons[lastShape];
};
append the instance to the instances collection
IF sweepShape =
NIL
THEN {
sweepShape ¬ G3dShape.CopyShape[thisInstance];
sweepShape.surfaces ¬ NIL;
}
ELSE AppendVertices[sweepShape, thisInstance];
ENDLOOP;
build the instances
IF instance
THEN BuildInstances[sweepShape, thisInstance, tubeTexture];
build the bridges
IF connect THEN sweepShape ¬ BuildBridges[sweepShape, thisInstance, close];
insert the first and last instances if requested
IF firstInstance
THEN sweepShape ¬
IF sweepShape =
NIL
THEN G3dShape.CopyShape[firstShape]
ELSE Merge2Shapes[sweepShape, firstShape];
IF lastInstance
THEN sweepShape ¬
IF sweepShape =
NIL
THEN G3dShape.CopyShape[lastShape]
ELSE Merge2Shapes[sweepShape, lastShape];
combine the instances and the bridges
RETURN[sweepShape];
};