<<>> <> <> <> DIRECTORY Commander, Draw2d, G3dBasic, G3dControl, G3dCurve, G3dDraw, G3dMatrix, G3dSpline, G3dVector, G3dView, Imager, ImplicitConvolve, ImplicitDefs, ImplicitDesign, IO, Rope; ImplicitWingCmdImpl: CEDAR PROGRAM IMPORTS G3dBasic, G3dControl, G3dCurve, G3dSpline, G3dVector, ImplicitConvolve, ImplicitDesign, IO ~ BEGIN <> RealSequence: TYPE ~ G3dBasic.RealSequence; Triple: TYPE ~ G3dBasic.Triple; TripleSequence: TYPE ~ G3dBasic.TripleSequence; TripleSequenceRep: TYPE ~ G3dBasic.TripleSequenceRep; Curve: TYPE ~ G3dCurve.Curve; Spline: TYPE ~ G3dSpline.Spline; SplineSequence: TYPE ~ G3dSpline.SplineSequence; Primitive: TYPE ~ ImplicitConvolve.Primitive; PrimitiveList: TYPE ~ ImplicitConvolve.PrimitiveList; TripleList: TYPE ~ ImplicitConvolve.TripleList; ROPE: TYPE ~ Rope.ROPE; <> Segment: TYPE ~ RECORD [p1, p2: Triple, primitives: PrimitiveList]; SegmentList: TYPE ~ LIST OF Segment; WingData: TYPE ~ REF WingDataRep; WingDataRep: TYPE ~ RECORD [ cmd: Commander.Handle _ NIL, tool: ImplicitDesign.Tool _ NIL, kHeight: REAL _ 0.1, kWidth: REAL _ 0.25, thumb: SegmentList _ NIL, finger1, finger2, finger3, finger4: SegmentList _ NIL, upperArm, lowerArm, elbow: SegmentList _ NIL, loft1, loft2, loft3, loft4, loft5, loft6, loft7: SplineSequence _ NIL, primitives: PrimitiveList _ NIL ]; out: IO.STREAM; fingerExtent: REAL _ 0.2; fingerTipIntensity: REAL _ 3.5; fingerIntensity: REAL _ 4.5; muscleExtent: REAL _ 0.5; muscleIntensity: REAL _ 5.0; muscleTipIntensity: REAL _ 4.0; webExtent: REAL _ 0.1; webIntensity: REAL _ 1.75; gRes: ImplicitConvolve.IntegerPair _ [60, 60]; WingCmd: Commander.CommandProc ~ { w: WingData _ NEW[WingDataRep _ [cmd: cmd]]; out _ cmd.out; MakeWing[w]; IO.PutF[out, "%g primitives\n", IO.int[NPrimitives[w.primitives]]]; w.tool _ ImplicitConvolve.MakeTool[ cmd: cmd, name: "WING IT!", primitives: w.primitives, clientData: w, toolSettings: [trackSize: .09, threshold: 0.5] ]; G3dControl.UpdateControl[w.tool.renderTool.camera, w.tool.renderTool.camera.scale, 0.2]; }; NPrimitives: PROC [p: PrimitiveList] RETURNS [n: NAT _ 0] ~ { FOR l: PrimitiveList _ p, l.rest WHILE l # NIL DO n _ n+1; ENDLOOP; }; MakeWing: PROC [w: WingData, repaint: BOOL _ FALSE] ~ { w.primitives _ NIL; w.thumb _ MakeThumb[[-.2, 0, 1.2], [-.3, 0, 1.8]]; w.finger1 _ MakeFinger[[-.2, 0, 1.2], [-1.9, .1, 1.2], [-2.2, .25, 1], [-2.5, .4, .7]]; w.finger2 _ MakeFinger[[-.2, 0, 1.2], [-1.7, .05, .8], [-2.8, .15, -.1], [-3.1, .25, -1.0]]; w.finger3 _ MakeFinger[[-.2, 0, 1.2], [-1.8, 0, .3], [-2.6, .1, -.7], [-2.7, .15, -1.4]]; w.finger4 _ MakeFinger[[-.2, 0, 1.2], [-1.2, 0, -.3], [-1.5, 0, -1.4], [-1.5, 0, -2.]]; w.upperArm _ MakeUpperArm[[3.6, 0, 1.7], [2.3, 0, -.2]]; w.lowerArm _ MakeLowerArm[[2.3, 0, -.2], [-.2, 0, 1.2]]; w.elbow _ MakeElbow[[2.3, 0, -.2], [2.2, 0, -2.2]]; w.loft1 _ MakeLofts[ w, CombineSegments[w.lowerArm, w.thumb], ReverseSegments[w.upperArm], 8, 0.35]; w.loft2 _ MakeLofts[w, w.thumb, w.finger1, 4, .5]; w.loft3 _ MakeLofts[w, w.finger1, w.finger2, 6, .5]; w.loft4 _ MakeLofts[w, w.finger2, w.finger3, 6, .5]; w.loft5 _ MakeLofts[w, w.finger3, w.finger4, 6, .5]; w.loft6 _ MakeLofts[ w, w.finger4, CombineSegments[ReverseSegments[w.lowerArm], w.elbow], 8, 0.75]; w.loft7 _ MakeLofts[w, w.elbow, ReverseSegments[w.upperArm], 4, 0.25]; FOR l: LIST OF SegmentList _ LIST[ w.thumb, w.finger1, w.finger2, w.finger3, w.finger4, w.upperArm, w.lowerArm], l.rest WHILE l # NIL DO FOR s: SegmentList _ l.first, s.rest WHILE s # NIL DO FOR p: PrimitiveList _ s.first.primitives, p.rest WHILE p # NIL DO IF p.first # NIL THEN w.primitives _ CONS[p.first, w.primitives]; ENDLOOP; ENDLOOP; ENDLOOP; MakeRectangles[w, w.loft1, 7]; MakeRectangles[w, w.loft2, 4]; MakeRectangles[w, w.loft3, 3]; MakeRectangles[w, w.loft4, 3]; MakeRectangles[w, w.loft5, 4]; MakeRectangles[w, w.loft6, 6]; MakeRectangles[w, w.loft7, 4]; IF repaint THEN ImplicitDesign.Repaint[w.tool]; }; MakeRectangles: PROC [w: WingData, splines: SplineSequence, res: NAT] ~ { Add: PROC [list: TripleList] ~ { pts: TripleSequence _ TripleSequenceFromList[list]; p: Primitive _ ImplicitConvolve.MakePrimitive[pts, webExtent,, webIntensity,,, gRes]; w.primitives _ CONS[p, w.primitives]; }; FillUp: PROC [pts: TripleSequence, s: Spline] ~ { FOR i: NAT IN [0..res] DO pts[i] _ G3dSpline.Position[s, REAL[i]/REAL[res]]; ENDLOOP; }; pts1: TripleSequence _ NEW[TripleSequenceRep[res+1]]; pts2: TripleSequence _ NEW[TripleSequenceRep[res+1]]; FillUp[pts1, splines[0]]; FOR n: NAT IN [1..splines.length) DO FillUp[pts2, splines[n]]; FOR i: NAT IN [0..res) DO Add[LIST[pts1[i], pts1[i+1], pts2[i+1], pts2[i]]]; ENDLOOP; {temp: TripleSequence _ pts1; pts1 _ pts2; pts2 _ temp}; ENDLOOP; }; MakeSegment: PROC [p1, p2: Triple, extent, intensity0, intensity1: REAL] RETURNS [s: Segment] ~ { pts: TripleSequence _ TripleSequenceFromList[LIST[p1, p2]]; intensities: RealSequence _ RealSequenceFromList[LIST[intensity0, intensity1]]; primitive: Primitive _ ImplicitConvolve.MakePrimitive[pts, extent, 0, 1, intensities,, gRes]; s _ [p1, p2, LIST[primitive]]; }; MakeThumb: PROC [p1, p2: Triple] RETURNS [list: SegmentList] ~ { list _ LIST[MakeSegment[p1, p2, 0.2, fingerIntensity, fingerTipIntensity]]; }; MakeFinger: PROC [p1, p2, p3, p4: Triple] RETURNS [list: SegmentList] ~ { list _ LIST[ MakeSegment[p1, p2, fingerExtent, fingerIntensity, fingerTipIntensity], MakeSegment[p2, p3, fingerExtent, fingerIntensity, fingerTipIntensity], MakeSegment[p3, p4, fingerExtent, fingerIntensity, fingerTipIntensity]]; }; MakeUpperArm: PROC [p1, p2: Triple] RETURNS [list: SegmentList] ~ { s: Segment _ [p1, p2, NIL]; bicep: PrimitiveList _ MakeMuscle[p1, [1.9, 0, .15], .2, .7, muscleTipIntensity, muscleTipIntensity, muscleIntensity, muscleExtent]; tricep: PrimitiveList _ MakeMuscle[p1, [2.3, 0, -.15], .1, .6, muscleTipIntensity, muscleTipIntensity, muscleIntensity, muscleExtent]; s.primitives _ CombinePrimitives[LIST[bicep, tricep]]; list _ LIST[s]; }; MakeLowerArm: PROC [p1, p2: Triple] RETURNS [list: SegmentList] ~ { s1: Segment _ [p1, p2, MakeMuscle[p1, p2, .2, .7, muscleTipIntensity, muscleTipIntensity, muscleIntensity, muscleExtent]]; list _ LIST[s1]; }; MakeElbow: PROC [p1, p2: Triple] RETURNS [list: SegmentList] ~ {list _ LIST[[p1, p2, NIL]]}; <> MakeMuscle: PROC [ p1, p2: Triple, -- endpoints of the muscle tendon1, tendon2: REAL, -- start/stop of the muscle intensity1, intensity2, maxIntensity: REAL, -- start/stop and max height of muscle extent: REAL] -- blending extent RETURNS [list: PrimitiveList _ NIL] ~ { IntensityAt intensity _ intensity1+ IF SlowInOut: PROC [x: REAL] RETURNS [REAL] ~ {RETURN[(3.0-2.0*x)*x*x]}; xx: REAL _ ( intensity _ intensity+ }; }; pp: Triple _ p1; pIntensity: REAL _ intensity1; FOR i: NAT IN [1..8] DO p: Triple _ G3dVector.Interp[ intensity: REAL _ IntensityAt pts: TripleSequence _ TripleSequenceFromList[LIST[pp, p]]; intensities: RealSequence _ RealSequenceFromList[LIST[pIntensity, intensity]]; list _ CONS[ImplicitConvolve.MakePrimitive[pts, extent, 0, 1.0, intensities,, gRes], list]; pp _ p; pIntensity _ intensity; ENDLOOP; }; <> CurveFromSegmentList: PROC [s: SegmentList] RETURNS [c: Curve] ~ { pts: TripleList _ LIST[s.first.p1]; FOR l: SegmentList _ s, l.rest WHILE l # NIL DO pts _ CONS[l.first.p2, pts]; ENDLOOP; c _ G3dCurve.CurveFromSplines[G3dSpline.Interpolate[TripleSequenceFromList[pts]]]; }; PositionA: PROC [s: SegmentList, t: REAL] RETURNS [p: Triple] ~ { length, totalLength, desiredLength: REAL _ 0.0; FOR l: SegmentList _ s, l.rest WHILE l # NIL DO totalLength _ totalLength+G3dVector.Distance[l.first.p1, l.first.p2]; ENDLOOP; desiredLength _ t*totalLength; FOR l: SegmentList _ s, l.rest WHILE l # NIL DO segLength: REAL _ G3dVector.Distance[l.first.p1, l.first.p2]; dif: REAL _ (length _ length+segLength)-desiredLength; IF dif < 0.0 THEN LOOP; RETURN[G3dVector.Interp[(segLength-dif)/segLength, l.first.p1, l.first.p2]]; ENDLOOP; }; globalCross: Triple _ [0.0, 1.0, 0.0]; MakeLofts: PROC [w: WingData, s0, s1: SegmentList, nLofts: NAT, sag: REAL] RETURNS [splines: SplineSequence] ~ { Loft: PROC [t, kWide, kHeight, kSag: REAL] RETURNS [s: Spline] ~ { p0: Triple _ PositionA[s0, t]; p1: Triple _ PositionA[s1, t]; p0p1: Triple _ G3dVector.Sub[p1, p0]; lenp0p1: REAL _ G3dVector.Length[p0p1]; beam: Triple _ G3dVector.Mul[p0p1, kWide]; pMid: Triple _ G3dVector.Midpoint[p0, p1]; pp0: Triple _ G3dVector.Sub[pMid, beam]; pp1: Triple _ G3dVector.Add[pMid, beam]; <> cross: Triple _ G3dVector.SetVectorLength[globalCross, kHeight*lenp0p1]; sag: Triple _ G3dVector.SetVectorLength[vSum, -t*t*kSag]; v: Triple _ G3dVector.Add[cross, sag]; pp0 _ G3dVector.Add[pp0, v]; pp1 _ G3dVector.Add[pp1, v]; s _ G3dSpline.SplineFromBezier[[p0, pp0, pp1, p1]]; }; c0: Curve _ CurveFromSegmentList[s0]; c1: Curve _ CurveFromSegmentList[s1]; v0: Triple _ G3dVector.Sub[PositionA[s0, 1.0], s0.first.p1]; v1: Triple _ G3dVector.Sub[PositionA[s1, 1.0], s1.first.p1]; vSum: Triple _ G3dVector.Add[G3dVector.Unit[v0], G3dVector.Unit[v1]]; splines _ NEW[G3dSpline.SplineSequenceRep[nLofts]]; splines.length _ nLofts; FOR n: NAT IN [0..nLofts) DO splines[n] _ Loft[REAL[n]/REAL[nLofts-1], w.kWidth, w.kHeight, sag]; ENDLOOP; }; <> <> <> <> <> <> <> <<};>> <> <> <> <<};>> <> ReverseSegments: PROC [list: SegmentList] RETURNS [ret: SegmentList] ~ { <> FOR s: SegmentList _ list, s.rest WHILE s # NIL DO ret _ CONS[[s.first.p2, s.first.p1, s.first.primitives], ret]; ENDLOOP; }; CombineSegments: PROC [s1, s2: SegmentList] RETURNS [ret: SegmentList] ~ { tmp: SegmentList _ NIL; FOR l: SegmentList _ s1, l.rest WHILE l # NIL DO tmp _ CONS[l.first, tmp]; ENDLOOP; FOR l: SegmentList _ s2, l.rest WHILE l # NIL DO tmp _ CONS[l.first, tmp]; ENDLOOP; FOR l: SegmentList _ tmp, l.rest WHILE l # NIL DO ret _ CONS[l.first, ret]; ENDLOOP; }; CombinePrimitives: PROC [list: LIST OF PrimitiveList] RETURNS [ret: PrimitiveList] ~ { FOR l: LIST OF PrimitiveList _ list, l.rest WHILE l # NIL DO FOR p: PrimitiveList _ l.first, p.rest WHILE p # NIL DO IF p.first # NIL THEN ret _ CONS[p.first, ret] ENDLOOP; ENDLOOP; }; TripleSequenceFromList: PROC [points: LIST OF Triple] RETURNS [TripleSequence] ~ { RETURN[G3dBasic.TripleSequenceFromList[points]]; }; RealSequenceFromList: PROC [reals: LIST OF REAL] RETURNS [s: RealSequence] ~ { len: NAT _ 0; FOR l: LIST OF REAL _ reals, l.rest WHILE l # NIL DO len _ len+1; ENDLOOP; s _ NEW[G3dBasic.RealSequenceRep[len]]; s.length _ len; FOR n: NAT IN [0..s.length _ len) DO {s[n] _ reals.first; reals _ reals.rest}; ENDLOOP; }; <> ImplicitDesign.Register["Wing", WingCmd, "\ta wing?", "ImplicitConvolve"]; END.