Clip3dImpl.mesa
Copyright © 1984 by Xerox Corporation. All rights reserved.
Bloomenthal, September 6, 1986 1:58:25 pm PDT
DIRECTORY Clip3d, Matrix3d, Vector3d;
Clip3dImpl: CEDAR PROGRAM
IMPORTS Matrix3d
EXPORTS Clip3d
~ BEGIN
Pair:  TYPE ~ Vector3d.Pair;
Triple: TYPE ~ Vector3d.Triple;
Quad:  TYPE ~ Vector3d.Quad;
Matrix: TYPE ~ Matrix3d.Matrix;
Wec:  TYPE ~ ARRAY[0..5] OF REAL;
Clipping operations on projected 3d points
AWec: PROC [xp: Quad] RETURNS [Wec] ~ {
Divide xp.x by format ratio if non-unity.
RETURN[[xp.w+xp.x, xp.w-xp.x, xp.w+xp.y, xp.w-xp.y, xp.z, xp.w-xp.z]];
};
Alphas: PUBLIC PROC [xp0, xp1: Quad] RETURNS [a0, a1: REAL, off: BOOL] ~ {
wec0: Wec ← AWec[xp0];
wec1: Wec ← AWec[xp1];
a0 ← 0.0;
a1 ← 1.0;
FOR i: NAT IN[0..5] DO
IF wec0[i] < 0.0 THEN {
IF wec1[i] < 0.0 THEN RETURN[a0, a1, TRUE];
a0 ← MAX[a0, wec0[i]/(wec0[i]-wec1[i])];
}
ELSE IF wec1[i] < 0.0 THEN
a1 ← MIN[a1, wec0[i]/(wec0[i]-wec1[i])];
IF a0 > a1 THEN RETURN[a0, a1, TRUE];
ENDLOOP;
RETURN[a0, a1, FALSE];
};
Frustum: PUBLIC PROC [p0, p1: Triple, m: Matrix] RETURNS [c0, c1: Triple, off: BOOL] ~ {
dif: Quad;
a0, a1, w0, w1: REAL;
xp0: Quad ← Matrix3d.TransformH[p0, m];
xp1: Quad ← Matrix3d.TransformH[p1, m];
[a0, a1, off] ← Alphas[xp0, xp1];
IF off THEN RETURN;
dif ← [xp1.x-xp0.x, xp1.y-xp0.y, xp1.z-xp0.z, xp1.w-xp0.w];
w0 ← 1.0/(xp0.w+a0*dif.w);
w1 ← 1.0/(xp0.w+a1*dif.w);
c0 ← [w0*(xp0.x+a0*dif.x), w0*(xp0.y+a0*dif.y), w0*(xp0.z+a0*dif.z)];
c1 ← [w1*(xp0.x+a1*dif.x), w1*(xp0.y+a1*dif.y), w1*(xp0.z+a1*dif.z)];
};
FrustumH: PUBLIC PROC [xp0, xp1: Quad] RETURNS [c0, c1: Triple, off: BOOL] ~ {
dif: Quad;
a0, a1, w0, w1: REAL;
[a0, a1, off] ← Alphas[xp0, xp1];
IF off THEN RETURN;
dif ← [xp1.x-xp0.x, xp1.y-xp0.y, xp1.z-xp0.z, xp1.w-xp0.w];
w0 ← 1.0/(xp0.w+a0*dif.w);
w1 ← 1.0/(xp0.w+a1*dif.w);
c0 ← [w0*(xp0.x+a0*dif.x), w0*(xp0.y+a0*dif.y), w0*(xp0.z+a0*dif.z)];
c1 ← [w1*(xp0.x+a1*dif.x), w1*(xp0.y+a1*dif.y), w1*(xp0.z+a1*dif.z)];
};
FrustumD: PUBLIC PROC [xp0, xp1: Quad] RETURNS [c0, c1: Pair, off: BOOL] ~ {
dif: Quad;
a0, a1, w0, w1: REAL;
[a0, a1, off] ← Alphas[xp0, xp1];
IF off THEN RETURN;
dif ← [xp1.x-xp0.x, xp1.y-xp0.y, , xp1.w-xp0.w];
w0 ← 1.0/(xp0.w+a0*dif.w);
w1 ← 1.0/(xp0.w+a1*dif.w);
c0 ← [w0*(xp0.x+a0*dif.x), w0*(xp0.y+a0*dif.y)];
c1 ← [w1*(xp0.x+a1*dif.x), w1*(xp0.y+a1*dif.y)];
};
NearH: PUBLIC PROC [q0, q1: Quad] RETURNS [c0, c1: Pair, off: BOOL] ~ {
w0, w1: REAL;
a0: REAL ← 0.0;
a1: REAL ← 1.0;
dx: REAL ← q1.x-q0.x;
dy: REAL ← q1.y-q0.y;
dw: REAL ← q1.w-q0.w;
sum0: REAL ← q0.w+q0.z;
sum1: REAL ← q1.w+q1.z;
IF sum0 < 0.0 THEN {
IF sum1 < 0.0 THEN RETURN[c0, c1, TRUE];
a0 ← sum0/(sum0-sum1);
}
ELSE IF sum1 < 0.0 THEN a1 ← sum0/(sum0-sum1);
IF a0 > a1 THEN RETURN[c0, c1, TRUE];
w0 ← IF a0 = 0.0 THEN q0.w ELSE q0.w+a0*dw;
w1 ← IF a1 = 1.0 THEN q1.w ELSE q0.w+a1*dw;
RETURN[[(q0.x+a0*dx)/w0, (q0.y+a0*dy)/w0], [(q0.x+a1*dx)/w1, (q0.y+a1*dy)/w1], FALSE];
};
END.