The ~WING~ of a BAT
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
];
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]]};