Linear3dImpl.mesa
Copyright © 1984 by Xerox Corporation. All rights reserved.
Last Edited by: Crow, February 5, 1986 2:04:01 pm PST
DIRECTORY
RealFns    USING [CosDeg, SinDeg, SqRt],
Vector2    USING [VEC],
Linear3d    USING [Triple, Quad, Xfm3d];
Linear3dImpl: CEDAR PROGRAM
IMPORTS RealFns
EXPORTS Linear3d
~ BEGIN
Basic3dError: PUBLIC SIGNAL [reason: ATOM] = CODE;
Basic Types
Pair: TYPE ~ Vector2.VEC;           -- RECORD [ x, y: REAL];
Triple: TYPE ~ Linear3d.Triple;         -- RECORD [ x, y, z: REAL];
Quad: TYPE ~ Linear3d.Quad;          -- RECORD [ x, y, z, w: REAL];
Xfm3d: TYPE ~ Linear3d.Xfm3d;         -- RECORD [ a, b, c, d: Quad];
IdentityXfm: Xfm3d ~ [[1,0,0,0], [0,1,0,0], [0,0,1,0], [0,0,0,1]];
Utility Procedures
Sqr: PROCEDURE [number: REAL] RETURNS [REAL] ~ INLINE { RETURN[number * number]; };
Procedures for Operations on Triples (3d vectors, or points)
SumTriple: PUBLIC PROCEDURE [t1, t2: Triple] RETURNS [Triple] ~ {
RETURN[ [t1.x + t2.x, t1.y + t2.y, t1.z + t2.z] ]; };
DiffTriple: PUBLIC PROCEDURE [t1, t2: Triple] RETURNS [Triple] ~ {
RETURN[ [t1.x - t2.x, t1.y - t2.y, t1.z - t2.z] ]; };
ScaleTriple: PUBLIC PROCEDURE [t: Triple, s: REAL] RETURNS [Triple] ~ {
RETURN[ [t.x * s, t.y * s, t.z * s] ]; };
Magnitude: PUBLIC PROC[v: Triple] RETURNS[REAL] ~ {
RETURN [ RealFns.SqRt[v.x * v.x + v.y * v.y + v.z * v.z] ];
};
Normalize: PUBLIC PROC[v: Triple] RETURNS[Triple] ~ {
mag: REAL ← RealFns.SqRt[v.x * v.x + v.y * v.y + v.z * v.z];
IF mag <= 0. THEN mag ← 1.;
RETURN [ [v.x/mag, v.y/mag, v.z/mag] ];
};
DotProd: PUBLIC PROC[v1, v2: Triple] RETURNS [REAL] ~ {
RETURN [v1.x * v2.x + v1.y * v2.y + v1.z * v2.z];
};
CrossProd: PUBLIC PROC[v1, v2: Triple] RETURNS [vOut: Triple] ~ {
vOut.x ← v1.y*v2.z - v1.z*v2.y;
vOut.y ← v1.z*v2.x - v1.x*v2.z;
vOut.z ← v1.x*v2.y - v1.y*v2.x;
};
EvalPlane: PUBLIC PROC[plane: Quad, point: Triple] RETURNS [distance: REAL]~ {
distance ← plane.x*point.x + plane.y*point.y + plane.z*point.z + plane.w;
};
Transform3d: PUBLIC PROC[ vtx: Triple, xfm: Xfm3d] RETURNS [t: Triple] ~ {
t.x ← xfm.a.x * vtx.x + xfm.b.x * vtx.y + xfm.c.x * vtx.z + xfm.d.x;
t.y ← xfm.a.y * vtx.x + xfm.b.y * vtx.y + xfm.c.y * vtx.z + xfm.d.y;
t.z ← xfm.a.z * vtx.x + xfm.b.z * vtx.y + xfm.c.z * vtx.z + xfm.d.z;
};
TransformVec3d: PUBLIC PROC[ vtx: Triple, xfm: Xfm3d] RETURNS [t: Triple] ~ {
t.x ← xfm.a.x * vtx.x + xfm.b.x * vtx.y + xfm.c.x * vtx.z;
t.y ← xfm.a.y * vtx.x + xfm.b.y * vtx.y + xfm.c.y * vtx.z;
t.z ← xfm.a.z * vtx.x + xfm.b.z * vtx.y + xfm.c.z * vtx.z;
};
Procedures for Operations on Transformations
ConcatT: PUBLIC PROC[xfm1, xfm2: Xfm3d] RETURNS[xfmOut: Xfm3d] ~{
Multiply 2 4x4 matrices
QuadProd: PROC[q1, q2: Quad] RETURNS [REAL] ~ {
RETURN [q1.x * q2.x + q1.y * q2.y + q1.z * q2.z + q1.w * q2.w]; };
col2x, col2y, col2z, col2w: Quad;
col2x ← [xfm2.a.x, xfm2.b.x, xfm2.c.x, xfm2.d.x];
col2y ← [xfm2.a.y, xfm2.b.y, xfm2.c.y, xfm2.d.y];
col2z ← [xfm2.a.z, xfm2.b.z, xfm2.c.z, xfm2.d.z];
col2w ← [xfm2.a.w, xfm2.b.w, xfm2.c.w, xfm2.d.w];
xfmOut.a.x ← QuadProd[xfm1.a, col2x];  xfmOut.a.y ← QuadProd[xfm1.a, col2y];
xfmOut.a.z ← QuadProd[xfm1.a, col2z];    xfmOut.a.w ← QuadProd[xfm1.a, col2w];
xfmOut.b.x ← QuadProd[xfm1.b, col2x]; xfmOut.b.y ← QuadProd[xfm1.b, col2y];
xfmOut.b.z ← QuadProd[xfm1.b, col2z];    xfmOut.b.w ← QuadProd[xfm1.b, col2w];
xfmOut.c.x ← QuadProd[xfm1.c, col2x];  xfmOut.c.y ← QuadProd[xfm1.c, col2y];
xfmOut.c.z ← QuadProd[xfm1.c, col2z];    xfmOut.c.w ← QuadProd[xfm1.c, col2w];
xfmOut.d.x ← QuadProd[xfm1.d, col2x]; xfmOut.d.y ← QuadProd[xfm1.d, col2y];
xfmOut.d.z ← QuadProd[xfm1.d, col2z];    xfmOut.d.w ← QuadProd[xfm1.d, col2w];
};
Translate3d: PUBLIC PROC[ delta: Triple] RETURNS [xfm: Xfm3d] ~ {
xfm ← IdentityXfm;
xfm.d ← [delta.x, delta.y, delta.z, 1.];
};
Rotate3d: PUBLIC PROC[base, axis: Triple, theta: REAL] RETURNS[Xfm3d] ~ {
xfm, mtx: Xfm3d ← IdentityXfm;
cosTheta: REAL ← RealFns.CosDeg[theta];
sinTheta: REAL ← RealFns.SinDeg[theta];
xfm.d.x ← -base.x; xfm.d.y ← -base.y; xfm.d.z ← -base.z;
axis ← Normalize[axis];
mtx.a.x ← Sqr[axis.x] + (1.0 - Sqr[axis.x]) * cosTheta;
mtx.b.y ← Sqr[axis.y] + (1.0 - Sqr[axis.y]) * cosTheta;
mtx.c.z ← Sqr[axis.z] + (1.0 - Sqr[axis.z]) * cosTheta;
mtx.b.x ← axis.x * axis.y * (1.0 - cosTheta) + axis.z * sinTheta;
mtx.a.y ← axis.x * axis.y * (1.0 - cosTheta) - axis.z * sinTheta;
mtx.c.x ← axis.x * axis.z * (1.0 - cosTheta) - axis.y * sinTheta;
mtx.a.z ← axis.x * axis.z * (1.0 - cosTheta) + axis.y * sinTheta;
mtx.c.y ← axis.y * axis.z * (1.0 - cosTheta) + axis.x * sinTheta;
mtx.b.z ← axis.y * axis.z * (1.0 - cosTheta) - axis.x * sinTheta;
xfm ← ConcatT[xfm, mtx];
mtx ← IdentityXfm;
mtx.d.x ← base.x; mtx.d.y ← base.y; mtx.d.z ← base.z;
xfm ← ConcatT[xfm, mtx];
RETURN[xfm];
};
END.