<<>> <> <> <> DIRECTORY Commander, CommanderOps, Controls, Draw2d, FileNames, G3dBasic, G3dDraw, G3dMatrix, G3dTube, G3dSpline, G3dTool, G3dVector, ImplicitConvolve, ImplicitDefs, ImplicitDesign, IO, Menus, Rope, TerminalIO; ImplicitPetalCmdImpl: CEDAR PROGRAM IMPORTS CommanderOps, Controls, FileNames, G3dBasic, G3dDraw, G3dTube, G3dSpline, G3dTool, G3dVector, ImplicitConvolve, ImplicitDesign, IO, Rope ~ BEGIN <> RealSequence: TYPE ~ G3dBasic.RealSequence; Triple: TYPE ~ G3dBasic.Triple; TripleSequence: TYPE ~ G3dBasic.TripleSequence; TripleSequenceRep: TYPE ~ G3dBasic.TripleSequenceRep; Spline: TYPE ~ G3dSpline.Spline; SplineSequence: TYPE ~ G3dSpline.SplineSequence; Tube: TYPE ~ G3dTube.Tube; ClickProc: TYPE ~ Menus.ClickProc; ROPE: TYPE ~ Rope.ROPE; Primitive: TYPE ~ ImplicitConvolve.Primitive; PrimitiveList: TYPE ~ ImplicitConvolve.PrimitiveList; TripleList: TYPE ~ ImplicitConvolve.TripleList; <> WingData: TYPE ~ REF WingDataRep; WingDataRep: TYPE ~ RECORD [ tool: ImplicitDesign.Tool ¬ NIL, tube: Tube ¬ NIL, primitives: PrimitiveList ¬ NIL, c0, c1: Spline ¬ NIL, lofts: SplineSequence ¬ NIL, kHeight: REAL ¬ 0.5, kWidth: REAL ¬ 0.25, kSag: REAL ¬ -0.2, thickness: REAL ¬ 0.01, doWeb, doVeins: BOOL ¬ TRUE, showLofts, showSplines: BOOL ¬ TRUE, showLines: BOOL ¬ FALSE ]; WingCmd: Commander.CommandProc ~ { argv: CommanderOps.ArgumentVector ¬ CommanderOps.Parse[cmd]; FOR n: NAT IN [0..argv.argc-1) DO IF Rope.Equal[argv[n], "-tube", FALSE] THEN {Wing[cmd, argv[n+1]]; RETURN}; ENDLOOP; RETURN[$Failure, "must specify -tube "]; }; Wing: PROC [cmd: Commander.Handle, tubeName: ROPE] ~ { w: WingData ¬ NEW[WingDataRep]; w.tube ¬ G3dTube.TubeFromFile[FileNames.ResolveRelativePath[tubeName]]; IF w.tube = NIL OR G3dTube.NBranches[w.tube, TRUE] # 2 THEN IO.PutF[cmd.out, "bad tube\n"] ELSE { G3dTube.SelectAll[w.tube]; G3dTube.Make[w.tube]; MakeWing[w, 6]; w.tool ¬ ImplicitConvolve.MakeTool[ cmd: cmd, name: "WINGing it!", polys: w.primitives, extraButtons: LIST[ Controls.ClickButton["Height", KHeight, w, 1], Controls.ClickButton["Width", KWidth, w, 1], Controls.ClickButton["Sag", KSag, w, 1], Controls.ClickButton["NLofts", NLofts, w, 1], Controls.ClickButton["Thick", Thickness, w, 1], Controls.ClickButton["Veins-On", ToggleVeins, w, 1], Controls.ClickButton["Web-On", ToggleWeb, w, 1]], <> <> <> draw: Draw, data: w, toolSettings: [trackSize: .015, threshold: 0.25] ] }; }; <> MakeWing: PROC [w: WingData, nLofts: NAT, repaint: BOOL ¬ FALSE] ~ { MakeLofts[w, nLofts]; MakePrimitives[w]; IF repaint THEN ImplicitDesign.Repaint[w.tool]; }; Draw: Draw2d.DrawProc ~ { Action: PROC ~ { IF w.showLines THEN G3dTube.DrawLines[context, w.tube, view]; IF w.showSplines THEN G3dTube.DrawSplines[context, w.tube, view]; IF w.showLofts THEN G3dDraw.DrawCurves[context, w.lofts, view]; }; w: WingData ¬ NARROW[clientData]; view: G3dMatrix.Matrix ¬ G3dTool.GetViewTransform[viewer]; <> }; <> MakePrimitives: PROC [w: WingData] ~ { AddPrimitive: PROC [list: TripleList, intensity, extent: REAL, intensities: RealSequence ¬ NIL] ~ { ScaleOffset: PROC [list: TripleList, scale, zOffset: REAL] RETURNS [p: TripleSequence] ~ { p ¬ G3dBasic.TripleSequenceFromList[list]; FOR n: NAT IN [0..p.length) DO p[n] ¬ G3dVector.Sub[G3dVector.Mul[p[n], scale], [0, 0, zOffset]]; ENDLOOP; }; pts: TripleSequence ¬ ScaleOffset[list, 1.75, .5]; p: Primitive ¬ ImplicitConvolve.MakePrimitive[pts, extent,, intensity, intensities,, [55, 55]]; p.display ¬ display; display ¬ IF (count ¬ count+1) MOD 6 = 0 THEN [5, display.y+p.res.y+5] ELSE [display.x+p.res.x+5, display.y]; w.primitives ¬ CONS[p, w.primitives]; }; AddSegment: PROC [p1, p2: Triple, intensities: RealSequence ¬ NIL] ~ { AddPrimitive[LIST[p1, p2], 1.0, .04, intensities]; }; AddRectangle: PROC [p1, p2, p3, p4: Triple] ~ {AddPrimitive[LIST[p1, p2, p3, p4], .75, .015]}; MakeRectangles: PROC [res: NAT] ~ { pts1: TripleSequence ¬ NEW[TripleSequenceRep[res+1]]; pts2: TripleSequence ¬ NEW[TripleSequenceRep[res+1]]; FOR n: NAT IN [0..res] DO pts1[n] ¬ w.tube.p1; ENDLOOP; FOR n: NAT IN [0..w.lofts.length) DO FOR i: NAT IN [0..res] DO pts2[i] ¬ G3dSpline.Position[w.lofts[n], REAL[i]/REAL[res]]; ENDLOOP; FOR i: NAT IN [0..res) DO AddRectangle[pts1[i], pts1[i+1], pts2[i+1], pts2[i]]; ENDLOOP; {temp: TripleSequence ¬ pts1; pts1 ¬ pts2; pts2 ¬ temp}; ENDLOOP; }; MakeSegments: PROC [s: Spline, res: NAT] ~ { p1: Triple ¬ w.tube.p1; FOR i: NAT IN [1..res] DO t: REAL ¬ REAL[i]/REAL[res]; p2: Triple ¬ G3dSpline.Position[s, REAL[i]/REAL[res]]; intensities: RealSequence ¬ NEW[G3dBasic.RealSequenceRep[2]]; intensities[0] ¬ 1.0-REAL[i]/REAL[res]; intensities[1] ¬ 1.0-REAL[i-1]/REAL[res]; AddSegment[p1, p2, intensities]; p1 ¬ p2; ENDLOOP; }; count: NAT ¬ 0; display: ImplicitConvolve.NatPair ¬ [5, 5]; MakeSegments[w.c0, w.lofts.length]; MakeSegments[w.c1, w.lofts.length]; MakeRectangles[w.lofts.length]; }; MakeLofts: PROC [w: WingData, nLofts: NAT] ~ { 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]]; }; w.c0 ¬ G3dTube.GetBranch[w.tube, 0].spline; w.c1 ¬ G3dTube.GetBranch[w.tube, 1].spline; IF w.lofts = NIL THEN w.lofts ¬ NEW[G3dSpline.SplineSequenceRep[nLofts]]; IF w.lofts.maxLength < nLofts THEN { old: SplineSequence ¬ w.lofts; w.lofts ¬ NEW [G3dSpline.SplineSequenceRep[nLofts]]; FOR n: NAT IN [0..old.length) DO w.lofts[n] ¬ old[n]; ENDLOOP; }; w.lofts.length ¬ nLofts; 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; }; << [Artwork node; type 'Artwork on' to command tool] >> <> <> NLofts: ClickProc ~ { w: WingData ¬ NARROW[clientData]; MakeWing[w, MAX[1, Controls.GetNat[w.tool.typescript, "NLofts", w.lofts.length]], TRUE]; }; Thickness: ClickProc ~ { w: WingData ¬ NARROW[clientData]; w.thickness ¬ Controls.TypescriptReadValue[w.tool.typescript, "Thickness", w.thickness]; }; KHeight: ClickProc ~ { w: WingData ¬ NARROW[clientData]; w.kHeight ¬ Controls.TypescriptReadValue[w.tool.typescript, "KHeight", w.kHeight]; MakeWing[w, w.lofts.length, TRUE]; }; KWidth: ClickProc ~ { w: WingData ¬ NARROW[clientData]; w.kWidth ¬ Controls.TypescriptReadValue[w.tool.typescript, "KWidth", w.kWidth]; MakeWing[w, w.lofts.length, TRUE]; }; KSag: ClickProc ~ { w: WingData ¬ NARROW[clientData]; w.kSag ¬ Controls.TypescriptReadValue[w.tool.typescript, "KSag", w.kSag]; MakeWing[w, w.lofts.length, TRUE]; }; Option: TYPE ~ {web, veins, lofts, lines, splines}; ToggleWeb: ClickProc ~ {Toggle[clientData, mouseButton, web, "Web"]}; ToggleVeins: ClickProc ~ {Toggle[clientData, mouseButton, veins, "Veins"]}; ToggleLoft: ClickProc ~ {Toggle[clientData, mouseButton, lofts, "Lofts"]}; ToggleLine: ClickProc ~ {Toggle[clientData, mouseButton, lines, "Lines"]}; ToggleSpline: ClickProc ~ {Toggle[clientData, mouseButton, splines, "Splines"]}; Toggle: PROC [ref: REF, button: Menus.MouseButton, option: Option, name: ROPE] ~ { w: WingData ¬ NARROW[ref]; state: BOOL ¬ SELECT option FROM web => w.doWeb ¬ NOT w.doWeb, veins => w.doVeins ¬ NOT w.doVeins, lofts => w.showLofts ¬ NOT w.showLofts, lines => w.showLines ¬ NOT w.showLines, splines => w.showSplines ¬ NOT w.showSplines, ENDCASE => TRUE; Controls.ButtonToggle[ w.tool.renderTool.outerData, state, Rope.Cat[name, "-On"], Rope.Cat[name, "-Off"]]; IF button = blue THEN ImplicitDesign.Repaint[w.tool, NIL]; }; <> ImplicitDesign.Register["Wing", WingCmd, "\ta wing?", "ImplicitConvolve"]; END.