Loft:
PROC
[c0,
c1:
Spline,
t,
kWide,
kHigh,
kSag:
REAL,
out:
Spline]
RETURNS
[Spline]
~
{
p0, p1, v0, v1, p0p1, pMid, vSum, beam, pp0, pp1, cross, sag: Triple;
[p0, v0] ¬ G3dSpline.PositionAndVelocity[c0, t];
[p1, v1] ¬ G3dSpline.PositionAndVelocity[c1, t];
p0p1 ¬ [p1.x-p0.x, p1.y-p0.y, p1.z-p0.z];
beam ¬ [p0p1.x*kWide, p0p1.y*kWide, p0p1.z*kWide];
pMid ¬ [0.5*(p0.x+p1.x), 0.5*(p0.y+p1.y), 0.5*(p0.z+p1.z)];
vSum ¬ [v0.x+v1.x, v0.y+v1.y, v0.z+v1.z];
pp0 ¬ [pMid.x-beam.x, pMid.y-beam.y, pMid.z-beam.z];
pp1 ¬ [pMid.x+beam.x, pMid.y+beam.y, pMid.z+beam.z];
cross ¬G3dVector.SetVectorLength[G3dVector.Cross[v0,v1],kHigh*G3dVector.Length[p0p1]];
sag ¬ G3dVector.SetVectorLength[vSum, -t*t*kSag];
pp0 ¬ [pp0.x+cross.x+sag.x, pp0.y+cross.y+sag.y, pp0.z+cross.z+sag.z];
pp1 ¬ [pp1.x+cross.x+sag.x, pp1.y+cross.y+sag.y, pp1.z+cross.z+sag.z];
RETURN[G3dSpline.SplineFromBezier[[p0, pp0, pp1, p1], out]];
};
FOR n:
NAT
IN [1..nLofts]
DO
t: REAL ¬ REAL[n]/REAL[nLofts];
w.lofts[n-1] ¬ Loft[w.c0, w.c1, t, w.kWidth, w.kHeight, w.kSag, w.lofts[n-1]];
ENDLOOP;