<> <> <> 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; <> AWec: PROC [xp: Quad] RETURNS [Wec] ~ { <> 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.