IF shape #
NIL
AND shape.surfaces #
NIL
AND shape.vertices #
NIL
THEN {
-- don't wedge!
SetColor:
PROC [color: Triple] ~ {
IF color # nowColor THEN G3dDraw.SetColor[context, nowColor ¬ color, useCG6];
};
DrawLine:
PROC [i0, i1:
INT] ~ {
s0: G3dBasic.Screen ¬ screens[i0];
s1: G3dBasic.Screen ¬ screens[i1];
IF
color
THEN
SetColor[G3dVector.Midpoint[shape.vertices[i0].color, shape.vertices[i1].color]];
SELECT
TRUE
FROM
s0.visible AND s1.visible => G3dDraw.Line2d[context, s0.intPos, s1.intPos, type, useCG6];
(s0.l
AND
s1.l)
OR(s0.r
AND
s1.r)
OR(s0.b
AND
s1.b)
OR(s0.t
AND
s1.t)
OR(s0.n
AND
s1.n)
=>
NULL;
ENDCASE => {
cp: G3dClip.ClippedPair ¬ G3dClip.NearH[s0.quad, s1.quad]; -- let Imager do 2d clip
IF
NOT cp.off
THEN {
p0: Pair ¬ [vp.scale.x*cp.c0.x+vp.translate.x, vp.scale.y*cp.c0.y+vp.translate.y];
p1: Pair ¬ [vp.scale.x*cp.c1.x+vp.translate.x, vp.scale.y*cp.c1.y+vp.translate.y];
ip0: IntegerPair ¬ [Real.Round[p0.x], Real.Round[p0.y]];
ip1: IntegerPair ¬ [Real.Round[p1.x], Real.Round[p1.y]];
G3dDraw.Line2d[context, ip0, ip1, type, useCG6];
};
};
};
DrawPolygon:
PROC [poly: NatSequence] ~ {
IF poly #
NIL
AND poly.length > 0
THEN {
stop: CARDINAL ~ poly.length-1;
FOR i: INT IN [0..stop) DO DrawLine[poly[i], poly[i+1]]; ENDLOOP;
DrawLine[poly[stop], poly[0]];
};
};
DrawTaperedPolygon:
PROC [poly: NatSequence] ~ {
IF poly #
NIL
AND poly.length > 0
THEN {
stop: CARDINAL ~ poly.length-1;
FOR i: INT IN [0..stop) DO DrawTaperedSegment[poly[i], poly[i+1]]; ENDLOOP;
DrawTaperedSegment[poly[stop], poly[0]];
};
};
DrawPoly:
PROC [p: NatSequence] ~ {
IF options.
tapered
THEN DrawTaperedPolygon[p]
ELSE DrawPolygon[p];
};
DrawTaperedSegment:
PROC [i0, i1:
INT] ~ {
G3dDraw.TaperedSegment[context, shape.vertices[i0].point, shape.vertices[i1].point, 0.003, 0.003, x, inverse, vp];
};
DrawVec:
PROC [base, vector, color: Triple] ~ {
Process.CheckForAbort[];
SetColor[color];
G3dDraw.Vector[context, base, vector, x, viewport,, vectorScale];
};
zMin, zDiv: REAL;
nowColor: Triple ¬ [1.0, 1.0, 1.0];
polys: SurfaceSequence ¬ shape.surfaces;
type: DrawType ¬ options.lineType;
mat: Matrix ¬ IF shape.matrix # NIL THEN shape.matrix ELSE G3dMatrix.Identity[];
x: Matrix ¬ G3dMatrix.Mul[shape.matrix ¬ mat, view, G3dMatrix.ObtainMatrix[]];
inverse: Matrix ¬
IF options.
flatShade
OR options.
hiddenLineElim
OR options.
tapered
THEN (
IF inverseView #
NIL
THEN inverseView
ELSE G3dMatrix.Invert[x, G3dMatrix.ObtainMatrix[]])
ELSE NIL;
vp: Viewport ~ viewport;
useCG6: G3dDraw.UseCG6 ¬ IF Imager.GetProp[context, $CG6] # NIL THEN y ELSE n;
color: BOOL ¬ G3dShape.VertexValid[shape, color];
IF options.
labelVertices
OR
options.
labelPolygons
OR
options.
faceNormals
THEN G3dShape.SetFaceCenters[shape];
IF options.faceNormals THEN G3dShape.SetFaceNormals[shape];
IF options.vertexNormals THEN G3dShape.SetVertexNormals[shape];
IF strokeWidth # 0.0 THEN Imager.SetStrokeWidth[context, strokeWidth];
IF options.
dimFurtherLines
THEN {
zDif: REAL;
IF shape.objectExtent.min = shape.objectExtent.max
THEN shape.objectExtent ¬ G3dShape.BoundingBox[shape];
zMin ¬ G3dMatrix.Transform[shape.objectExtent.min, x].z;
zDif ¬ G3dMatrix.Transform[shape.objectExtent.max, x].z-zMin;
zDiv ¬ IF zDif # 0.0 THEN 0.8/zDif ELSE 0.8;
};
IF
forceTransform
OR screens =
NIL
OR
NOT screens.screensValid
THEN screens ¬ SetScreenCoords[context, shape, x, viewport, screens];
IF shape.edges = NIL THEN shape.edges ¬ G3dShape.MakeEdges[shape];
SELECT
TRUE
FROM
options.
hiddenLineElim,
options.
flatShade => {
DoPoly:
PROC [id:
INT] ~ {
DoTriangle:
PROC [i1, i2, i3:
INT] ~ {
need (why?) reverse poly order so back-face removal of agrees with line-drawn
t.p3 ¬ shape.vertices[i1].point;
t.p2 ¬ shape.vertices[i2].point;
t.p1 ¬ shape.vertices[i3].point;
IF options.
hiddenLineElim
THEN G3dDraw.FillTriangle[context, t, [1.0, 1.0, 1.0], x, vp]
ELSE G3dDraw.ShadeTriangle[context, t, lightVector, x, vp, f.color, f.color];
};
poly: G3dBasic.NatSequence ¬ shape.surfaces[id].vertices;
f: G3dShape.Face ¬ shape.faces[id];
t.normal ¬ f.normal;
IF poly.length = 3
THEN DoTriangle[poly[0], poly[1], poly[2]]
ELSE
FOR i:
INT
IN [1..poly.length-2]
DO
DoTriangle[poly[0], poly[i], poly[i+1]];
ENDLOOP;
IF options.
hiddenLineElim
THEN {
G3dDraw.SetColor[context, f.color];
DrawPolygon[poly];
};
};
t: REF G3dDraw.TriangleInfo ¬ NEW[G3dDraw.TriangleInfo];
ApplyInDepthOrder[shape, x, inverse, TRUE, DoPoly];
};
options.
silhouettesOnly
=> {
G3dShape.SetFwdFacingFaces[shape, x];
FOR n:
INT
IN [0..shape.edges.length)
DO
e: Edge ¬ shape.edges[n];
IF e.p0 = -1
OR e.p1 = -1
OR
shape.faces[e.p0].fwdFacing # shape.faces[e.p1].fwdFacing
THEN DrawLine[e.v0, e.v1];
ENDLOOP;
};
options.
backFaces = on => {
IF
NOT options.
verticesOnly
THEN
FOR n:
INT
IN [0..shape.edges.length)
DO
e: Edge ¬ shape.edges[n];
Process.CheckForAbort[];
IF options.
dimFurtherLines
THEN {
z:
REAL ¬ 0.5*(
G3dMatrix.Transform[shape.vertices[e.v0].point, x].z+
G3dMatrix.Transform[shape.vertices[e.v1].point, x].z);
Imager.SetGray[context, 0.2+zDiv*(z-zMin)];
};
IF options.
tapered
THEN DrawTaperedSegment[e.v0, e.v1]
ELSE DrawLine[e.v0, e.v1];
ENDLOOP;
IF options.
vertexNormals
OR options.
verticesOnly
OR options.
labelVertices
THEN
FOR n:
INT
IN [0..shape.vertices.length)
DO
v: Vertex ¬ shape.vertices[n];
Process.CheckForAbort[];
IF options.
vertexNormals
THEN DrawVec[v.point, v.normal, v.color]
ELSE
IF
options.
verticesOnly
THEN G3dDraw.Mark2d[context, screens[n].intPos, dot, useCG6];
IF options.
labelVertices
THEN
Draw2d.Label[context, screens[n].pos, IO.PutFR1["%g", IO.int[n]]];
ENDLOOP;
IF options.
faceNormals
OR options.
labelPolygons
THEN
FOR n:
INT
IN [0..shape.faces.length)
DO
f: G3dShape.Face ¬ shape.faces[n];
Process.CheckForAbort[];
IF options.faceNormals THEN DrawVec[f.center, f.normal, f.color];
IF options.
labelPolygons
THEN
G3dDraw.Mark[context, f.center, x, viewport, IO.PutFR1["%g", IO.int[n]], none];
ENDLOOP;
};
options.
backFaces = off => {
G3dShape.SetFwdFacingFaces[shape, x];
IF
NOT options.
tapered
AND
NOT options.
verticesOnly
THEN
FOR n:
INT
IN [0..shape.edges.length)
DO
e: Edge ¬ shape.edges[n];
IF (e.p0 # -1
AND shape.faces[e.p0].fwdFacing)
OR
(e.p1 # -1
AND shape.faces[e.p1].fwdFacing)
THEN DrawLine[e.v0, e.v1];
ENDLOOP;
IF options.
vertexNormals
OR options.
verticesOnly
OR options.
faceNormals
OR
options.
labelVertices
OR options.
labelPolygons
OR options.
tapered
THEN
FOR n:
INT
IN [0..shape.surfaces.length)
DO
poly: NatSequence ¬ shape.surfaces[n].vertices;
IF NOT shape.faces[n].fwdFacing THEN LOOP;
IF options.
vertexNormals
OR options.
verticesOnly
OR
options.
labelVertices
THEN
FOR n:
INT
IN [0..poly.length)
DO
id: INT ¬ poly[n];
v: Vertex ¬ shape.vertices[id];
IF options.
vertexNormals
THEN DrawVec[v.point, v.normal, v.color]
ELSE
IF options.
verticesOnly
THEN
Draw2d.Mark[context, screens[poly[n]].pos, dot];
IF options.
labelVertices
THEN
Draw2d.Label[context, screens[id].pos, IO.PutFR1["%g", IO.int[id]]];
ENDLOOP;
IF
options.
faceNormals
OR options.
labelPolygons
THEN {
f: G3dShape.Face ¬ shape.faces[n];
IF options.faceNormals THEN DrawVec[f.center, f.normal, f.color];
IF options.
labelPolygons
THEN
G3dDraw.Mark[context, f.center, x, viewport,
IO.PutFR1["%g", IO.int[n]], none];
};
IF options.tapered THEN DrawTaperedPolygon[poly];
ENDLOOP;
};
options.
backFaces = dashed => {
save: DrawType ¬ type;
G3dShape.SetFwdFacingFaces[shape, x];
FOR n:
INT
IN [0..shape.edges.length)
DO
e: Edge ¬ shape.edges[n];
type ¬
IF (e.p0 # -1
AND shape.faces[e.p0].fwdFacing)
OR
(e.p1 # -1
AND shape.faces[e.p1].fwdFacing)
THEN solid ELSE dashed;
Process.CheckForAbort[];
DrawLine[e.v0, e.v1];
ENDLOOP;
type ¬ save;
};
ENDCASE;
IF inverseView = NIL THEN G3dMatrix.ReleaseMatrix[inverse];
G3dMatrix.ReleaseMatrix[x];
};