<> <> <> DIRECTORY Commander, Controls, Controls3d, Draw2d, Draw3d, Icons, IO, Real, Rope, Spline3d, TubeDefs, TubeIO, TubeDisplay, TubePick, TubeStructure, Vector3d, ViewerOps; TubeDesignImpl: CEDAR PROGRAM IMPORTS Commander, Controls, Controls3d, Draw2d, Draw3d, Icons, IO, Real, Spline3d, TubeDisplay, TubeIO, TubePick, TubeStructure, Vector3d, ViewerOps ~ BEGIN OPEN TubeDefs; UserData: TYPE ~ RECORD [o: OuterData, p: ProgramData]; ActionType: TYPE ~ {none, select, camera, spline, shape, button}; ProgramData: TYPE ~ REF ProgramDataRec; ProgramDataRec: TYPE ~ RECORD [ outer: Controls.Viewer _ NIL, graphics: Controls.Viewer _ NIL, mouse, mousePrev: Mouse _ [0, 0, none, left], entries: LIST OF Controls.Entry _ NIL, cam: Controls3d.Camera, -- camera hold: Controls3d.Hold, -- handle on a point and its tangent twist0: ControlData _ NIL, -- twist 0 twist1: ControlData _ NIL, -- twist 1 r0: ControlData _ NIL, -- radius 0 r1: ControlData _ NIL, -- radius 1 scal: ControlData _ NIL, -- scale eps: ControlData _ NIL, -- spline flatness value cres: ControlData _ NIL, -- circ. resolution lim: ControlData _ NIL, -- vector limit graphicsData: GraphicsData _ NIL, outerData: OuterData _ NIL, view: Matrix _ NIL, xmats: MatrixSeq _ NIL, tube: Tube _ NIL, -- all the tube splines pick: Pick _ NIL, action: ActionType _ none, xformIO: BOOL _ FALSE, -- xform points by camera when writing to file details: Details _ NIL, circle: PairSequence _ NIL, noDraw: BOOL _ FALSE ]; TubeDesign: Commander.CommandProc ~ { p: ProgramData _ NEW[ProgramDataRec]; InitProgramData[p]; MakeDetails[p]; InitViewer[p]; }; InitProgramData: PROC [p: ProgramData] ~ { p.pick _ NEW[PickRec]; p.view _ NEW[MatrixRep]; p.tube _ NEW[TubeRec _ [p0: [-0.5,0.,0.], p1: [0.5,0.,0.], v0: [1.,1.,0.], v1: [1.,1.,0.]]]; p.cam _ Controls3d.InitCamera[dz: 0.5, zoom: 3., fov: 0., proc: Controller, data: p]; p.hold _ Controls3d.InitHold[Controller, p]; p.twist0 _ Controls.NewControl["tw0", vert, , -1000., 1000., 0.0, , , , Controller, p]; p.twist1 _ Controls.NewControl["tw1", vert, , -1000., 1000., 0.0, , , , Controller, p]; p.r0 _ Controls.NewControl["r0", vert, , 0.0, 0.5, 0.0, , , , Controller, p]; p.r1 _ Controls.NewControl["r1", vert, , 0.0, 0.5, 0.0, , , , Controller, p]; p.scal _ Controls.NewControl["scal", vert, , 0.0, 4.0, 1.0, , , , Controller, p]; p.eps _ Controls.NewControl["eps", vert, , 0.001, 0.1, 0.03, , , , Controller, p]; p.cres _ Controls.NewControl["cres", vert, , 3.0, 15.0, 6.0, , TRUE, , Controller, p]; p.lim _ Controls.NewControl["lim", vert, , 0.0, 1000.0, 500.0, , TRUE, , Controller, p]; p.pick.tube _ p.tube; p.tube.c _ Spline3d.CoeffsFromHermite[[p.tube.p0, p.tube.p1, p.tube.v0, p.tube.v1]]; p.details _ NEW[DetailsRec]; TubePick.PointPick[p.pick]; }; InitViewer: PROC [p: ProgramData] ~ { Controls.ControlRow[p.twist0, 2]; Controls.ControlRow[p.cam.pan, 3]; p.outer _ Controls.OuterViewer[ name: "Tube", column: left, entries: LIST[ ["Help", Help, 2], ["Auto-On", TogAuto, 2], ["Label-On", TogLabel, 2], ["No Xform IO", TogXformIO, 2], ["Max-Out", MaxPointsPolyOut, 2], ["Poly-Out", PointsPolyOut, 2], ["IP-out", IPOut, 2], ["Skel-Off", TogSkel, 1], ["Pick-On", TogPick, 1], ["Splines-On", TogSpline, 1], ["Circles-Off", TogCircles, 0], ["Lines-Off", TogLines, 0], ["Frames-Off", TogFrames, 0], ["Normals-Off", TogNormals, 0], ["Curv-Off", TogCurv, 0], ["Vel-Off", TogVel, 0], ["Acc-Off", TogAcc, 0]], controls: LIST[ p.hold.dx, p.hold.dy, p.hold.dz, p.hold.lng, p.hold.lat, p.hold.mag, p.twist0, p.twist1, p.r0, p.r1, p.scal, p.eps, p.cres, p.lim, p.cam.pan, p.cam.tilt, p.cam.roll, p.cam.zoom, p.cam.dx, p.cam.dy, p.cam.dz, p.cam.fov], typeScript: TRUE, graphicsHeight: 300, graphicsProc: ScreenPick, graphicsShow: Display, data: p, noOpen: TRUE]; p.entries _ NARROW[p.outer.data, Controls.OuterData].entries; p.graphics _ NARROW[p.outer.data, Controls.OuterData].graphics; p.graphicsData _ NARROW[p.graphics.data]; p.outerData _ NARROW[p.outer.data]; p.outer.icon _ Icons.NewIconFromFile["Tube.icon", 0]; Controls3d.FocusHold[p.pick.tan, p.hold]; ViewerOps.OpenIcon[p.outer]; }; Display: Controls.GraphicsShow ~ { p: ProgramData _ NARROW[data]; Action: PROC ~ { p.view _ Controls3d.InitPix[context, w, h, p.view]; IF p.details.spline THEN TubeDisplay.ShowSplineEnds[p.tube, context, p.view]; IF p.details.on THEN TubeDisplay.ShowTube[p.tube, context, p.details, p.view] ELSE IF p.details.spline THEN TubeDisplay.ShowSplines[p.tube, context, p.view]; IF p.details.pick THEN Draw3d.PV[p.pick.pos, p.pick.tan, , context, p.view, IF p.pick.t IN (0.0..1.0) THEN cross ELSE none]; }; IF whatChanged # NIL AND p.noDraw THEN RETURN; IF TubeDisplay.NVectors[p.tube, p.details] < p.lim.val THEN Draw2d.DoWithBuffer[context, Action, w, h] ELSE Draw2d.DoNoBuffer[context, Action, w, h]; }; Controller: Controls.ControlProc ~ { <> p: ProgramData _ NARROW[control.data]; MouseAction[p, control.mouse, control]; IF NOT p.noDraw THEN { p.details.on _ NOT p.details.auto OR p.action = shape OR p.mouse.state # held; IF p.action = spline AND p.pick.dividePending THEN { TubePick.DivideSpline[p.pick]; Controls.SetControlVal[p.hold.mag, Vector3d.Mag[p.pick.tubePt0.v1]]; }; SELECT control FROM p.scal => MakeDetails[p]; p.r0, p.r1 => ChangeRadii[p]; p.twist0 => ChangeTwist0[p]; p.twist1 => ChangeTwist1[p]; p.cres => TubeStructure.PropagateCircleRes[p.tube, Real.RoundI[p.cres.val]]; p.eps => MakeDetails[p]; p.hold.dx, p.hold.dy, p.hold.dz => ChangePosition[p]; p.hold.lng, p.hold.lat, p.hold.mag => ChangeTangent[p]; p.cam.pan, p.cam.tilt, p.cam.roll, p.cam.zoom, p.cam.dx, p.cam.dy, p.cam.dz, p.cam.fov => Controls3d.SetCamera[p.cam]; ENDCASE => NULL; }; ViewerOps.PaintViewer[control.graphics, client, FALSE, control]; }; MakeDetails: PROC [p: ProgramData] ~ { TubeStructure.PropagateFrames[p.tube, p.scal.val, p.eps.val]; }; ChangePosition: PROC [p: ProgramData] ~ { TubePick.ChangePosition[p.pick, [p.hold.dx.val, p.hold.dy.val, p.hold.dz.val]]; IF p.details.on THEN MakeDetails[p]; }; ChangeTangent: PROC [p: ProgramData] ~ { v: Triple _ Vector3d.CartesianFromPolar[[p.hold.lng.val, p.hold.lat.val, p.hold.mag.val]]; TubePick.ChangeTangent[p.pick, v]; IF p.details.on THEN MakeDetails[p]; }; ChangeRadii: PROC [p: ProgramData] ~ { r, dr: REAL; n: NAT _ TubePick.NumberPicked[p.pick]; IF n = 0 THEN RETURN; r _ p.r0.val; dr _ (p.r1.val-r)/REAL[n]; IF p.pick.tubePick0.prev # NIL THEN p.pick.tubePick0.prev.r1 _ r; FOR s: Tube _ p.pick.tubePick0, s.next WHILE s # NIL AND s # p.pick.tubePick1.next DO s.r0 _ r; r _ r+dr; s.r1 _ r; ENDLOOP; IF p.pick.tubePick1.next # NIL THEN p.pick.tubePick1.next.r0 _ r; TubePick.RemakePicked[p.pick, p.scal.val, p.eps.val]; }; ChangeTwist0: PROC [p: ProgramData] ~ { nBefore: NAT _ TubePick.BeforePicked[p.pick]; change: REAL _ p.twist0.val-p.twist0.preval; IF nBefore > 0 THEN { dchange: REAL _ 0.0; ddchange: REAL _ change/REAL[nBefore]; FOR s: Tube _ p.tube, s.next WHILE s # p.pick.tubePick0 DO s.twist0 _ s.twist0+dchange; dchange _ dchange+ddchange; s.twist1 _ s.twist1+dchange; ENDLOOP; }; FOR s: Tube _ p.pick.tubePick0, s.next WHILE s # NIL DO s.twist0 _ s.twist0+change; s.twist1 _ s.twist1+change; ENDLOOP; IF p.pick.tubePick1 # NIL THEN Controls.SetControlVal[p.twist1, p.pick.tubePick1.twist1]; IF p.details.on THEN MakeDetails[p]; }; ChangeTwist1: PROC [p: ProgramData] ~ { nPicked: NAT _ TubePick.NumberPicked[p.pick]; change: REAL _ p.twist1.val-p.twist1.preval; IF nPicked > 0 THEN { dchange: REAL _ 0.0; ddchange: REAL _ change/REAL[nPicked]; FOR s: Tube _ p.pick.tubePick0, s.next WHILE s # p.pick.tubePick1.next DO s.twist0 _ s.twist0+dchange; dchange _ dchange+ddchange; s.twist1 _ s.twist1+dchange; ENDLOOP; }; IF p.pick.tubePick1 # NIL THEN FOR s: Tube _ p.pick.tubePick1.next, s.next WHILE s # NIL DO s.twist0 _ s.twist0+change; s.twist1 _ s.twist1+change; ENDLOOP; IF p.details.on THEN MakeDetails[p]; }; ScreenPick: Controls.GraphicsProc ~ { <> p: ProgramData _ NARROW[graphics.data]; MouseAction[p, graphics.mouse, graphics]; IF p.mouse.state = up THEN RETURN; TubePick.ScreenPick[p.tube, p.mouse, p.view, p.pick]; IF p.mouse.button = left THEN Controls3d.FocusHold[p.pick.tan, p.hold]; FocusPick[p]; }; FocusPick: PROC [p: ProgramData] ~ { <> <<>> IF p.pick.tubePick0 # NIL THEN { Controls.SetControlVal[p.r0, p.pick.tubePick0.r0]; Controls.SetControlVal[p.twist0, p.pick.tubePick0.twist0]; }; IF p.pick.tubePick1 # NIL THEN { Controls.SetControlVal[p.r1, p.pick.tubePick1.r1]; Controls.SetControlVal[p.twist1, p.pick.tubePick1.twist1]; }; }; MouseAction: PROC [p: ProgramData, mouse: Mouse, whatChanged: REF ANY] ~ { wasDown: BOOL _ p.mouse.state = down; p.mousePrev _ p.mouse; p.mouse _ mouse; p.action _ SELECT whatChanged FROM p.entries => button, p.graphicsData => select, p.cam.roll, p.cam.pan, p.cam.tilt, p.cam.zoom, p.cam.fov => camera, p.cam.dx, p.cam.dy, p.cam.dz => camera, p.hold.dx, p.hold.dy, p.hold.dz, p.hold.lng, p.hold.lat, p.hold.mag => spline, p.twist0, p.twist1, p.r0, p.r1, p.scal, p.cres => shape, ENDCASE => none; p.noDraw _ p.mouse.state = up AND wasDown AND p.action # button AND p.details.on; Controls.TypeScriptClear[NARROW[p.outer.data, Controls.OuterData]]; }; Toggle: PROC [clientData: REF ANY, type: DetailType, trueName, falseName: Rope.ROPE] ~ { u: UserData _ UserDataFromClientData[clientData]; TubeDisplay.ToggleDetail[u.p.details, type, trueName, falseName, u.o]; MouseAction [u.p, [0, 0, up, left], u.p.entries]; MakeDetails[u.p]; ViewerOps.PaintViewer[u.p.graphics, client, FALSE, u.p.entries]; }; TogLabel: Controls.ClickProc ~ {Toggle[clientData, label, "Label-On", "Label-Off"]}; TogAuto: Controls.ClickProc ~ {Toggle[clientData, auto, "Auto-On", "Auto-Off"]}; TogSkel: Controls.ClickProc ~ {Toggle[clientData, skel, "Skel-On", "Skel-Off"]}; TogPick: Controls.ClickProc ~ {Toggle[clientData, pick, "Pick-On", "Pick-Off"]}; TogSpline: Controls.ClickProc ~ {Toggle[clientData, spline, "Splines-On", "Splines-Off"]}; TogCircles: Controls.ClickProc ~ {Toggle[clientData, circles, "Circles-On", "Circles-Off"]}; TogLines: Controls.ClickProc ~ {Toggle[clientData, lines, "Lines-On", "Lines-Off"]}; TogFrames: Controls.ClickProc ~ {Toggle[clientData, frames, "Frames-On", "Frames-Off"]}; TogNormals: Controls.ClickProc ~ {Toggle[clientData, normals, "Normals-On", "Normals-Off"]}; TogCurv: Controls.ClickProc ~ {Toggle[clientData, curv, "Curv-On", "Curv-Off"]}; TogVel: Controls.ClickProc ~ {Toggle[clientData, vel, "Vel-On", "Vel-Off"]}; TogAcc: Controls.ClickProc ~ {Toggle[clientData, acc, "Acc-On", "Acc-Off"]}; TogXformIO: Controls.ClickProc ~ { u: UserData _ UserDataFromClientData[clientData]; Controls.EntryToggle[u.o, u.p.xformIO _ NOT u.p.xformIO, "Xform IO", "No Xform IO"]; }; IPOut: Controls.ClickProc ~ { u: UserData _ UserDataFromClientData[clientData]; TubeIO.QueryAndIPOut[u.p.tube, u.o, u.p.details, u.p.view]; }; PointsPolyOut: Controls.ClickProc ~ { u: UserData _ UserDataFromClientData[clientData]; m: Matrix _ IF u.p.xformIO THEN Controls3d.GetCamera[] ELSE NIL; TubeIO.QueryAndPointsPolyOut[u.p.tube, u.o, m]; }; MaxPointsPolyOut: Controls.ClickProc ~ { u: UserData _ UserDataFromClientData[clientData]; m: Matrix _ IF u.p.xformIO THEN Controls3d.GetCamera[] ELSE NIL; TubeIO.QueryAndMaxPointsPolyOut[u.p.tube, u.o, m]; }; UserDataFromClientData: PROC [clientData: REF ANY] RETURNS [u: UserData] ~ { u.p _ NARROW[(u.o _ NARROW[clientData]).data]; }; Help: Controls.ClickProc ~ { outer: Controls.OuterData _ NARROW[clientData]; helpMessage: Rope.ROPE _ " Mouse use: any button to manipulate sliders or dials left button to select a point on a spline middle button to select an initial spline right button to select an ending spline General approach: use top row of controls to adjust viewing parameters use middle row to control selected splines use bottom row to control selected point location and tangent\n"; IO.PutF[outer.cmdOut, helpMessage]; }; Commander.Register["///Commands/Tube", TubeDesign, "\nModel tubular structures."]; END. ..