TubeDesignmpl.mesa
Copyright © 1985 by Xerox Corporation. All rights reserved.
Bloomenthal, February 24, 1987 6:14:40 pm PST
DIRECTORY CedarProcess, Commander, Contours, Controls, Controls3d, Draw2d, Draw3d, Icons, Menus, Real, Render3d, Rope, ThreeDBasics, ThreeDMisc, TubeDefs, TubeIO, TubeContour, TubeDisplay, TubeGeometry, TubeMisc, TubePick, TubeRender, Vector3d, ViewerOps;
Initialization
TubeDesign: Commander.CommandProc ~ {
p: ProgramData ~ NEW[ProgramDataRep];
InitProgramData[p];
InitViewer[p];
ReplaceTube[p, ResetTube[]];
};
InitProgramData:
PROC [p: ProgramData] ~ {
p.view ← NEW[MatrixRep];
p.details ← NEW[DetailsRep];
p.pendings ← NEW[PendingsRep];
p.cam ← Controls3d.InitCamera[scale: 3.0, data: p, proc: CameraControl];
p.hold ← Controls3d.InitHold[TubeControl, p];
p.tw0 ← Controls.NewControl["tw0", vSlider, p, -1000., 1000., 0.0, TubeControl];
p.tw1 ← Controls.NewControl["tw1", vSlider, p, -1000., 1000., 0.0, TubeControl];
p.tens0 ← Controls.NewControl["tens0", vSlider, p, -3.0, 3.0, 0.0, TubeControl];
p.tens1 ← Controls.NewControl["tens1", vSlider, p, -3.0, 3.0, 0.0, TubeControl];
p.r0 ← Controls.NewControl["r0", vSlider, p, 0.0, 0.5, 0.0, TubeControl];
p.r1 ← Controls.NewControl["r1", vSlider, p, 0.0, 0.5, 0.0, TubeControl];
p.scale ← Controls.NewControl["scale", vSlider, p, 0.0, 4.0, 1.0, TubeControl];
p.epsilon ← Controls.NewControl["eps", vSlider, p, 0.0, 0.2, 0.03, TubeControl,,,,,,,,,,,, exp];
p.cres ← Controls.NewControl["cres", vSlider, p, 3.0, 25.0, 6.0, TubeControl, , TRUE];
p.lim ← Controls.NewControl["lim", vSlider, p, 0.0, 1000.0, 500.0, TubeControl, , TRUE];
p.controls ←
LIST[
p.hold.x, p.hold.y, p.hold.z, p.hold.lng, p.hold.lat, p.hold.mag,
p.tw0, p.tw1, p.r0, p.r1, p.scale, p.tens0, p.tens1,
p.cam.xGlobal, p.cam.yGlobal, p.cam.zGlobal, p.cam.scale,
p.cam.hScreen, p.cam.vScreen, p.cam.fieldOfView,
p.lim, p.epsilon, p.cres];
p.buttons ←
LIST[
tube:
[name: "Tube Ops:", proc: NIL, row: 3],
[name: "New", proc: NewTube, guarded: TRUE, row: 3, x: 75],
["Branch", Branch, 3],
["Delete", Delete, 3],
["Wt Rad", WeightRadii, 3],
["Linear", CycleRadiusMode, 3],
["Round-Off", TogRound, 3],
["Read", ReadFile, 3],
["Get", GetTube, 3],
["Get Contour", GetContour, 3],
["Write", WriteFile, 3],
miscellany:
[name: "Misc Ops:", proc: NIL, row: 2],
[name: "Rend-Off", proc: TogRender, row: 2, x: 75],
["Smooth", TogRenderStyle, 2],
["BFaces-Off", TogBackFaces, 2],
["Abort Rend", AbortRender, 2],
["Norm IO", TogXformIO, 2],
["PP-Out", WriteFile, 2],
["IP-Out", WriteFile, 2],
line drawing:
[name: "Draw Ops:", proc: NIL, row: 1],
[name: "Vectors-On", proc: TogVectors, row: 1, x: 75],
["Skel-Off", TogSkel, 1],
["Splines-On", TogSpline, 1],
["Ends-On", TogEnds, 1],
["Pick-On", TogPick, 1],
["Label-On", TogLabel, 1],
["Auto-Off", TogAuto, 1],
[name: "Contours-Off", proc: TogContours, row: 0, x: 75],
["Lines-Off", TogLines, 0],
["Frames-Off", TogFrames, 0],
["Normals-Off", TogNormals, 0],
["Curv-Off", TogCurv, 0],
["Vel-Off", TogVel, 0],
["Acc-Off", TogAcc, 0]];
};
InitViewer:
PROC [p: ProgramData] ~ {
Controls.ControlRow[p.cam.xGlobal, 1];
p.outer ← Controls.OuterViewer[
name: "Tube Design",
buttons: p.buttons,
controls: p.controls,
controlSizes: [20, 200, 60, 20, 60, 150, 150],
typeScriptHeight: 18,
graphicsHeight: 300,
graphicsProc: ScreenPick,
graphicsShow: GraphicsShow,
data: p,
destroyProc: DestroyProc,
noOpen: TRUE];
p.outerData ← NARROW[p.outer.data];
p.buttons ← p.outerData.buttons;
p.graphics ← p.outerData.graphics;
p.graphicsData ← NARROW[p.graphics.data];
p.outer.icon ← Icons.NewIconFromFile["///Commands/Tube.icon", 0];
ViewerOps.OpenIcon[p.outer];
};
GraphicsShow: Controls.GraphicsShow ~ {
p: ProgramData ~ NARROW[data];
Action:
PROC ~ {
p.view ← Controls3d.InitContext[context, p.cam, p.view];
IF p.details.spline
AND p.details.ends
THEN TubeDisplay.DrawSplineEnds[p.tube, context, p.view];
IF p.details.enabled
THEN TubeDisplay.DrawTube[p.tube, context, p.details, p.view]
ELSE IF p.details.spline THEN TubeDisplay.DrawSplines[p.tube, context, p.view];
IF p.details.pick
AND p.pick #
NIL
AND p.pick.tube #
NIL
THEN
Draw3d.Vector[context, p.pick.pos, p.pick.tan, 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.value
THEN Draw2d.DoWithBuffer[context, Action]
ELSE Action[];
};
User Interaction
Moused:
PROC [p: ProgramData, mouse: Mouse, whatChanged:
REF
ANY, msg:
ROPE ←
NIL] ~ {
p.mousePrev ← p.mouse;
p.mouse ← mouse;
p.action ←
SELECT whatChanged
FROM
p.buttons => button,
p.graphicsData => select,
p.cam => camera,
p.hold.lat, p.hold.lng, p.hold.mag, p.hold.x, p.hold.y, p.hold.z, p.epsilon => spline,
p.scale, p.r0, p.r1, p.tw0, p.tw1, p.cres => shape,
ENDCASE => none;
p.details.enabled ← NOT p.details.autoSimplify OR p.action = shape OR p.mouse.state = up;
p.noDraw ← p.mouse.state = up AND p.action # button AND NOT p.details.autoSimplify;
IF
NOT p.noDraw
THEN
SELECT whatChanged
FROM
p.scale => p.pendings.scale ← TRUE;
p.r0, p.r1 => p.pendings.r ← TRUE;
p.tw0 => p.pendings.tw0 ← TRUE;
p.tw1 => p.pendings.tw1 ← TRUE;
p.tens0, p.tens1 => p.pendings.tens ← TRUE;
p.cres => p.pendings.cres ← TRUE;
p.epsilon => p.pendings.epsilon ← TRUE;
p.hold.x, p.hold.y, p.hold.z => p.pendings.holdPosition ← TRUE;
p.hold.lng, p.hold.lat, p.hold.mag => p.pendings.holdTangent ← TRUE;
ENDCASE;
IF p.action = spline AND p.pick.dividePending THEN DivideSpline[p];
IF msg =
NIL
THEN Controls.TypeScriptClear[p.outerData]
ELSE Controls.TypeScriptWrite[p.outerData, msg];
};
DivideSpline:
PROC [p: ProgramData] ~ {
TubePick.DivideSpline[p.pick];
Controls.SetSliderDialValue[p.hold.mag, Vector3d.Length[p.pick.tube.v1]];
};
CheckPendingAndRePaint:
PROC [p: ProgramData, forceReDraw:
BOOL ←
FALSE] ~ {
p.pendings.shape ← p.pendings.shape OR p.pendings.holdPosition OR p.pendings.holdTangent;
p.pendings.skin ←
p.pendings.skin OR p.pendings.shape OR p.pendings.r OR p.pendings.tens OR
p.pendings.tw0 OR p.pendings.tw1 OR p.pendings.epsilon;
IF p.pendings.holdPosition
THEN
TubePick.ChangePosition[p.pick, [p.hold.x.value, p.hold.y.value, p.hold.z.value]];
IF p.pendings.holdTangent
THEN TubePick.ChangeTangent[p.pick,
Vector3d.CartesianFromPolar[[p.hold.lng.value, p.hold.lat.value, p.hold.mag.value]]];
IF p.pendings.scale THEN TubeGeometry.ReScale[p.tube, p.scale.value, 0.0];
IF p.pendings.cres THEN TubeContour.PropagateCircleRes[p.tube, Real.RoundI[p.cres.value]];
IF p.pendings.tens THEN TubePick.ChangeTension[p.pick, p.tens0.value, p.tens1.value];
IF p.details.skin
OR p.details.shape
THEN {
IF p.pendings.r
THEN
TubePick.ChangeRadii[p.pick, p.r0.value, p.r1.value, p.scale.value, p.epsilon.value];
IF p.pendings.tw0
THEN {
TubePick.ChangeTw0[p.pick, p.tw0.value, p.tw0.valuePrev];
IF p.pick.selected1 # NIL THEN Controls.SetSliderDialValue[p.tw1, p.pick.selected1.tw1];
};
IF p.pendings.tw1 THEN TubePick.ChangeTw1[p.pick, p.tw1.value, p.tw1.valuePrev];
IF p.pendings.shape OR p.pendings.skin THEN MakeDetails[p];
};
IF forceReDraw THEN p.noDraw ← FALSE;
IF p.vectors THEN ViewerOps.PaintViewer[p.graphics, client, FALSE, p];
IF p.render
THEN {
IF p.renderProcess =
NIL
OR CedarProcess.GetStatus[p.renderProcess] # busy
THEN {
IF p.pendings.skin OR p.pendings.cres OR p.pendings.scale OR p.pendings.r OR p.pendings.tens THEN TubeRender.AddTube[p.tube, p.context3d, p.renderStyle];
p.renderProcess ← CedarProcess.Fork[ForkRender, p];
};
};
TubeMisc.ClearPendings[p.pendings];
};
CameraControl: Controls3d.CameraProc ~ {
p: ProgramData ~ NARROW[data];
Moused[p, control.mouse, control];
IF p.noDraw THEN RETURN;
IF control.mouse.button = right THEN CheckPendingAndRePaint[p];
};
TubeControl: Controls.ControlProc ~ {
p: ProgramData ~ NARROW[control.data];
Moused[p, control.mouse, control];
IF p.noDraw THEN RETURN;
IF control.mouse.button = right THEN CheckPendingAndRePaint[p];
};
MakePick:
PROC [p: ProgramData] ~ {
p.pick ← NEW[PickRep ← [tube: p.tube]];
p.pendings.holdPosition ← p.pendings.holdTangent ← FALSE;
TubePick.SetPickPoint[p.pick];
IF p.hold.x.viewer # NIL THEN Controls3d.FocusHold[p.pick.tan, p.hold];
};
ScreenPick: Controls.GraphicsProc ~ {
Proc called as result of mousing down in graphics viewer.
p: ProgramData ~ NARROW[graphics.data];
Moused[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];
ViewerOps.PaintViewer[graphics.viewer, client, FALSE, graphics];
};
FocusPick:
PROC [p: ProgramData] ~ {
adjust controls to selected splines settings:
IF p.pick.selected0 #
NIL
THEN {
Controls.SetSliderDialValue[p.r0, p.pick.selected0.r0];
Controls.SetSliderDialValue[p.tw0, p.pick.selected0.tw0];
Controls.SetSliderDialValue[p.tens0, p.pick.selected0.tens0];
};
IF p.pick.selected1 #
NIL
THEN {
Controls.SetSliderDialValue[p.r1, p.pick.selected1.r1];
Controls.SetSliderDialValue[p.tw1, p.pick.selected1.tw1];
Controls.SetSliderDialValue[p.tens1, p.pick.selected1.tens1];
};
};
Tube Modification
NewTube: ClickProc ~ {ReplaceTube[UserDataFromClientData[clientData].p, ResetTube[]]};
MakeDetails:
PROC [p: ProgramData] ~ {
TubeGeometry.MakeFrames[p.tube, p.epsilon.value, p.scale.value, 0, p.details.skin, p.round];
, p.view];
};
ResetTube:
PROC RETURNS [tube: Tube] ~ {
tube ← NEW[TubeRep ← [p0: [-0.5,0.,0.], p1: [0.5,0.,0.], v0: [1.,1.,0.], v1: [1.,1.,0.]]];
TubeGeometry.SetCoeffs[tube];
tube.name ← "Tube";
};
ReplaceTube:
PROC [p: ProgramData, tube: Tube] ~ {
p.tube ← tube;
IF tube.name = NIL THEN tube.name ← "Tube";
p.pendings ← NEW[PendingsRep ← [shape: TRUE]];
MakePick[p];
FocusPick[p];
Moused[p, [0, 0, up, left], p.buttons];
CheckPendingAndRePaint[p, TRUE];
};
Branch: ClickProc ~ {
p: ProgramData ~ UserDataFromClientData[clientData].p;
IF p.pick.t = 0.0 AND p.pick.tube.prev = NIL THEN RETURN;
IF p.pick.dividePending THEN DivideSpline[p];
TubeMisc.AddBranch[p.pick.tube, TubeMisc.NewBranch[p.pick.tube]];
CheckPendingAndRePaint[p, TRUE];
};
Delete: ClickProc ~ {
p: ProgramData ~ UserDataFromClientData[clientData].p;
TubeMisc.Delete[p.pick.selected0];
p.pick.selected0 ← p.pick.selected1 ← NIL;
TubeMisc.UnSelectAll[p.tube];
IF NOT TubeMisc.Find[p.pick.tube, p.tube] THEN p.pick.tube ← NIL;
CheckPendingAndRePaint[p, TRUE];
};
WeightRadii: ClickProc ~ {
p: ProgramData ~ UserDataFromClientData[clientData].p;
TubeMisc.SetDescendantRadii[p.tube, p.radiusMode];
p.pendings.skin ← TRUE;
CheckPendingAndRePaint[p, TRUE];
};
GetContour: ClickProc ~ {
u: UserData ~ UserDataFromClientData[clientData];
c: Control ~ Controls.LastControlMoused[];
IF c #
NIL
AND c.type = contour
AND
NOT c.viewer.destroyed
THEN {
TubeContour.AddContour[u.p.tube, Contours.Orient[Contours.FromControl[c, u.p.pick.t]]];
Moused[u.p, [0, 0, up, left], u.p.buttons, "Contour received\n"];
u.p.pendings.skin ← TRUE;
CheckPendingAndRePaint[u.p, TRUE];
}
ELSE {
Controls.TypeScriptWrite[u.o, "First middle-click a contour viewer\n"];
RETURN;
};
};
GetTube: ClickProc ~ {
u: UserData ~ UserDataFromClientData[clientData];
tube: Tube ~ TubePick.LastTubePicked[];
IF tube #
NIL
THEN ReplaceTube[u.p, tube]
ELSE Controls.TypeScriptWrite[u.o, "First click a tube viewer\n"];
};
Changing State
TogDetail:
PROC [r:
REF
ANY, button: Menus.MouseButton, type: DetailType, name:
ROPE] ~ {
u: UserData ~ UserDataFromClientData[r];
m: Mouse ~ [0, 0, up, SELECT button FROM red => left, yellow => middle, ENDCASE => right];
wasShape: BOOL ~ u.p.details.shape;
wasSkin: BOOL ~ u.p.details.skin;
TubeMisc.ToggleDetail[u.p.details, type, Rope.Cat[name, "-On"], Rope.Cat[name, "-Off"], u.o];
Moused[u.p, m, u.p.buttons];
IF wasShape # u.p.details.shape THEN u.p.pendings.shape ← u.p.details.shape;
IF wasSkin # u.p.details.skin THEN u.p.pendings.skin ← u.p.details.skin;
IF type # autoSimplify AND button = blue THEN CheckPendingAndRePaint[u.p, TRUE];
};
TogLabel: ClickProc ~ {TogDetail[clientData, mouseButton, label, "Label"]};
TogAuto: ClickProc ~ {TogDetail[clientData, mouseButton, autoSimplify, "Auto"]};
TogSkel: ClickProc ~ {TogDetail[clientData, mouseButton, skeleton, "Skel"]};
TogPick: ClickProc ~ {TogDetail[clientData, mouseButton, pick, "Pick"]};
TogSpline: ClickProc ~ {TogDetail[clientData, mouseButton, spline, "Splines"]};
TogEnds: ClickProc ~ {TogDetail[clientData, mouseButton, ends, "Ends"]};
TogContours: ClickProc ~ {TogDetail[clientData, mouseButton, contours, "Contours"]};
TogLines: ClickProc ~ {TogDetail[clientData, mouseButton, lines, "Lines"]};
TogFrames: ClickProc ~ {TogDetail[clientData, mouseButton, frames, "Frames"]};
TogNormals: ClickProc ~ {TogDetail[clientData, mouseButton, normals, "Normals"]};
TogCurv: ClickProc ~ {TogDetail[clientData, mouseButton, curvature, "Curv"]};
TogVel: ClickProc ~ {TogDetail[clientData, mouseButton, velocity, "Vel"]};
TogAcc: ClickProc ~ {TogDetail[clientData, mouseButton, acceleration, "Acc"]};
TogXformIO: ClickProc ~ {
u: UserData ~ UserDataFromClientData[clientData];
Controls.ButtonToggle[u.o, u.p.xformIO ← NOT u.p.xformIO, "Xfrm IO", "Norm IO"];
};
TogRender: ClickProc ~ {
u: UserData ~ UserDataFromClientData[clientData];
Controls.ButtonToggle[u.o, u.p.render ← NOT u.p.render, "Rend-On", "Rend-Off"];
IF u.p.render
THEN {
IF u.p.context3d = NIL THEN u.p.context3d ← Render3d.InitContext3d[];
TubeRender.AddTube[u.p.tube, u.p.context3d, u.p.renderStyle];
};
IF mouseButton = blue THEN CheckPendingAndRePaint[u.p];
};
TogVectors: ClickProc ~ {
u: UserData ~ UserDataFromClientData[clientData];
Controls.ButtonToggle[u.o, u.p.vectors ← NOT u.p.vectors, "Vectors-On", "Vectors-Off"];
IF mouseButton = blue THEN CheckPendingAndRePaint[u.p, TRUE];
};
TogRenderStyle: ClickProc ~ {
RopeFromType:
PROC [type: RenderStyle]
RETURNS [rope:
ROPE] ~ {
rope ← SELECT type FROM smooth => "Smooth", shiny => "Shiny", ENDCASE => "Faceted";
};
u: UserData ~ UserDataFromClientData[clientData];
old: RenderStyle ~ u.p.renderStyle;
u.p.renderStyle ← IF old = RenderStyle.LAST THEN RenderStyle.FIRST ELSE SUCC[old];
IF mouseButton = blue THEN CheckPendingAndRePaint[u.p];
Controls.ButtonReLabel[u.o, RopeFromType[old], RopeFromType[u.p.renderStyle]];
Render3d.SetRenderStyle[u.p.context3d, u.p.tube.name, u.p.renderStyle];
};
TogBackFaces: ClickProc ~ {
u: UserData ~ UserDataFromClientData[clientData];
u.p.backFaces ← NOT u.p.backFaces;
Controls.ButtonToggle[u.o, u.p.backFaces, "BFaces-On", "BFaces-Off"];
Render3d.SetInsideVisible[u.p.context3d, u.p.tube.name, u.p.backFaces];
IF mouseButton = blue THEN CheckPendingAndRePaint[u.p];
};
TogRound: ClickProc ~ {
u: UserData ~ UserDataFromClientData[clientData];
u.p.round ← NOT u.p.round;
u.p.pendings.shape ← TRUE;
Controls.ButtonToggle[u.o, u.p.round, "Round-On", "Round-Off"];
IF mouseButton = blue THEN CheckPendingAndRePaint[u.p];
};
CycleRadiusMode: ClickProc ~ {
u: UserData ~ UserDataFromClientData[clientData];
Roper:
PROC [mode: RadiusMode]
RETURNS [
ROPE] ~ {
RETURN[SELECT mode FROM linear => "Linear", ENDCASE => "Square"];
};
old: RadiusMode ~ u.p.radiusMode;
u.p.radiusMode ← IF old = RadiusMode.LAST THEN RadiusMode.FIRST ELSE SUCC[old];
IF u.o # NIL THEN Controls.ButtonReLabel[u.o, Roper[old], Roper[u.p.radiusMode]];
};