G3dDraw.mesa
Copyright Ó 1985, 1992 by Xerox Corporation. All rights reserved.
Bloomenthal, April 10, 1993 12:45 pm PDT
DIRECTORY Draw2d, G3dBasic, G3dCurve, G3dMatrix, G3dPatch, G3dPlane, G3dShape, G3dSpline, G3dView, Imager, Rope;
G3dDraw: CEDAR DEFINITIONS
~ BEGIN
Type Declarations
DrawType:   TYPE ~ Draw2d.DrawType;    -- {solid, dashed, dotted}
MarkType:   TYPE ~ Draw2d.MarkType;    -- {cross, x, asterisk, dot, none}
IntegerPair:  TYPE ~ G3dBasic.IntegerPair;
NatSequence:  TYPE ~ G3dBasic.NatSequence;
Pair:     TYPE ~ G3dBasic.Pair;
PairSequence:  TYPE ~ G3dBasic.PairSequence;
Quad:    TYPE ~ G3dBasic.Quad;
Triple:    TYPE ~ G3dBasic.Triple;
TripleSequence: TYPE ~ G3dBasic.TripleSequence;
SurfaceSequence: TYPE ~ G3dBasic.SurfaceSequence;
Matrix:    TYPE ~ G3dMatrix.Matrix;
Viewport:   TYPE ~ G3dMatrix.Viewport;
ScreenSequence: TYPE ~ G3dShape.ScreenSequence;
Bezier:    TYPE ~ G3dSpline.Bezier;
Spline:    TYPE ~ G3dSpline.Spline;
SplineSequence: TYPE ~ G3dSpline.SplineSequence;
Context:    TYPE ~ Imager.Context;
ROPE:    TYPE ~ Rope.ROPE;
PointProc:   TYPE ~ PROC [context: Context, pair: Pair];
UseCG6:    TYPE ~ {y, n, maybe};
2d Foundations
CG6Available: PROC RETURNS [BOOL];
Tests for bound ImagerCG6Context.
WrapInCG6: PROC [context: Context, action: PROC];
Apply action after setting CG6 sub-screen variables for the given context.
$CG6 is placed on the context property list during action, and removed after.
No op if CG6 graphics accelerator not available.
The following three procedures utilize CG6 hardware if:
useCG6 = y: (RuntimeError will occur if CG6 hardware is unavailable), or
useCG6 = maybe and call is from within WrapInCG6.
Clear: PROC [
context:   Context,
color:    Triple,
useCG6:   UseCG6 ¬ maybe];
Clear the context to white.
Line2d: PROC [
context:   Context,
p1, p2:   IntegerPair,
drawType:  DrawType,
useCG6:   UseCG6 ¬ maybe];
Draw the specified line, optionally using CG6 hardware.
Mark2d: PROC [
context:   Context,
p:     IntegerPair,
type:    MarkType,
useCG6:   UseCG6 ¬ maybe];
Make the specified mark, optionally using CG6 hardware.
Arrow2d: PROC [
context:   Context,
tail, head:  IntegerPair,
type:    DrawType,
useCG6:   UseCG6 ¬ maybe];
Draw the specified arrow, optionally using CG6 hardware.
Quadrangle: PROC [
context:   Context,
x0, y0, x1, y1: INT,
x2, y2, x3, y3: INT,
useCG6:   UseCG6 ¬ maybe];
Draw the specified quadrangle, optionally using CG6 hardware.
Color
SetColor: PROC [context: Context, color: Triple, useCG6: UseCG6 ¬ maybe];
Set the current color.
Notes
On perspective and viewport:
In the following drawing procedures, if the view matrix has perspective, then
transformed vertices are clipped against the +/- 1 viewing frustum.
viewport, if # [], is applied to the transformed point(s).
(if a viewport is incorporated into the view matrix, clipping errors will occur).
On use of CG6 hardware:
The following drawing procedures utilize CG6 hardware if they are called from within
WrapInCG6; otherwise they utilize Draw2d or Imager procedures.
Point Drawing
Mark: PROC [
context:   Context,
point:    Triple,
view:    Matrix,
viewport:   Viewport,
label:    ROPE ¬ NIL,
markType:  MarkType ¬ cross];
Draw a mark and optional label at the transformed point.
Clips in z, allowing the Imager to clip in x and y.
Incorporating the viewport transformation into view will not affect clipping.
MarkHex: PROC [
context:   Context,
point:    Triple,
view:    Matrix,
viewport:   Viewport,
fill:    BOOL ¬ TRUE,
radius:   INT ¬ 4,
useCG6:   UseCG6 ¬ maybe];
Draw point as a hexagon, whose radius is approximately radius
Box: PROC [
context:   Context,
point:    Triple,
view:    Matrix,
viewport:   Viewport,
w, h:    INT,
label:    ROPE ¬ NIL];
Draw a filled box and optional label at the transformed point.
DoWithPoint: PROC [
context:   Context,
point:    Triple,
pointProc:  PointProc,
view:    Matrix,
viewport:   Viewport];
Apply pointProc to the transformed point.
No op if the transformed point is clipped from the viewing frustum.
Straight Line Drawing
Segment: PROC [
context:   Context,
point0, point1: Triple,
view:    Matrix,
viewport:   Viewport,
drawType:  DrawType ¬ solid];
Draw segment point0-point1.
TaperedSegment: PROC [
context:   Context,
point0, point1: Triple,
radius0, radius1: REAL,
view:    Matrix,
viewInverse:  Matrix ¬ NIL,
viewport:   Viewport];
Draw solid segment point0-point1 with the associated radii, given in real world units.
ForwardFacingSegment: PROC [
context:   Context,
point0, point1: Triple,
view:    Matrix,
viewport:   Viewport,
drawType:  DrawType ¬ solid];
Draw segment point0-point1 if it faces out from the screen (delta-z is positive).
Vector: PROC [
context:   Context,
base, vector:  Triple,
view:    Matrix,
viewport:   Viewport,
label:    ROPE ¬ NIL,
scale:    REAL ¬ 0.2,
absolute2dLen: REAL ¬ 0.0,
markType:  MarkType ¬ none,
drawType:  DrawType ¬ solid];
Draw and optionally label vector. The base is marked with mark.
The label occurs about 6 pixels beyond the end of the vector, in the direction of the vector.
If absolute2dLen # 0.0 then set the length of the 2d vector projection.
Axes: PROC [
context:   Context,
view:    Matrix,
viewport:   Viewport,
scale:    REAL ¬ 1.0,
drawType:  DrawType ¬ solid,
label:    BOOL ¬ TRUE];
Draw the coordinate axes.
ConnectedPairs: PROC [
context:   Context,
pairs:    PairSequence,
closed:   BOOL ¬ TRUE,
drawType:  DrawType ¬ solid];
Connect the sequence of pairs together, optionally closing the loop.
ConnectedPoints: PROC [
context:   Context,
points:   TripleSequence,
view:    Matrix ¬ NIL,
viewport:   Viewport,
closed:   BOOL ¬ TRUE,
drawType:  DrawType ¬ solid];
Connect the sequence of triples together, optionally closing the loop.
The triples are transformed by matrix if non-NIL.
DrawWithConnectedPoints: PROC [
context:   Context,
nPoints:   INT,
getPoint:   PROC [i: INT] RETURNS [Triple],
view:    Matrix ¬ NIL,
viewport:   Viewport,
closed:   BOOL ¬ TRUE,
drawType:  DrawType ¬ solid];
Connect the sequence of triples together, optionally closing the loop.
The triples are transformed by matrix if non-NIL.
Shape Drawing
Options: TYPE ~ RECORD [
flatShade:   BOOL ¬ FALSE,
hiddenLineElim: BOOL ¬ FALSE,
lineType:   DrawType ¬ solid,
backFaces:  {on, off, dashed} ¬ on,
faceNormals:  BOOL ¬ FALSE,
vertexNormals: BOOL ¬ FALSE,
verticesOnly:  BOOL ¬ FALSE,
labelVertices:  BOOL ¬ FALSE,
labelPolygons: BOOL ¬ FALSE,
silhouettesOnly: BOOL ¬ FALSE,
tapered:   BOOL ¬ FALSE,
dimFurtherLines:BOOL ¬ FALSE];
Shape: PROC [
context:   Context,
shape:    G3dShape.Shape,
view:    Matrix,
inverseView:  Matrix ¬ NIL,
viewport:   Viewport,
lightVector: Triple ¬ [1.0, 0.0, 0.0],
screens:   ScreenSequence ¬ NIL,
forceTransform: BOOL ¬ FALSE,
options:    Options ¬ []]
RETURNS [ScreenSequence];
Draw the shape in the given context, with the given options.
If screens = NIL, it is allocated; screens is returned.
If screens.valid or NOT forceTransform then screens are used directly to display;
otherwise they are first computed according to the view matrix.
ApplyInDepthOrder: PROC [
shape:    G3dShape.Shape,
view:    Matrix,
inverseView:  Matrix ¬ NIL,
backToFront:  BOOL ¬ TRUE,
Action:   PROC [id: INT]];
Apply Action to polygons of shape, in back to front or front to back depth order.
Applied to forward faces only if NOT shape.showBackfaces.
SetScreenCoords: PROC [
context:   Context,
shape:    G3dShape.Shape,
view:    Matrix,
viewport:   Viewport ¬ [],
screens:   ScreenSequence ¬ NIL,
setScreenExtent: BOOL ¬ TRUE]
RETURNS [ScreenSequence];
If screens = NIL, it is allocated; screens is returned.
This transforms the shape's vertices by matrix, ignoring shape.matrix.
The .pos, .outCode and .inViewFrustum fields are computed; .fwdFacing is not computed.
Patch Drawing
Patch: PROC [
context:   Context,
view:    Matrix,
viewport:   Viewport,
patch:    G3dPatch.Patch,
nCurves:   INT,
nSegments:  INT];
Draw the surface as as series of curves, each a series of straight segments.
Use forward differencing technique.
Curve Drawing
ConnectedCurve: PROC [
context:   Context,
c:     G3dCurve.Curve,
view:    Matrix ¬ NIL,
viewport:   G3dMatrix.Viewport ¬ [],
nSegments:  INT ¬ 0,
dotted:   BOOL ¬ FALSE,
forInterpress:  BOOL ¬ FALSE];
Draw each spline segment of curve, transforming by view if non-NIL.
If nSegments # 0, use it as number of segments per spline; otherwise, use Lane's formula.
If forInterpress, curve is drawn with minimal number of MaskVectors and MaskTrajectories.
Curves: PROC [
context:   Context,
curves:   SplineSequence,
view:    Matrix ¬ NIL,
viewport:   Viewport,
dotted:   BOOL ¬ FALSE,
forInterpress:  BOOL ¬ FALSE];
Draw the curve, first transforming it if view is non-NIL.
If nSegments # 0, it determines number of curve segments; otherwise, use Lane's formula.
If forInterpress, curve is drawn with minimal number of MaskVectors and MaskTrajectories.
Curve: PROC [
context:   Context,
curve:   Spline,
view:    Matrix ¬ NIL,
viewport:   Viewport,
nSegments:  INT ¬ 0,
forInterpress:  BOOL ¬ FALSE];
Draw the curve, first transforming it if view is non-NIL.
If nSegments # 0, it determines number of curve segments; otherwise, use Lane's formula.
If forInterpress, curve is drawn with minimal number of MaskVectors and MaskTrajectories.
DotCurve: PROC [
context:   Context,
curve:   Spline,
view:    Matrix ¬ NIL,
viewport:   Viewport,
nSegments:  INT ¬ 0];
Draw the curve on the given context as above but as a series of dots.
BezierPolygon: PROC [
context:   Context,
bezier:   Bezier,
view:    Matrix ¬ NIL,
viewport:   Viewport,
drawType:  DrawType ¬ solid,
close:    BOOL ¬ FALSE];
Draw the traditional three sides of the Bezier polygon; if close is true, draw the fourth side.
Triangle Drawing
Triangle: PROC [
context:   Context,
p0, p1, p2:  Triple,
view:    Matrix,
viewport:   Viewport,
drawType:  DrawType ¬ solid];
Draw the triangle.
FrontFacingTriangle: PROC [
context:   Context,
p0, p1, p2:  Triple,
view:    Matrix,
inverseView:  Matrix ¬ NIL,
viewport:   Viewport,
normal:   Triple ¬ [0, 0, 0],
drawType:  DrawType ¬ solid];
Draw the triangle if it is front-facing.
TriangleInfo: TYPE ~ RECORD [p1, p2, p3, normal: Triple];
FillTriangle: PROC [
context:   Context,
triangle:   REF TriangleInfo,
color:    Triple,
view:    Matrix,
viewport:   Viewport];
Fill the triangle with the given color.
ShadeTriangle: PROC [
context:   Context,
triangle:   REF TriangleInfo,
lightVector:  Triple,
view:    Matrix,
viewport:   Viewport,
frontColor:  Triple,
backColor:  Triple];
Shade the triangle; triangle.normal and lightVector are presumed unit length.
ShadeFrontFacingTriangle: PROC [
context:   Context,
triangle:   REF TriangleInfo,
lightVector:  Triple,
view:    Matrix,
inverseView:  Matrix ¬ NIL,
viewport:   Viewport,
color:    Triple];
Shade the triangle if it is front-facing;
triangle.normal and lightVector are presumed unit length.
Polygon Drawing
Polygon: PROC [
context:   Context,
poly:    NatSequence,
pairs:    PairSequence ¬ NIL,
triples:   TripleSequence ¬ NIL,
view:    Matrix ¬ NIL,
viewport:   Viewport,
drawType:  DrawType ¬ solid];
Draw a single polygon. If pairs is NIL then transform the appropriate triples by view.
Either pairs must be non-NIL or both triples and view must be non-NIL.
FrontFacingPolygon: PUBLIC PROC [
context:   Context,
poly:    NatSequence,
view:    Matrix,
inverseView:  Matrix ¬ NIL,
viewport:   Viewport,
normal:   Triple ¬ [0, 0, 0],
pairs:    PairSequence ¬ NIL,
triples:   TripleSequence ¬ NIL,
drawType:  DrawType ¬ solid];
Draw the polygon if it is back-facing; normal is the polygon normal.
if normal is the origin, compute it from triples; no-op if normal = origin and triples = NIL.
If pairs is NIL then transform the appropriate triples by view.
Polygons: PROC [
context:   Context,
pairs:    PairSequence ¬ NIL,
triples:   TripleSequence ¬ NIL,
polygons:   SurfaceSequence,
view:    Matrix ¬ NIL,
viewport:   Viewport,
drawType:  DrawType ¬ solid];
Draw the polygon sequence. If pairs is NIL then transform the triples by view.
Either pairs must be non-NIL or both triples and view must be non-NIL.
FrontFacingPolygons: PROC [
context:   Context,
pairs:    PairSequence ¬ NIL,
triples:   TripleSequence ¬ NIL,
polygons:   SurfaceSequence,
view:    Matrix,
inverseView:  Matrix ¬ NIL,
viewport:   Viewport,
normals:   TripleSequence,
drawType:  DrawType ¬ solid];
Draw the polygon sequence except for back-facing polygons.
If pairs is NIL then transform the triples by view.
normals are the polygon normals (one per polygon).
Miscellaneous Drawing
Plane: PROC [
context:   Context,
plane:    G3dPlane.Plane,
view:    Matrix,
viewport:    Viewport,
size:    REAL ¬ 0.1,
drawType:  DrawType ¬ solid];
Draw a plane.
Circle: PROC [
context:   Context,
p0, p1, p2:  Triple,
nVertices:  INT,
view:    Matrix,
viewport:   Viewport,
drawType:  DrawType ¬ solid];
Draw circle given three of its vertices.
Cube: PROC [
context:    Context,
center:   Triple,
size:    REAL,
view:    Matrix,
viewport:   Viewport,
drawType:  DrawType ¬ solid];
Draw a cube given its center and size (length of an edge).
ScreenRadiusFromSphere: PROC [
sphere:   G3dBasic.Sphere,
view:    Matrix,
viewInverse:  Matrix ¬ NIL,
viewport:   Viewport]
RETURNS [REAL];
Return the (approximate) screen radius for a sphere.
GetSpherePoints: PROC [
center:   Triple,
radius:   REAL,
nCircles:   INT]
RETURNS [TripleSequence];
Return a sequence of points that constitute a sphere and can be drawn by DrawSphere.
Sphere: PROC [
context:   Context,
center:   Triple,
radius:   REAL,
nCircles:   INT,
view:    Matrix,
viewport:   Viewport,
points:   TripleSequence ¬ NIL,
drawType:  DrawType ¬ solid];
Draw a sphere given its center and radius. nCircles is the number of circles drawn.
If points = NIL, obtain them from GetSpherePoints.
Labelling
Label: PROC [
context:   Context,
point:    Triple,
rope:    ROPE,
view:    Matrix,
viewport:   Viewport,
offset:    Pair ¬ [6, -8]];
Label the point with the given rope
LabelPairs: PROC [context: Context, pairs: PairSequence];
Print the pair number next to the pair.
Pendant: PROC [
context:   Context,
view:    Matrix,
size:    REAL ¬ .07,
wPos, hPos:  REAL ¬ .7,
names:   ARRAY [0..6) OF ROPE ¬ ALL[NIL]];
Produce a screen pendant showing the directions. Naming order is is x, y, z, -x, -y, -z.
Asterisk3d: PROC [
context:   Context,
p:     Triple,
size:    REAL,
view:    Matrix,
viewport:   Viewport,
drawType:  DrawType ¬ solid];
Mark a three-dimensional asterisk at p, with dimensions size.
END.