TnsrTriangleDivide:
PROC[ context:
REF Context, p:
REF Patch, tol:
REAL] ~ {
Divide triangular patch into three subquadrilaterals and send to display
shape: REF ShapeInstance ← NARROW[ GetProp[p.props, $Shape] ];
v0, v1, v2, vCtr, vCtr1, vCtr2, vCtr3: VertexInfo; flat0, flat1, flat2: BOOLEAN;
t: REF TangentTriple ← NARROW[GetProp[p.props, $Tangents] ];
t00, t01, t10, t11, t20, t21, tm0, tm1, tm2: TangentSet;
outPatch: REF PatchSequence ← NEW[PatchSequence[3]];
Find midpoints and midslopes for each side
[v0, t00, t01, flat0] ← CurveDivideTan[
context, p[0], p[1], t[0].et0, t[0].et1,
GetNmlVec[t[0].et0, p[0]], GetNmlVec[t[0].et1, p[1], TRUE], 0.5, tol ];
[v1, t10, t11, flat1] ← CurveDivideTan[
context, p[1], p[2], t[1].et0, t[1].et1,
GetNmlVec[t[1].et0, p[1]], GetNmlVec[t[1].et1, p[2], TRUE], 0.5, tol];
[v2, t20, t21, flat2] ← CurveDivideTan[
context, p[2], p[0], t[2].et0, t[2].et1,
GetNmlVec[t[2].et0, p[2]], GetNmlVec[t[2].et1, p[0], TRUE], 0.5, tol];
IF flat0
AND flat1
AND flat2
AND stopIfStraight
-- all straight? then done
THEN TnsrQuadDisplay[context, p, recurseLimit, tol]; -- display as polygon
Get inner edges from midpoint to opposite vertex curves
tm0.et0 ← GetSlopeVec[ [v0.shade.exn, v0.shade.eyn, v0.shade.ezn], Add[t10.et0, t21.et1] ];
tm0.et0 ← ScaleTangent[ tm0.et0, DiffPosns[p[2].coord, v0.coord, $Eye] ];
tm0.et1 ← GetSlopeVec[ [p[2].shade.exn, p[2].shade.eyn, p[2].shade.ezn], Add[t20.et0, t11.et1]];
tm0.et1 ← ScaleTangent[ tm0.et1, DiffPosns[v0.coord, p[2].coord, $Eye] ];
tm1.et0 ← GetSlopeVec[ [v1.shade.exn, v1.shade.eyn, v1.shade.ezn], Add[t20.et0, t01.et1]];
tm1.et0 ← ScaleTangent[ tm1.et0, DiffPosns[p[0].coord, v1.coord, $Eye] ];
tm1.et1 ← GetSlopeVec[ [p[0].shade.exn, p[0].shade.eyn, p[0].shade.ezn], Add[t00.et0, t21.et1]];
tm1.et1 ← ScaleTangent[ tm1.et1, DiffPosns[v1.coord, p[0].coord, $Eye] ];
tm2.et0 ← GetSlopeVec[ [v2.shade.exn, v2.shade.eyn, v2.shade.ezn], Add[t00.et0, t11.et1]];
tm2.et0 ← ScaleTangent[ tm2.et0, DiffPosns[p[1].coord, v2.coord, $Eye] ];
tm2.et1 ← GetSlopeVec[ [p[1].shade.exn, p[1].shade.eyn, p[1].shade.ezn], Add[t10.et0, t01.et1]];
tm2.et1 ← ScaleTangent[ tm2.et1, DiffPosns[v2.coord, p[1].coord, $Eye] ];
Split inner edges at 1/3 point and average for ctr. point
[vCtr1, tm0, , ] ← CurveDivideTan[
context, v0, p[2], tm0.et0, tm0.et1,
GetNmlVec[tm0.et0, v0], GetNmlVec[tm0.et1, p[2], TRUE], 1.0/3.0, tol ];
[vCtr2, tm1, , ] ← CurveDivideTan[
context, v1, p[0], tm1.et0, tm1.et1,
GetNmlVec[tm1.et0, v1], GetNmlVec[tm1.et1, p[0], TRUE], 1.0/3.0, tol ];
[vCtr3, tm2, , ] ← CurveDivideTan[
context, v2, p[1], tm2.et0, tm2.et1,
GetNmlVec[tm2.et0, v2], GetNmlVec[tm2.et1, p[1], TRUE], 1.0/3.0, tol ];
[[vCtr.coord.ex, vCtr.coord.ey, vCtr.coord.ez]] ← Div[
-- average positions
Add[
[vCtr1.coord.ex, vCtr1.coord.ey, vCtr1.coord.ez],
Add[
[vCtr2.coord.ex, vCtr2.coord.ey, vCtr2.coord.ez],
[vCtr3.coord.ex, vCtr3.coord.ey, vCtr3.coord.ez]
]
],
3.0
];
[[vCtr.shade.exn, vCtr.shade.eyn, vCtr.shade.ezn]] ← Div[
-- average normals
Add[
[vCtr1.shade.exn, vCtr1.shade.eyn, vCtr1.shade.ezn],
Add[
[vCtr2.shade.exn, vCtr2.shade.eyn, vCtr2.shade.ezn],
[vCtr3.shade.exn, vCtr3.shade.eyn, vCtr3.shade.ezn]
]
],
3.0
];
FOR i:
NAT
IN [0..3)
DO
outPatch[i] ← ShapeUtilities.GetPatch[4]; -- 4 point patch, released by display action
outPatch[i].type ← p.type;
outPatch[i].oneSided ← p.oneSided;
outPatch[i].nVtces ← 4;
outPatch[i].clipState ← p.clipState;
outPatch[i].dir ← p.dir;
outPatch[i].props ← p.props;
ENDLOOP;
{
OPEN v0.coord; clip ← ShapeUtilities.GetClipCodeForPt[context, [ ex, ey, ez] ];
IF clip = NoneOut
THEN [ [sx, sy, sz] ] ← ShapeUtilities.XfmPtToDisplay[ context, [ex, ey, ez], shape ]; };
{
OPEN v1.coord; clip ← ShapeUtilities.GetClipCodeForPt[context, [ ex, ey, ez] ];
IF clip = NoneOut
THEN [ [sx, sy, sz] ] ← ShapeUtilities.XfmPtToDisplay[ context, [ex, ey, ez], shape ]; };
{
OPEN v2.coord; clip ← ShapeUtilities.GetClipCodeForPt[context, [ ex, ey, ez] ];
IF clip = NoneOut
THEN [ [sx, sy, sz] ] ← ShapeUtilities.XfmPtToDisplay[ context, [ex, ey, ez], shape ]; };
{
OPEN vCtr.coord; clip ← ShapeUtilities.GetClipCodeForPt[context, [ ex, ey, ez] ];
IF clip = NoneOut
THEN [ [sx, sy, sz] ] ← ShapeUtilities.XfmPtToDisplay[ context, [ex, ey, ez], shape ]; };
outPatch[0][0] ← p[0]; outPatch[0][1] ← v0; outPatch[0][2] ← vCtr; outPatch[0][3] ← v2;
outPatch[1][0] ← p[1]; outPatch[1][1] ← v1; outPatch[1][2] ← vCtr; outPatch[1][3] ← v0;
outPatch[2][0] ← p[2]; outPatch[2][1] ← v2; outPatch[2][2] ← vCtr; outPatch[2][3] ← v1;
outPatch[0].props ← PutPropSafely[ outPatch[0].props, $Tangents,
NEW[TangentQuad ←
[t00, tm0, [tm2.t1, tm2.et1, tm2.t0, tm2.et0], t21] ] ];
outPatch[1].props ← PutPropSafely[ outPatch[1].props, $Tangents,
NEW[TangentQuad ←
[t10, tm1, [tm0.t1, tm0.et1, tm0.t0, tm0.et0], t01] ] ];
outPatch[2].props ← PutPropSafely[ outPatch[2].props, $Tangents,
NEW[TangentQuad ←
[t20, tm2, [tm1.t1, tm1.et1, tm1.t0, tm1.et0], t11] ] ];
FOR i: NAT IN [0..3) DO ShapeUtilities.GetPatchClipState[ outPatch[i] ]; ENDLOOP; --bad!!
outPatch.length ← 3;
FOR i: NAT IN [0..3) DO TnsrQuadDisplay[ context, outPatch[i], 0, tol ]; ENDLOOP;
};
SubdivideTnsrQuad:
PROC[context:
REF Context, p:
REF Patch, level:
NAT, tol:
REAL]
RETURNS[
REF PatchSequence] ~ {
Divide quadrangular patch into four subquadrangles
shape: REF ShapeInstance ← NARROW[ GetProp[p.props, $Shape] ];
v0, v1, v2, v3, vCtr, vCtr2: VertexInfo; flat0, flat1, flat2, flat3: BOOLEAN;
t: REF TangentQuad ← NARROW[GetProp[p.props, $Tangents] ];
t00, t01, t10, t11, t20, t21, t30, t31, tm0, tm1, tm2, tm3: TangentSet;
outPatch: REF PatchSequence ← NEW[PatchSequence[4]];
Find midpoints and midslopes for each side
[v0, t00, t01, flat0] ← CurveDivideTan[
context, p[0], p[1], t[0].et0, t[0].et1,
GetNmlVec[t[0].et0, p[0]], GetNmlVec[t[0].et1, p[1], TRUE], 0.5, tol ];
[v1, t10, t11, flat1] ← CurveDivideTan[
context, p[1], p[2], t[1].et0, t[1].et1,
GetNmlVec[t[1].et0, p[1]], GetNmlVec[t[1].et1, p[2], TRUE], 0.5, tol];
[v2, t20, t21, flat2] ← CurveDivideTan[
context, p[2], p[3], t[2].et0, t[2].et1,
GetNmlVec[t[2].et0, p[2]], GetNmlVec[t[2].et1, p[3], TRUE], 0.5, tol];
[v3, t30, t31, flat3] ← CurveDivideTan[
context, p[3], p[0], t[3].et0, t[3].et1,
GetNmlVec[t[3].et0, p[3]], GetNmlVec[t[3].et1, p[0], TRUE], 0.5, tol];
IF flat0
AND flat1
AND flat2
AND flat3
AND stopIfStraight
-- all straight? then done
THEN RETURN[NIL];
Get inner edge endpoint tangents from opposite midpoints
- first project direction given by endpoint cross-tangents on plane given by normal
- Then scale direction by distance to opposite midpoint
tm0.et0 ← GetSlopeVec[ [v0.shade.exn, v0.shade.eyn, v0.shade.ezn], Add[t10.et0, t31.et1] ];
tm0.et0 ← ScaleTangent[ tm0.et0, DiffPosns[v2.coord, v0.coord, $Eye] ];
tm0.et1 ← GetSlopeVec[ [v2.shade.exn, v2.shade.eyn, v2.shade.ezn], Add[t11.et1, t30.et0] ];
tm0.et1 ← ScaleTangent[ tm0.et1, DiffPosns[v0.coord, v2.coord, $Eye] ];
tm1.et0 ← GetSlopeVec[ [v1.shade.exn, v1.shade.eyn, v1.shade.ezn], Add[t20.et0, t01.et1] ];
tm1.et0 ← ScaleTangent[ tm1.et0, DiffPosns[v3.coord, v1.coord, $Eye] ];
tm1.et1 ← GetSlopeVec[ [v3.shade.exn, v3.shade.eyn, v3.shade.ezn], Add[t21.et1, t00.et0] ];
tm1.et1 ← ScaleTangent[ tm1.et1, DiffPosns[v1.coord, v3.coord, $Eye] ];
tm0.et0 ← GetSlopeVec[ [v0.shade.exn, v0.shade.eyn, v0.shade.ezn],
DiffPosns[v2.coord, v0.coord, $Eye] ];
tm0.et1 ← GetSlopeVec[ [v2.shade.exn, v2.shade.eyn, v2.shade.ezn],
DiffPosns[v0.coord, v2.coord, $Eye] ];
tm1.et0 ← GetSlopeVec[ [v1.shade.exn, v1.shade.eyn, v1.shade.ezn],
DiffPosns[v3.coord, v1.coord, $Eye] ];
tm1.et1 ← GetSlopeVec[ [v3.shade.exn, v3.shade.eyn, v3.shade.ezn],
DiffPosns[v1.coord, v3.coord, $Eye] ];
Get center point, normal and cross tangents
[vCtr, tm0, tm2, ] ← CurveDivideTan[
context, v0, v2, tm0.et0, tm0.et1,
GetNmlVec[tm0.et0, v0], GetNmlVec[tm0.et1, v2, TRUE], 0.5, tol ];
[vCtr2, tm1, tm3, ] ← CurveDivideTan[
context, v1, v3, tm1.et0, tm1.et1,
GetNmlVec[tm1.et0, v1], GetNmlVec[tm1.et1, v3, TRUE], 0.5, tol ];
[[vCtr.coord.ex, vCtr.coord.ey, vCtr.coord.ez]] ← Div[
-- average
Add[
[vCtr.coord.ex, vCtr.coord.ey, vCtr.coord.ez],
[vCtr2.coord.ex, vCtr2.coord.ey, vCtr2.coord.ez]
],
2
];
[[vCtr.shade.exn, vCtr.shade.eyn, vCtr.shade.ezn]] ← Nmlize[ Cross[ tm2.et0 , tm3.et0 ] ];
FOR i:
NAT
IN [0..4)
DO
outPatch[i] ← ShapeUtilities.GetPatch[4]; -- 4 point patch, released by display action
outPatch[i].type ← p.type;
outPatch[i].oneSided ← p.oneSided;
outPatch[i].nVtces ← 4;
outPatch[i].clipState ← p.clipState;
outPatch[i].dir ← p.dir;
outPatch[i].props ← p.props;
ENDLOOP;
{
OPEN v0.coord; clip ← ShapeUtilities.GetClipCodeForPt[context, [ ex, ey, ez] ];
IF clip = NoneOut
THEN [ [sx, sy, sz] ] ← ShapeUtilities.XfmPtToDisplay[ context, [ex, ey, ez], shape ]; };
{
OPEN v1.coord; clip ← ShapeUtilities.GetClipCodeForPt[context, [ ex, ey, ez] ];
IF clip = NoneOut
THEN [ [sx, sy, sz] ] ← ShapeUtilities.XfmPtToDisplay[ context, [ex, ey, ez], shape ]; };
{
OPEN v2.coord; clip ← ShapeUtilities.GetClipCodeForPt[context, [ ex, ey, ez] ];
IF clip = NoneOut
THEN [ [sx, sy, sz] ] ← ShapeUtilities.XfmPtToDisplay[ context, [ex, ey, ez], shape ]; };
{
OPEN v3.coord; clip ← ShapeUtilities.GetClipCodeForPt[context, [ ex, ey, ez] ];
IF clip = NoneOut
THEN [ [sx, sy, sz] ] ← ShapeUtilities.XfmPtToDisplay[ context, [ex, ey, ez], shape ]; };
{
OPEN vCtr.coord; clip ← ShapeUtilities.GetClipCodeForPt[context, [ ex, ey, ez] ];
IF clip = NoneOut
THEN [ [sx, sy, sz] ] ← ShapeUtilities.XfmPtToDisplay[ context, [ex, ey, ez], shape ]; };
outPatch[0][0] ← p[0]; outPatch[0][1] ← v0; outPatch[0][2] ← vCtr; outPatch[0][3] ← v3;
outPatch[1][0] ← p[1]; outPatch[1][1] ← v1; outPatch[1][2] ← vCtr; outPatch[1][3] ← v0;
outPatch[2][0] ← p[2]; outPatch[2][1] ← v2; outPatch[2][2] ← vCtr; outPatch[2][3] ← v1;
outPatch[3][0] ← p[3]; outPatch[3][1] ← v3; outPatch[3][2] ← vCtr; outPatch[3][3] ← v2;
IF t #
NIL
THEN {
outPatch[0].props ← PutPropSafely[ outPatch[0].props, $Tangents,
NEW[TangentQuad ←
[t00, tm0, tm3, t31] ] ];
outPatch[1].props ← PutPropSafely[ outPatch[1].props, $Tangents,
NEW[TangentQuad ←
[t10, tm1, [tm0.t1, tm0.et1, tm0.t0, tm0.et0], t01] ] ];
outPatch[2].props ← PutPropSafely[ outPatch[2].props, $Tangents,
NEW[TangentQuad ←
[t20, [tm2.t1, tm2.et1, tm2.t0, tm2.et0], [tm1.t1, tm1.et1, tm1.t0, tm1.et0], t11] ] ];
outPatch[3].props ← PutPropSafely[ outPatch[3].props, $Tangents,
NEW[TangentQuad ←
[t30, [tm3.t1, tm3.et1, tm3.t0, tm3.et0], tm2, t21] ] ];
};
FOR i: NAT IN [0..4) DO ShapeUtilities.GetPatchClipState[ outPatch[i] ]; ENDLOOP; --bad!!
outPatch.length ← 4;
RETURN[ outPatch ]; -- return four sub-patches
};