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