<<>> <> <> <> DIRECTORY G3dBasic, G3dClip, G3dMatrix; G3dClipImpl: CEDAR PROGRAM IMPORTS G3dMatrix EXPORTS G3dClip ~ BEGIN ClippedPair: TYPE ~ G3dClip.ClippedPair; ClippedTriple: TYPE ~ G3dClip.ClippedTriple; Matrix: TYPE ~ G3dClip.Matrix; Quad: TYPE ~ G3dClip.Quad; Triple: TYPE ~ G3dClip.Triple; Wec: TYPE ~ ARRAY[0..6) 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..6) 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 [ct: ClippedTriple] ~ { dif: Quad; a0, a1, w0, w1: REAL; xp0: Quad ¬ G3dMatrix.TransformH[p0, m]; xp1: Quad ¬ G3dMatrix.TransformH[p1, m]; [a0, a1, ct.off] ¬ Alphas[xp0, xp1]; IF ct.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); ct.c0 ¬ [w0*(xp0.x+a0*dif.x), w0*(xp0.y+a0*dif.y), w0*(xp0.z+a0*dif.z)]; ct.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 [ct: ClippedTriple] ~ { dif: Quad; a0, a1, w0, w1: REAL; [a0, a1, ct.off] ¬ Alphas[xp0, xp1]; IF ct.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); ct.c0 ¬ [w0*(xp0.x+a0*dif.x), w0*(xp0.y+a0*dif.y), w0*(xp0.z+a0*dif.z)]; ct.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 [cp: ClippedPair] ~ { dif: Quad; a0, a1, w0, w1: REAL; [a0, a1, cp.off] ¬ Alphas[xp0, xp1]; IF cp.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); cp.c0 ¬ [w0*(xp0.x+a0*dif.x), w0*(xp0.y+a0*dif.y)]; cp.c1 ¬ [w1*(xp0.x+a1*dif.x), w1*(xp0.y+a1*dif.y)]; }; NearH: PUBLIC PROC [q0, q1: Quad] RETURNS [cp: ClippedPair] ~ { 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[[[0, 0], [0, 0], TRUE]]; a0 ¬ sum0/(sum0-sum1); } ELSE IF sum1 < 0.0 THEN a1 ¬ sum0/(sum0-sum1); IF a0 > a1 THEN RETURN[[[0, 0], [0, 0], 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; cp.c0 ¬ IF w0 = 0 THEN [q0.x+a0*dx, q0.y+a0*dy] ELSE [(q0.x+a0*dx)/w0, (q0.y+a0*dy)/w0]; cp.c1 ¬ IF w1 = 0 THEN [q0.x+a1*dx, q0.y+a1*dy] ELSE [(q0.x+a1*dx)/w1, (q0.y+a1*dy)/w1]; cp.off ¬ FALSE; }; <<>> END.