TubeDesignmpl.mesa
Copyright © 1985 by Xerox Corporation. All rights reserved.
Bloomenthal, May 17, 1986 11:04:18 am PDT
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:    BOOLFALSE,   -- xform points by camera when writing to file
details:    Details ← NIL,
circle:     PairSequence ← NIL,
noDraw:    BOOLFALSE
];
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 ~ {
Proc called as result of any slider or dial manipulation.
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 ~ {
Proc called as result of mousing down in graphics viewer.
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] ~ {
adjust controls to selected splines settings:
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.
..