<<>> <> <> <> DIRECTORY G3dBasic, G3dMatrix, G3dPatch, G3dSpline, G3dVector; G3dPatchImpl: CEDAR PROGRAM IMPORTS G3dSpline, G3dVector EXPORTS G3dPatch ~ BEGIN <> Triple: TYPE ~ G3dBasic.Triple; Matrix: TYPE ~ G3dMatrix.Matrix; Bezier: TYPE ~ G3dSpline.Bezier; Spline: TYPE ~ G3dSpline.Spline; ControlPoints: TYPE ~ G3dPatch.ControlPoints; ControlPointsRep: TYPE ~ G3dPatch.ControlPointsRep; FourPatches: TYPE ~ G3dPatch.FourPatches; Patch: TYPE ~ G3dPatch.Patch; PatchRep: TYPE ~ G3dPatch.PatchRep; <> FromBezier: PUBLIC PROC [cp: ControlPoints, out: Patch ¬ NIL] RETURNS [p: Patch] ~ { p ¬ IF out # NIL THEN out ELSE NEW[PatchRep]; p.controlPoints ¬ cp; FOR i: NAT IN [0..4) DO p.sCurves[i]¬G3dSpline.SplineFromBezier[[cp[i][0],cp[i][1],cp[i][2], cp[i][3]], p.sCurves[i]]; ENDLOOP; FOR i: NAT IN [0..4) DO p.tCurves[i]¬G3dSpline.SplineFromBezier[[cp[0][i],cp[1][i],cp[2][i], cp[3][i]], p.tCurves[i]]; ENDLOOP; }; <> Position: PUBLIC PROC [patch: Patch, s, t: REAL] RETURNS [Triple] ~ { Lerp: PROC [p, q: Triple] RETURNS [Triple] ~ INLINE { RETURN[[p.x+s*(q.x-p.x), p.y+s*(q.y-p.y), p.z+s*(q.z-p.z)]]; }; s0: Triple ¬ G3dSpline.Position[patch.sCurves[0], t]; s1: Triple ¬ G3dSpline.Position[patch.sCurves[1], t]; s2: Triple ¬ G3dSpline.Position[patch.sCurves[2], t]; s3: Triple ¬ G3dSpline.Position[patch.sCurves[3], t]; s12: Triple ¬ Lerp[s1, s2]; RETURN[Lerp[Lerp[Lerp[s0, s1], s12], Lerp[s12, Lerp[s2, s3]]]]; }; <<>> Normal: PUBLIC PROC [patch: Patch, s, t: REAL, unitize: BOOL ¬ TRUE] RETURNS [Triple] ~ { vs: Triple ¬ G3dSpline.Velocity[SCurve[patch, s], t]; vt: Triple ¬ G3dSpline.Velocity[SCurve[patch, t], s]; n: Triple ¬ G3dVector.Cross[vs, vt]; RETURN[IF unitize THEN G3dVector.Unit[n] ELSE n]; }; SplineFrom4: PROC [curves: ARRAY [0..4) OF Spline, t: REAL, out: Spline ¬ NIL] RETURNS [Spline] ~ { p0: Triple ¬ G3dSpline.Position[curves[0], t]; p1: Triple ¬ G3dSpline.Position[curves[1], t]; p2: Triple ¬ G3dSpline.Position[curves[2], t]; p3: Triple ¬ G3dSpline.Position[curves[3], t]; RETURN[G3dSpline.SplineFromBezier[[p0, p1, p2, p3], out]]; }; <<>> SCurve: PUBLIC PROC [patch: Patch, s: REAL, out: Spline ¬ NIL] RETURNS [Spline] ~ { RETURN[SplineFrom4[patch.tCurves, s, out]]; }; <<>> TCurve: PUBLIC PROC [patch: Patch, t: REAL, out: Spline ¬ NIL] RETURNS [Spline] ~ { RETURN[SplineFrom4[patch.sCurves, t, out]]; }; <> Subdivide: PUBLIC PROC [patch: Patch, s, t: REAL ¬ 0.5] RETURNS [fp: FourPatches] ~ { BezierDivide: PROC [b: Bezier, t: REAL] RETURNS [b1, b2: Bezier] ~ { Lerp: PROC [p, q: Triple] RETURNS [Triple] ~ INLINE { tt: REAL ¬ 1.0-t; RETURN[[tt*p.x+t*q.x, tt*p.y+t*q.y, tt*p.z+t*q.z]]; }; b01: Triple ¬ Lerp[b.b0, b.b1]; b12: Triple ¬ Lerp[b.b1, b.b2]; b23: Triple ¬ Lerp[b.b2, b.b3]; b0112: Triple ¬ Lerp[b01, b12]; b1223: Triple ¬ Lerp[b12, b23]; b01121223: Triple ¬ Lerp[b0112, b1223]; RETURN[[b.b0, b01, b0112, b01121223], [b01121223, b1223, b23, b.b3]]; }; PatchFromBezier: PROC [b0, b1, b2, b3: Bezier] RETURNS [p: Patch] ~ { RETURN[FromBezier[NEW[ControlPointsRep ¬ [ [b0.b0, b0.b1, b0.b2, b0.b3], [b1.b0, b1.b1, b1.b2, b1.b3], [b2.b0, b2.b1, b2.b2, b2.b3], [b3.b0, b3.b1, b3.b2, b3.b3]]]]]; }; cp: ControlPoints ¬ patch.controlPoints; s0, s1, s2, s3, s4, s5, s6, s7, t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13: Bezier; [s0, s1] ¬ BezierDivide[[cp[0][0], cp[0][1], cp[0][2], cp[0][3]], s]; [s2, s3] ¬ BezierDivide[[cp[1][0], cp[1][1], cp[1][2], cp[1][3]], s]; [s4, s5] ¬ BezierDivide[[cp[2][0], cp[2][1], cp[2][2], cp[2][3]], s]; [s6, s7] ¬ BezierDivide[[cp[3][0], cp[3][1], cp[3][2], cp[3][3]], s]; [t0, t1] ¬ BezierDivide[[s0.b0, s2.b0, s4.b0, s6.b0], t]; [t2, t3] ¬ BezierDivide[[s0.b1, s2.b1, s4.b1, s6.b1], t]; [t4, t5] ¬ BezierDivide[[s0.b2, s2.b2, s4.b2, s6.b2], t]; [t6, t7] ¬ BezierDivide[[s0.b3, s2.b3, s4.b3, s6.b3], t]; [t8, t9] ¬ BezierDivide[[s1.b1, s3.b1, s5.b1, s7.b1], t]; [t10, t11] ¬ BezierDivide[[s1.b2, s3.b2, s5.b2, s7.b2], t]; [t11, t12] ¬ BezierDivide[[s1.b3, s3.b3, s5.b3, s7.b3], t]; fp[0] ¬ PatchFromBezier[t0, t2, t4, t6]; fp[1] ¬ PatchFromBezier[t1, t3, t5, t7]; fp[2] ¬ PatchFromBezier[t6, t8, t10, t12]; fp[3] ¬ PatchFromBezier[t7, t9, t11, t13]; }; <> << [1.000, 0.000, 0.000, 0.000],>> << [0.500, 0.500, 0.000, 0.000],>> << [0.025, 0.500, 0.250, 0.000],>> << [0.125, 0.375, 0.375, 0.125]]];>> <<>> <> <> <> <> <

> <> <> <> <> <> <<};>> <<>> END. .. If ever we want forward differencing: Patch: TYPE ~ REF RECORD [ARRAY [0..4) OF ARRAY [0..4) OF ARRAY [0..4) OF REAL; <> Bezier: PUBLIC PROC [cp: ControlPoints, out: Patch ¬ NIL] RETURNS [p: Patch] ~ { b: PatchRep; p ¬ IF out # NIL THEN out ELSE NEW[PatchRep]; FOR k: NAT IN [0..4) DO <> IF k = 3 THEN FOR i: NAT IN [0..4) DO b[i][0][k] ¬ -cp[i][0][k]+3.0*cp[i][1][k]-3.0*cp[i][2][k]+cp[i][3][k]; b[i][1][k] ¬ 3.0*cp[i][0][k]-6.0*cp[i][1][k]+3.0*cp[i][2][k]; b[i][2][k] ¬ 3.0*cp[i][0][k]+3.0*cp[i][1][k]; b[i][3][k] ¬ 1.0; ENDLOOP ELSE FOR i: NAT IN [0..4) DO b[i][0][3] ¬ 0.0; b[i][1][3] ¬ 0.0; b[i][2][3] ¬ 6.0; b[i][3][3] ¬ 1.0; ENDLOOP; <> FOR j: NAT IN [0..4) DO p[0][j][k] ¬ -b[0][j][k]+3.0*b[1][j][k]-3.0*b[2][j][k]+b[3][j][k]; p[1][j][k] ¬ 3.0*b[0][j][k]-6.0*b[1][j][k]+3.0*b[2][j][k]; p[2][j][k] ¬ -3.0*b[0][j][k]+3.0*b[1][j][k]; p[3][j][k] ¬ b[0][j][k]; ENDLOOP; ENDLOOP; }; <> Draw: PUBLIC PROC [context: Context, view: Matrix, patch: Patch, nCurves, nSegments: NAT] ~ { tcoeff, ucoeff, temp, diff: PatchRep; curve: Spline; s1: REAL ¬ 1.0/REAL[nSegments]; s2: REAL ¬ s1*s1; s22: REAL ¬ s2+s2; s3: REAL ¬s2*s1; s36: REAL ¬ 6.0*s3; c1: REAL ¬ 1.0/REAL[nCurves]; c2: REAL ¬ c1*c1; c22: REAL ¬ c2+c2; c3: REAL ¬ c2*c1; c36: REAL ¬ 6.0*c3; sDirection: BOOL ¬ TRUE; <> FOR j: NAT IN [0..4) DO FOR i: NAT IN [0..4) DO FOR k: NAT IN [0..4) DO tcoeff[i][j][k] ¬ patch[i][j][0]*view[0][k]+ patch[i][j][1]*view[1][k]+ patch[i][j][2]*view[2][k]+ patch[i][j][3]*view[3][k]; ENDLOOP; ENDLOOP; ENDLOOP; FOR k: NAT IN [0..4) DO <> FOR i: NAT IN [0..4) DO temp[i][0][k] ¬ tcoeff[i][3][k]; temp[i][1][k] ¬ tcoeff[i][0][k]*c3+tcoeff[i][1][k]*c2+tcoeff[i][2][k]*c1; temp[i][3][k] ¬ tcoeff[i][0][k]*c36; temp[i][2][k] ¬ temp[i][3][k]+tcoeff[i][1][k]*c22; ENDLOOP; <> FOR j: NAT IN [0..4) DO diff[0][j][k] ¬ temp[3][j][k]; diff[1][j][k] ¬ s3*temp[0][j][k]+s2*temp[1][j][k]+s1*temp[2][j][k]; diff[3][j][k] ¬ s36*temp[0][j][k]; diff[2][j][k] ¬ diff[3][j][k]+s22*temp[1][j][k]; ENDLOOP; ENDLOOP; }; <<>>