G3dControl.mesa
Copyright © 1985 by Xerox Corporation. All rights reserved.
Bloomenthal, April 11, 1992 12:27 pm PDT
Heckbert, June 17, 1988 10:39:40 pm PDT
DIRECTORY Controls, Draw2d, G3dBasic, G3dMatrix, G3dPlane, G3dQuaternion, G3dShape, G3dView, Imager, Rope;
G3dControl: CEDAR DEFINITIONS
~ BEGIN
Imported Types
Control:    TYPE ~ Controls.Control;
ControlProc:   TYPE ~ Controls.ControlProc;
ControlList:   TYPE ~ Controls.ControlList;
Mouse:    TYPE ~ Controls.Mouse;
Viewer:    TYPE ~ Controls.Viewer;
DrawType:   TYPE ~ Draw2d.DrawType;
IntegerPair:   TYPE ~ G3dBasic.IntegerPair;
Pair:     TYPE ~ G3dBasic.Pair;
PairSequence:  TYPE ~ G3dBasic.PairSequence;
Triple:    TYPE ~ G3dBasic.Triple;
TripleSequence:  TYPE ~ G3dBasic.TripleSequence;
Matrix:    TYPE ~ G3dMatrix.Matrix;
Viewport:    TYPE ~ G3dMatrix.Viewport;
Plane:     TYPE ~ G3dPlane.Plane;
Quaternion:   TYPE ~ G3dQuaternion.Quaternion;
ScreenSequence:  TYPE ~ G3dShape.ScreenSequence;
Context:    TYPE ~ Imager.Context;
ROPE:     TYPE ~ Rope.ROPE;
Local Types
Method:    TYPE ~ {controls, geometry};
ProxyMode:   TYPE ~ {par, wor, eye};
MovRot:    TYPE ~ RECORD [
xMov:       Control ← NIL,   -- x translation
yMov:      Control ← NIL,   -- y translation
zMov:      Control ← NIL,   -- z translation
xRot:       Control ← NIL,   -- rotation about x axis
yRot:       Control ← NIL,   -- rotation about y axis
zRot:       Control ← NIL   -- rotation about z axis
];
ArcBall:    TYPE ~ REF ArcBallRep;
ArcBallRep:   TYPE ~ RECORD [
originBody:     BOOLTRUE,   -- rotate wrt body, else wrt world
rotate:       ArcControl ← NIL,  -- data structure for the rotator
translate:      ArcControl ← NIL  -- data structure for the translator
];
ArcControl:   TYPE ~ REF ArcControlRep;
ArcControlRep:   TYPE ~ RECORD [
control:      Control ← NIL,
inCorner:      BOOLFALSE,
firstPlace, lastPlace:   Triple ← [0,0,1],
firstPrev, lastPrev:   Triple ← [0,0,1],
qAbs:       Quaternion ← [0,0,0,1], -- rotation at mouse down
tAbs:       Triple ← [0,0,0],   -- translation at mouse down
qInc:       Quaternion ← [0,0,0,1], -- incremented rotate
tInc:       Triple ← [0,0,0],   -- incremented translate
qTan:       Quaternion ← [0,0,0,1],
qBasis:      Triple ← [0,0,0],
ropeBasis:      Triple ← [0,0,0],
rope:       ROPENIL,
inhibitPrint:     BOOLFALSE,
frame:       Matrix ← NIL,
camera:      CameraControl ← NIL,
clientProc:     ControlProc ← NIL,
clientData:     REF ANYNIL
];
Camera:    TYPE ~ G3dView.Camera;
CameraControl:  TYPE ~ REF CameraControlRep;
CameraControlRep: TYPE ~ RECORD [
General information:
clientData:    REF ANYNIL,   -- client data
proc:      ControlProc ← NIL,  -- client proc called if camera changes
graphics:     Viewer ← NIL,   -- if non-nil, automate the redraw
method:     Method ← controls,  -- interactive controls or geometric specs?
use:      {view, shape, light}, -- what is being controlled?
State:
matrix:     Matrix ← NIL,   -- camera matrix
inverse:     Matrix ← NIL,   -- inverse of camera matrix
view:      Matrix ← NIL,   -- matrix times viewport
miscMatrix:    Matrix ← NIL,   -- for miscellaneous applications
miscVector:    Triple ← [],    -- for miscellaneous applications
miscPosition:    Triple ← [],    -- for miscellaneous applications
save:      Camera ← NIL,   -- for undo
Interactive control:
mouse:     Mouse ← [],    -- current state of the user's mouse
arcBall:     ArcBall ← NIL,   -- alternate to par/wor/eye
proxyMode:    ProxyMode ← par,  -- meaning of proxy controls
proxySelect:    Control ← NIL,   -- set camera.proxyMode
proxy:      MovRot ← [],   -- use defined by camera.proxyMode
par:      MovRot ← [],   -- actual tran & rotate parameter controls
wor:      MovRot ← [],   -- incremental world space xform controls
eye:      MovRot ← [],   -- incremental eye space xform controls
scale:      Control ← NIL,   -- scale about origin
fieldOfView:    Control ← NIL,   -- field of view
hScreen:     Control ← NIL,   -- horizontal screen translation
vScreen:     Control ← NIL,   -- vertical screen translation
current:     Control ← NIL,   -- current control moused
prev:      Control ← NIL,   -- previous control moused
initval:     REAL ← 0.0,    -- init val for current incremental control
incr:      Matrix ← NIL,   -- incremental xform (wor or eye space)
Geometric specification:
eyePoint:     Triple ← [],    -- location of the camera
lookAt:     Triple ← [],    -- camera's view direction
up:      Triple ← [],    -- camera's notion of "up"
roll:      REAL ← 0.0    -- rotation about the camera's axis
];
ArcBall: Quaternion Control of a CameraControl
InitArcBall: PROC [camera: CameraControl, clientProc: ControlProc, clientData: REF ANY]
RETURNS [ArcBall];
Return controls for rotation and translation.
camera is the non-arcBall camera defined in G3dControl.
Call proc, if non-nil, whenever a control is modified, passing data.
SetArcBall: PROC [arcBall: ArcBall, rotate, translate: Triple ← []];
Set the arc ball to the given state.
SetArcBallSize: PROC [arcBall: ArcBall, size: INTEGER];
Set the size of the controls.
CameraControl Procedures
The following procedures provide a standard set of controls for manipulating a "camera" for three dimensional graphics.

The camera parameters are field-of-view, scale (non-differential), translate (x, y, and z), and rotate (x, y, and z). These parameters may be directly manipulated using a subset of the controls (camera.par, camera.fieldOfView, and camera.scale) created by InitCameraControl.

For more intuitive interaction, incremental controls are provided that insert simple translation or rotation transformations into the camera transformation. The six controls in camera.wor provide incremental world space manipulation. The six controls in camera.eye provide incremental eye space manipulation. See WorldToViewMatrix for additional comments.

To conserve screen real estate "proxy" controls may be used; the meaning of these controls may be changed with camera.proxySelect.

Most applications will use InitCameraControl and InitContext.
 InitCameraControl is used when creating a viewer for graphics display;
 InitContext is used inside the applications PaintProc.

A graphics viewer is considered a screen, dimensioned [-1..1] in x and y. Rotations are in degrees.
SetCameraControlMethod: PROC [camera: CameraControl, method: Method];
Set the method for the camera.
CameraControlOrientation: PROC [camera: CameraControl, eyePoint, lookAt, up: Triple, roll: REAL];
Set camera's geometric specifications; up is relative to the camera's view direction.
This call forces camera.method to be geometric.
InitCameraControl: PROC [
proc: ControlProc ← NIL,
clientData: REF ANYNIL,
proxyMode: ProxyMode ← wor,
fieldOfView: REAL ← 60.0,
scale: REAL ← 1.0,
move: Triple ← [0.0, 2.0, 0.0],
rotate: Triple ← [0.0, 0.0, 0.0],
moveRange: REAL ← 10.0]
RETURNS [CameraControl];
Return the set of camera controls and intialize the camera matrix.
Call proc, if non-NIL, whenever a camera control is modified.
If graphics non-NIL, cause repaint whenever a camera control is modified.
The value of move controls  [-moveRange..moveRange].
fieldOfView, scale, move, and rotate are initial camera settings.
fieldOfView is the full field of view.
AddCameraControl: PROC [controls: ControlList, camera: CameraControl, useArcBalls: BOOL]
RETURNS [ControlList];
Add the camera controls to controls.
SetCameraControlGraphics: PROC [camera: CameraControl, graphics: Viewer];
Cause graphics to be redrawn whenever a camera control is modified.
InitContext: PROC [
context: Context,
camera: CameraControl,
viewer: Viewer ← NIL,
clear: BOOLTRUE,
out: Matrix ← NIL]
RETURNS [Matrix];
Optionally clear context and return camera matrix; use out if non-nil.
If viewer is non-nil, concatenate the camera matrix with the viewport.
UpdateCameraControl: PROC [camera: CameraControl];
If the last control modified is a normal parameter (camera.par, .fieldOfView, .scale),
recompute camera matrix.
If the last control modified is an incremental parameter (camera.wor, .eye), it is reset to zero,
the parameter controls are updated, and the matrix is recomputed.
UpdateControl: PROC [camera: CameraControl, control: Control, value: REAL];
This provides client-base control of the camera, rather than user interaction.
The specified control is modified and the camera updated; see above.
GetCameraControlMatrix: PROC [camera: CameraControl] RETURNS [Matrix];
Return the camera matrix.
GetViewMatrix: PROC [camera: CameraControl, out: Matrix] RETURNS [Matrix];
Return camera.view (camera matrix translated by hScreen and vScreen). Use out if non-NIL.
EyeViewFromCameraControl: PROC [camera: CameraControl] RETURNS [Triple];
Return the eye view direction given the camera.
SaveState: PROC [camera: CameraControl, state: Camera];
Save the current, germane camera variables in state.
RestoreState: PROC [camera: CameraControl, state: Camera];
Restore the state variables to the camera.
LastAdjustedCameraControl: PROC RETURNS [CameraControl];
Return the camera most recently adjusted.
CameraControlMessage: PROC [camera: CameraControl] RETURNS [ROPE];
Return a rope describing the settings of those camera controls that
have non-NIL viewers and non-zero settings.
Slice Types and Procedures
Slice:     TYPE ~ REF SliceRep;    -- controls for a planar slice
SliceRep:    TYPE ~ RECORD [
x, y, z:      Control ← NIL,   -- center of plane
phi, theta, size:    Control ← NIL,   -- direction and size of plane
plane:       Plane ← [],    -- the plane equation
matrix:      Matrix ← NIL    -- matrix to transform to plane
];
InitSlice: PROC [data: REF ANYNIL, proc: Controls.ControlProc ← NIL] RETURNS [slice: Slice];
Return a Slice. data is stored in the slice Controls
SetSlice: PROC [slice: Slice, plane: Plane, size: REAL ← 1.0];
Set the slicer controls and matrix such that slice is in the given plane with the given size.
UpdateSlice: PROC [slice: Slice];
Compute slice.matrix.
DrawSlice: PROC [
context: Context,
slice: Slice,
view: Matrix,
viewport: Viewport ← [],
drawType: DrawType ← solid];
Draw slice as a three-dimensional rectangle.
MoveSliceInY: PROC [slice: Slice, amount: REAL];
Move the slice plane in its y-direction by amount.
MoveSliceInZ: PROC [slice: Slice, amount: REAL];
Move the slice plane in its z-direction by amount.
Hold Types and Procedures
Hold:     TYPE ~ REF HoldRep;
HoldRep:    TYPE ~ RECORD [
pitch:       Control ← NIL,   -- declination about the horizontal
yaw:       Control ← NIL,   -- rotation about the absolute vertical
roll:       Control ← NIL,   -- rotation about the relative vertical
mag:       Control ← NIL,   -- magnitude of the pitch-yaw vector
x:        Control ← NIL,   -- x coordinate of position
y:        Control ← NIL,   -- y coordinate of position
z:        Control ← NIL   -- z coordinate of position
];
InitHold: PROC [proc: ControlProc ← NIL, data: REF ANYNIL] RETURNS [Hold];
Return set of seven controls for position and orientation.
SetHold: PROC [hold: Hold, position, tangent: Triple ← [0.0, 0.0, 0.0]];
Set hold.dx, hold.dy, hold.dz to position; hold.pitch, hold.yaw and hold.mag to be tangent.
PositionFromHold: PROC [hold: Hold] RETURNS [Triple];
Return the current hold position.
VectorFromHold: PROC [hold: Hold] RETURNS [t: Triple];
Return the current hold direction as determined by hold.pitch, hold.yaw, and hold.mag.
Interaction with the Display
Pick: TYPE ~ RECORD [offset: Pair, selected: INTEGER];
ScreenPick: PROC [screens: ScreenSequence, screen: IntegerPair] RETURNS [INTEGER];
Return index such that screens[index] is nearest screen; screen in pixels.
Return -1 if screens = NIL.
PointPick: PROC [points: TripleSequence, pairs: PairSequence, view: Matrix, mouse: Mouse]
RETURNS [INTEGER];
Pairs is the projection of points onto the screen and is recomputed if mouse.state = down.
Return the index of the pair nearest the mouse coordinates.
-1 is returned if the length of pairs is less than the length of points.
MovePointPick: PROC [
points: TripleSequence,
pairs: PairSequence ← NIL,
view: Matrix,
viewport: Viewport,
mouse: Mouse,
pick: Pick]
RETURNS [Pick];
If mouse.state = down, then select point that is closest on screen to mouse.
If pairs is non-NIL, assume it represents points transformed by view.
If mouse.state = held, then update the position of the selected point (and pair).
No action if mouse.state = up.
Miscellaneous Procedures
PaintControls: PROC [c1, c2, c3, c4, c5, c6: Control ← NIL];
Repaint non-nil controls.
SetTripleControls: PROC [x, y, z: Control ← NIL, triple: Triple, repaint: BOOLTRUE];
Set the controls to the values of the triple and optionally repaint the controls.
END.