G3dVolumeCmdsBImpl.mesa
Copyright Ó 1985, 1992 by Xerox Corporation. All rights reserved.
Bloomenthal, November 21, 1992 3:03 pm PST
DIRECTORY Args, Buttons, Commander, CommanderOps, Controls, Convert, Draw2d, FileNames, FS, G2dBasic, G3dBasic, G3dControl, G3dCubeDraw, G3dDraw, G3dMatrix, G3dOctree, G3dRayCube, G3dTool, G3dVector, G3dVoxel, Imager, ImagerSample, IO, MessageWindow, Real, Rope, ViewerClasses, ViewerOps;
G3dVolumeCmdsBImpl: CEDAR PROGRAM
IMPORTS Args, Buttons, CommanderOps, Controls, Convert, Draw2d, FileNames, FS, G3dControl, G3dCubeDraw, G3dDraw, G3dMatrix, G3dOctree, G3dRayCube, G3dTool, G3dVector, G3dVoxel, IO, ImagerSample, MessageWindow, Real, Rope, ViewerOps
~ BEGIN
Control:   TYPE ~ Controls.Control;
ClickProc:   TYPE ~ Controls.ClickProc;
OuterData:  TYPE ~ Controls.OuterData;
Ray:    TYPE ~ G3dBasic.Ray;
Triple:   TYPE ~ G3dBasic.Triple;
Camera:   TYPE ~ G3dControl.CameraControl;
Hold:    TYPE ~ G3dControl.Hold;
Matrix:   TYPE ~ G3dMatrix.Matrix;
Tool:    TYPE ~ G3dTool.Tool;
Intersection:  TYPE ~ G3dOctree.Intersection;
IntersectionList: TYPE ~ G3dOctree.IntersectionList;
Cube:    TYPE ~ G3dOctree.Cube;
CubeProc:  TYPE ~ G3dOctree.CubeProc;
Octree:   TYPE ~ G3dOctree.Octree;
OctreeRep:  TYPE ~ G3dOctree.OctreeRep;
RealSequence: TYPE ~ G3dVoxel.RealSequence;
Reals2d:   TYPE ~ G3dVoxel.Reals2d;
Context:   TYPE ~ Imager.Context;
ROPE:    TYPE ~ Rope.ROPE;
Viewer:   TYPE ~ ViewerClasses.Viewer;
Extract a Sub Grid Command
GridExtractCommand: Commander.CommandProc ~ {
argv: CommanderOps.ArgumentVector ¬ CommanderOps.Parse[cmd];
IF argv.argc # 9
THEN RETURN[$Failure, gridExtractUsage]
ELSE {
ENABLE G3dVoxel.Error => IF reason = $NoSuchFile THEN GOTO NoFile;
ReadGrid: PROC [in: ROPE] RETURNS [grid: G3dVoxel.Grid] ~ {
IO.PutF1[cmd.out, "Reading %g . . .", IO.rope[argv[1]]];
grid ¬ G3dVoxel.ReadGridFromFile[FileNames.ResolveRelativePath[in]];
IO.PutRope[cmd.out, " done!\n"];
};
GetIndex0: PROC [reals: RealSequence, r: REAL] RETURNS [NAT] ~ {
FOR n: NAT IN [1..reals.length) DO
IF reals[n] > r THEN RETURN[n-1];
REPEAT
FINISHED => RETURN[reals.length-2]; -- r at max, so i1 = length-1, i0 = length-2
ENDLOOP;
};
g: G3dVoxel.Grid;
in, out, x0, y0, z0, x1, y1, z1: Args.Arg;
[in, out, x0, y0, z0, x1, y1, z1] ¬ Args.ArgsGet[cmd, "%ss%rrrrrr"
! Args.Error => {msg ¬ reason; GOTO Bad}];
g ¬ ReadGrid[in.rope];
IF g.evenlySpaced
THEN RETURN[$Failure, "Sorry, this works for uneven spacing only"]
ELSE {
WriteRealSequence: PROC [key: Rope.ROPE, reals: RealSequence, i0, i1: NAT] ~ {
IO.PutF[s, "%l%g~%l\n", IO.rope["b"], IO.rope[key], IO.rope["B"]];
FOR n: NAT IN [i0..i1] DO
IO.PutF1[s, "%g\t", IO.real[reals[n]]];
ENDLOOP;
IO.PutRope[s, "\n"];
};
ix0: NAT ¬ GetIndex0[g.x, x0.real]+1;
ix1: NAT ¬ GetIndex0[g.x, x1.real];
iy0: NAT ¬ GetIndex0[g.y, y0.real]+1;
iy1: NAT ¬ GetIndex0[g.y, y1.real];
iz0: NAT ¬ GetIndex0[g.z, z0.real]+1;
iz1: NAT ¬ GetIndex0[g.z, z1.real];
s: IO.STREAM ¬ FS.StreamOpen[out.rope, $create];
IO.PutFL[s, "%lNumberOfIndices~%l\n%g\t%g\t%g\n", LIST[
IO.rope["b"], IO.rope["B"], IO.int[ix1-ix0+1], IO.int[iy1-iy0+1], IO.int[iz1-iz0+1]]];
WriteRealSequence["XLocations", g.x, ix0, ix1];
WriteRealSequence["YLocations", g.y, iy0, iy1];
WriteRealSequence["ZLocations", g.z, iz0, iz1];
IO.PutF[s, "%lValues~%l\n", IO.rope["b"], IO.rope["B"]];
FOR i: NAT IN [ix0..ix1] DO
reals2d: Reals2d ¬ g.values[i];
FOR j: NAT IN [iy0..iy1] DO
reals: RealSequence ¬ reals2d[j];
FOR k: NAT IN [iz0..iz1] DO
IO.PutF1[s, "%g\t", IO.real[reals[k]]];
ENDLOOP;
IO.PutRope[s, "\n"];
ENDLOOP;
ENDLOOP;
IO.Close[s];
};
EXITS
NoFile => RETURN[$Failure, "\tno such file"];
Bad => RETURN[$Failure, msg];
};
};
Drawing a Grid
DrawData: TYPE ~ RECORD [tool: Tool, inv: Matrix, xRes, yRes, zRes: INT, mode: ATOM];
GridDrawCommand: Commander.CommandProc ~ {
argv: CommanderOps.ArgumentVector ¬ CommanderOps.Parse[cmd];
IF argv.argc # 4
THEN RETURN[$Failure, gridDrawUsage]
ELSE {
d: REF DrawData ¬ NEW[DrawData];
d.xRes ¬ Convert.IntFromRope[argv[1]];
d.yRes ¬ Convert.IntFromRope[argv[2]];
d.zRes ¬ Convert.IntFromRope[argv[3]];
d.mode ¬ $Circles;
d.tool ¬ G3dTool.MakeTool[
name: "3d Grid Draw",
ops: [TRUE, FALSE],
extraButtons: LIST[Controls.ClickButton["Circles", Mode, d]],
client: [data: d, draw: DrawDraw]];
};
};
Mode: Controls.ClickProc ~ {
d: REF DrawData ¬ NARROW[clientData];
newName: ROPE;
SELECT d.mode FROM
$Taper => {d.mode ¬ $Circles; newName ¬ "Circles"};
$Circles => {d.mode ¬ $Nothing; newName ¬ "Nothing"};
ENDCASE => {d.mode ¬ $Taper; newName ¬ "Tapered"};
Controls.ButtonRelabel[d.tool.outerData, parent.name, newName];
IF mouseButton = blue THEN {
d.tool.camera.mouse.state ¬ up;
ViewerOps.PaintViewer[d.tool.graphics, client, FALSE, NIL];
};
};
DrawDraw: G3dTool.DrawProc ~ {
Lines: PROC [tapered: BOOL] ~ {
DrawSegment: PROC [p0, p1: Triple] ~ {
IF tapered
THEN G3dDraw.TaperedSegment[context, p0, p1, 0.01, 0.01, view, d.inv, vp]
ELSE G3dDraw.Segment[context, p0, p1, view, vp];
};
FOR i: INT IN [0..d.xRes] DO
x: REAL ¬ -xMax+i*size;
FOR j: INT IN [0..d.yRes] DO
y: REAL ¬ -yMax+j*size;
DrawSegment[[x, y, -zMax], [x, y, zMax]];
ENDLOOP;
ENDLOOP;
FOR j: INT IN [0..d.yRes] DO
y: REAL ¬ -yMax+j*size;
FOR k: INT IN [0..d.zRes] DO
z: REAL ¬ -zMax+k*size;
DrawSegment[[-xMax, y, z], [xMax, y, z]];
ENDLOOP;
ENDLOOP;
FOR k: INT IN [0..d.zRes] DO
z: REAL ¬ -zMax+k*size;
FOR i: INT IN [0..d.xRes] DO
x: REAL ¬ -xMax+i*size;
DrawSegment[[x, -yMax, z], [x, yMax, z]];
ENDLOOP;
ENDLOOP;
};
Circles: PROC ~ {
FOR i: INT IN [0..d.xRes] DO
x: REAL ¬ -xMax+i*size;
FOR j: INT IN [0..d.yRes] DO
y: REAL ¬ -yMax+j*size;
FOR k: INT IN [0..d.zRes] DO
z: REAL ¬ -zMax+k*size;
r: REAL ¬ G3dDraw.ScreenRadiusFromSphere[[[x, y, z], 0.01], view, d.inv, vp];
Draw2d.Circle[context, G3dMatrix.TransformD[[x, y, z], view], r, TRUE];
ENDLOOP;
ENDLOOP;
ENDLOOP;
};
d: REF DrawData ¬ NARROW[clientData];
size: REAL ¬ 1.0/REAL[d.xRes];
xMax: REAL ¬ 0.5*d.xRes*size;
yMax: REAL ¬ 0.5*d.yRes*size;
zMax: REAL ¬ 0.5*d.zRes*size;
d.inv ¬ G3dMatrix.Invert[view, d.inv];
IF d.tool.camera.mouse.state # up
THEN Lines[FALSE]
ELSE IF d.mode = $Taper
THEN Lines[TRUE]
ELSE {Lines[FALSE]; IF d.mode = $Circles THEN Circles[]};
};
Rendering a Grid
RenderData:    TYPE ~ RECORD [
tool:      G3dTool.Tool,
stop:      BOOL ¬ FALSE,
reals3d:     G3dVoxel.Reals3d,
cd:      ImagerSample.SampleMap,
cube:      G3dOctree.Cube];
SetSphericalReals: PROC [reals3d: G3dVoxel.Reals3d, size: REAL] ~ {
factor: REAL ¬ 1.0/G3dVector.Length[[0.5*size, 0.5*size, 0.5*size]];
FOR i: NAT IN [0..reals3d.length/2) DO
reals2dA: G3dVoxel.Reals2d ¬ reals3d[i];
reals2dB: G3dVoxel.Reals2d ¬ reals3d[reals3d.length-1-i];
x: REAL ¬ size*(REAL[i]/REAL[reals3d.length-1]-0.5);
FOR j: NAT IN [0..reals2dA.length/2) DO
realsA: G2dBasic.RealSequence ¬ reals2dA[j];
realsB: G2dBasic.RealSequence ¬ reals2dA[reals2dA.length-1-j];
realsC: G2dBasic.RealSequence ¬ reals2dB[j];
realsD: G2dBasic.RealSequence ¬ reals2dB[reals2dA.length-1-j];
y: REAL ¬ size*(REAL[j]/REAL[reals2dA.length-1]-0.5);
FOR k: NAT IN [0..realsA.length/2) DO
z: REAL ¬ size*(REAL[k]/REAL[realsA.length-1]-0.5);
kk: NAT ¬ realsA.length-1-k;
realsA[k] ¬ realsA[kk] ¬ realsB[k] ¬ realsB[kk] ¬
realsC[k] ¬ realsC[kk] ¬ realsD[k] ¬ realsD[kk] ¬
1.0-G3dVector.Length[[x, y, z]]*factor;
ENDLOOP;
ENDLOOP;
ENDLOOP;
};
GridRenderCommand: Commander.CommandProc ~ {
d: REF RenderData ¬ NEW[RenderData];
d.reals3d ¬ G3dVoxel.AllocateGridValues[[70, 70, 70]];
d.cube ¬ G3dOctree.NewCube[1.0];
d.cd ← CtBasic.GetBWColorDisplayMap[];
SetSphericalReals[d.reals3d, d.cube.size];
d.tool ¬ G3dTool.MakeTool[
name: "3d Grid Render",
ops: [FALSE, FALSE],
extraButtons: LIST[
Controls.ClickButton["Render", Render, d],
Controls.ClickButton["Abort", Abort, d]],
client: [data: d, draw: RenderDraw]];
};
Render: Controls.ClickProc ~ {
d: REF RenderData ¬ NARROW[clientData];
view: Matrix ¬ d.tool.views[0].camera.matrix;
height: CARDINAL ¬ ImagerSample.GetSize[d.cd].s;
d.stop ¬ FALSE;
FOR i: NAT IN [0..d.reals3d.length) DO
reals2d: G3dVoxel.Reals2d ¬ d.reals3d[i];
z: REAL ¬ d.cube.size*(0.5-REAL[i]/REAL[d.reals3d.length-1]);
FOR j: NAT IN [0..reals2d.length) DO
reals: G2dBasic.RealSequence ¬ reals2d[j];
y: REAL ¬ d.cube.size*(REAL[j]/REAL[reals2d.length-1]-0.5);
FOR k: NAT IN [0..reals.length) DO
x: REAL ¬ d.cube.size*(REAL[k]/REAL[reals.length-1]-0.5);
p: G2dBasic.Pair ¬ G3dMatrix.TransformD[[x, z, y], view];
ix: NAT ¬ Real.Round[p.x];
iy: NAT ¬ height-Real.Round[p.y];
get: CARDINAL ← CtBasic.GetBWPixel[d.cd, ix, iy];
val: CARDINAL ¬ Real.Round[255.0*reals[k]];
IF d.stop THEN RETURN;
CtBasic.PutBWBox[d.cd, ix, iy, ix+1, iy+1, IF get = 0 THEN val ELSE (get+val)/2];
ENDLOOP;
ENDLOOP;
ENDLOOP;
};
Abort: Controls.ClickProc ~ {NARROW[clientData, REF RenderData].stop ¬ TRUE};
RenderDraw: G3dTool.DrawProc ~ {
d: REF RenderData ¬ NARROW[clientData];
G3dCubeDraw.SimpleCube[context, d.cube, d.tool.views[0].camera.matrix];
};
Ray Tracing An Octree
OctreeData:   TYPE ~ REF OctreeDataRec;
OctreeDataRec:  TYPE ~ RECORD [
outer:        Viewer ¬ NIL,     -- parent viewer
graphics:       Viewer ¬ NIL,     -- graphical display viewer
view:        Matrix ¬ NIL,     -- view transformation
cam:        Camera ¬ NIL,     -- camera
hold:        Hold ¬ NIL,      -- ray control
ray:        Ray,        -- the ray itself
show:        {all, terminal} ¬ terminal,  -- display of Octree
intersectionList:     IntersectionList ¬ NIL,   -- ray-Octree intersections
octree:       Octree ¬ NIL      -- the Octree
];
OctreeTrace: Commander.CommandProc ~ {
argv: CommanderOps.ArgumentVector ~ CommanderOps.Parse[cmd];
IF argv.argc # 2
THEN RETURN[$Failure, "usage: OctreeRayTrace <fileName>"]
ELSE {
d: OctreeData ~ NEW[OctreeDataRec];
d.cam ¬ G3dControl.InitCameraControl[scale: 2.5, proc: OctreeCamera, clientData: d];
d.hold ¬ G3dControl.InitHold[OctreeHoldProc, d];
Controls.ControlRow[d.cam.proxy.xRot, 1];
d.outer ¬ Controls.OuterViewer[
name: Rope.Concat["Octree Trace", argv[1]],
controls: LIST[
d.cam.proxySelect, d.cam.proxy.xMov, d.cam.proxy.yMov, d.cam.proxy.zMov,
d.cam.proxy.xRot, d.cam.proxy.yRot, d.cam.proxy.zRot,
d.cam.scale, d.cam.fieldOfView],
buttons: LIST[
Button["IP Out", OctreeIPOut, 0],
Button["ShowTerminal", OctreeChangeShow],
Button["Ray Trace", OctreeButtonRayTrace]],
graphicsHeight: 400,
drawProc: OctreeDrawProc,
clientData: d
].parent;
d.graphics ¬ NARROW[d.outer.data, OuterData].graphics;
G3dControl.SetHold[d.hold, [0.0, 0.0, 0.0], [0.5, 0.0, 0.0]];
d.octree ¬ NEW[OctreeRep];
d.octree.root ¬ G3dOctree.ReadCubesFromFile[argv[1]];
d.octree.terminalRadius ¬ 0.5*G3dOctree.MinSize[d.octree.root];
d.ray ¬ RayFromHold[d.hold];
Repaint[d.graphics];
};
};
OctreeHoldProc: G3dControl.ControlProc ~ {
d: OctreeData ¬ NARROW[control.clientData];
d.ray ¬ RayFromHold[d.hold];
IF RespondNow[control] THEN OctreeRayTrace[d];
Repaint[d.graphics];
};
OctreeCamera: Controls.ControlProc ~ {
d: OctreeData ~ NARROW[clientData];
G3dControl.UpdateCameraControl[d.cam];
IF RespondNow[control] THEN Repaint[d.graphics];
};
OctreeDrawProc: Draw2d.DrawProc ~ {
d: OctreeData ~ NARROW[clientData];
Action: PROC ~ {
IF whatChanged = NIL
THEN d.view ¬ G3dControl.InitContext[context, d.cam, viewer, , d.view];
OctreeDrawAction[context, clientData, whatChanged, viewer];
};
Draw2d.DoWithBuffer[context, Action];
};
OctreeDrawAction: Draw2d.DrawProc ~ {
cubeProc: CubeProc ~ {
G3dCubeDraw.SimpleCube[
context, cube, d.view, vp, TRUE, IF cube.terminal THEN solid ELSE dashed];
};
d: OctreeData ~ NARROW[clientData];
IF d.show = all
THEN G3dOctree.Apply[d.octree.root, cubeProc]
ELSE G3dCubeDraw.TerminalCubes[context, d.octree.root, d.view, vp, solid];
IF d.intersectionList # NIL
THEN FOR l: IntersectionList ¬ d.intersectionList, l.rest WHILE l # NIL DO
G3dDraw.Mark[
context, l.first.point, d.view, vp,, IF l.first.type = entering THEN cross ELSE x];
ENDLOOP;
G3dDraw.Vector[context, d.ray.base, d.ray.axis, d.view, vp,, 1.0,, asterisk, dotted];
};
OctreeRayTrace: PROC [d: OctreeData] ~ {
d.intersectionList ¬ G3dRayCube.IntersectRayWithOctree[d.ray, d.octree];
};
OctreeButtonRayTrace: ClickProc ~ {
d: OctreeData ¬ NARROW[NARROW[clientData, OuterData].clientData];
OctreeRayTrace[d];
Repaint[d.graphics];
};
OctreeIPOut: ClickProc ~ {IPOut[clientData, OctreeDrawAction]};
OctreeChangeShow: ClickProc ~ {
d: OctreeData ¬ NARROW[NARROW[clientData, OuterData].clientData];
d.show ¬ IF d.show = all THEN terminal ELSE all;
Buttons.ReLabel[parent, IF d.show = all THEN "ShowAll" ELSE "ShowTerminal"];
IF mouseButton = blue THEN Repaint[d.graphics];
};
Ray Tracing A Cube
CubeData:   TYPE ~ REF CubeDataRec;
CubeDataRec:  TYPE ~ RECORD [
outer:       Viewer ¬ NIL,     -- parent viewer
graphics:      Viewer ¬ NIL,     -- graphical display viewer
view:       Matrix ¬ NIL,     -- view transformation
cam:       Camera ¬ NIL,     -- camera
hold:       Hold ¬ NIL,      -- ray control
x, y, z, size:     Control ¬ NIL,     -- location and size of cube
ray:       Ray,        -- the ray itself
tracePending:    BOOL ¬ FALSE,     -- some state
intersection:     Intersection,      -- ray-cube intersection
cube:       Cube ¬ NIL      -- a single cube
];
CubeTrace: Commander.CommandProc ~ {
d: CubeData ~ NEW[CubeDataRec];
d.x ¬ Controls.NewControl["x", vSlider, d, -1.0, 1.0, 0.0, CubeAdjust];
d.y ¬ Controls.NewControl["y", vSlider, d, -1.0, 1.0, 0.0, CubeAdjust];
d.z ¬ Controls.NewControl["z", vSlider, d, -1.0, 1.0, 0.0, CubeAdjust];
d.size ¬ Controls.NewControl["size", vSlider, d, 0.0, 1.0, 0.2, CubeAdjust];
d.hold ¬ G3dControl.InitHold[CubeHoldProc, d];
d.cam ¬ G3dControl.InitCameraControl[fieldOfView: 40, scale: 2.5, proc: CubeCamera, clientData: d];
Controls.ControlRow[d.cam.par.xRot, 1];
d.outer ¬ Controls.OuterViewer[
name: "Cube Trace",
controls: LIST[
d.x, d.y, d.z, d.size, d.hold.x, d.hold.y, d.hold.z, d.hold.pitch, d.hold.yaw, d.hold.mag,
d.cam.par.xRot, d.cam.par.yRot, d.cam.par.zRot, d.cam.scale, d.cam.fieldOfView],
graphicsHeight: 400,
drawProc: CubeDrawProc,
clientData: d
].parent;
d.graphics ¬ NARROW[d.outer.data, OuterData].graphics;
G3dControl.SetHold[d.hold, [0.0, 0.0, 0.0], [0.5, 0.0, 0.0]];
d.cube ¬ G3dOctree.NewCube[d.size.value, [d.x.value, d.y.value, d.z.value]];
d.ray ¬ RayFromHold[d.hold];
Repaint[d.graphics];
};
CubeAdjust: Controls.ControlProc ~ {
d: CubeData ¬ NARROW[control.clientData];
d.cube ¬ G3dOctree.NewCube[d.size.value, [d.x.value, d.y.value, d.z.value]];
IF RespondNow[control]
THEN {
CubeRayTrace[d];
Repaint[d.graphics];
}
ELSE d.tracePending ¬ TRUE;
};
CubeHoldProc: G3dControl.ControlProc ~ {
d: CubeData ¬ NARROW[control.clientData];
d.ray ¬ RayFromHold[d.hold];
IF RespondNow[control]
THEN CubeRayTrace[d]
ELSE d.tracePending ¬ TRUE;
Repaint[d.graphics];
};
CubeCamera: Controls.ControlProc ~ {
d: CubeData ~ NARROW[clientData];
G3dControl.UpdateCameraControl[d.cam];
IF RespondNow[control] THEN {
IF d.tracePending THEN CubeRayTrace[d];
Repaint[d.graphics];
};
};
CubeDrawProc: Draw2d.DrawProc ~ {
d: CubeData ~ NARROW[clientData];
Action: PROC ~ {
IF whatChanged = NIL
THEN d.view ¬ G3dControl.InitContext[context, d.cam, viewer, , d.view];
CubeDrawAction[context, clientData, whatChanged, viewer];
};
Draw2d.DoWithBuffer[context, Action];
};
CubeDrawAction: Draw2d.DrawProc ~ {
d: CubeData ~ NARROW[clientData];
label: ROPE ¬ G3dOctree.RopeFromDirectionSelect[d.intersection.directionSelect];
G3dCubeDraw.SimpleCube[context, d.cube, d.view, vp, TRUE, solid];
G3dDraw.Pendant[context, d.view];
IF d.intersection.type # empty THEN G3dDraw.Mark[
context, d.intersection.point, d.view, vp,, IF d.intersection.type=entering THEN cross ELSE x];
G3dDraw.Vector[context, d.ray.base, d.ray.axis, d.view, vp, label, 1.0,, asterisk, dotted];
};
CubeRayTrace: PROC [d: CubeData] ~ {
d.intersection ¬ G3dRayCube.IntersectRayWithCube[d.ray, d.cube];
d.tracePending ¬ FALSE;
};
CubeIPOut: ClickProc ~ {IPOut[clientData, CubeDrawAction]};
Ray Support
RayFromHold: PROC [hold: Hold] RETURNS [l: Ray] ~ {
l.base ¬ G3dControl.PositionFromHold[hold];
l.axis ¬ G3dControl.VectorFromHold[hold];
};
RayMessage: PROC [l: Ray] ~ {
r: ROPE ¬ IO.PutFR["base: (%g, %g, %g)", IO.real[l.base.x], IO.real[l.base.y], IO.real[l.base.z]];
r ¬ IO.PutFLR["%g, axis: (%g, %g, %g)",
LIST[IO.rope[r], IO.real[l.axis.x], IO.real[l.axis.y], IO.real[l.axis.z]]];
MessageWindow.Append[r, TRUE];
};
Miscellaneous Support
IPOut: PROC [clientData: REF ANY, drawAction: Draw2d.DrawProc] ~ {
outerData: OuterData ~ NARROW[clientData];
fileName: ROPE ¬ Controls.TypescriptReadFileName[outerData.typescript];
Draw2d.IPOut[fileName, drawAction, outerData.clientData];
};
Button: PROC [
name: ROPE ¬ NIL,
proc: ClickProc ¬ NIL,
row, x, y, w, h: INTEGER ¬ 0,
fork: BOOL ¬ TRUE,
doc: ROPE ¬ NIL,
guarded: BOOL ¬ FALSE,
font: Imager.Font ¬ NIL,
style: ATOM ¬ $BlackOnWhite]
RETURNS [Controls.Button]
~ {
RETURN[Controls.ClickButton[name, proc, , row, x, y, w, h, fork, guarded, doc, font, style]];
};
Repaint: PROC [v: Viewer, whatChanged: REF ANY ¬ NIL] ~ {
ViewerOps.PaintViewer[v, client, FALSE, whatChanged];
};
RespondNow: PROC [control: Control] RETURNS [BOOL] ~ {
RETURN[control.mouse.button = right];
};
Start Code
gridExtractUsage: Rope.ROPE ¬ "GridExtract <grid in name> <grid out> <x0 y0 z0 x1 y1 z1>";
gridDrawUsage: Rope.ROPE ¬ "GridDraw <xRes> <yRes> <zRes>";
gridRenderUsage: Rope.ROPE ¬ "GridRender (render a spherical function as a grid)";
G3dTool.Register["OctreeTrace", OctreeTrace, "OctreeTrace <fileName>."];
G3dTool.Register["OctreeCubeTrace", CubeTrace, "OctreeCubeTrace."];
G3dTool.Register["GridExtract", GridExtractCommand, gridExtractUsage];
G3dTool.Register["GridDraw", GridDrawCommand, gridDrawUsage];
G3dTool.Register["GridRender", GridRenderCommand, gridRenderUsage];
END.