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;
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]};
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];