/* A word about the 3D library. Even though this library supports three dimensions, the matrices are 4x4 for the following reason. With normal 3 dimensional vectors, translation is an ADDITION, and rotation is a MULTIPLICATION. A vector {x,y,z} is represented as a 4-tuple {x,y,z,1}. It is then possible to define a 4x4 matrix such that multiplying the vector by the matrix translates the vector. This allows combinations of translation and rotation to be obtained in a single matrix by multiplying a translation matrix and a rotation matrix together. Note that in the code, vectors have three components; since the fourth component is always 1, that value is not included in the vector variable to save space, but the routines make use of the fourth component (see vec_mult()). Similarly, the fourth column of EVERY matrix is always 0 0 0 1 but currently the C version of a matrix includes this even though it could be left out of the data structure and assumed in the routines. Vectors are ROW vectors, and are always multiplied with matrices FROM THE LEFT (e.g. vector*matrix). Also note the order of indices of a matrix is matrix[row][column], and in usual C fashion, numbering starts with 0. TRANSLATION MATRIX = 1 0 0 0 0 1 0 0 0 0 1 0 Tx Ty Tz 1 SCALE MATRIX = Sx 0 0 0 0 Sy 0 0 0 0 Sz 0 0 0 0 1 Rotation about x axis i degrees: ROTX(i) = 1 0 0 0 0 cosi sini 0 0 -sini cosi 0 0 0 0 1 Rotation about y axis i degrees: ROTY(i) = cosi 0 -sini 0 0 1 0 0 sini 0 cosi 0 0 0 0 1 Rotation about z axis i degrees: ROTZ(i) = cosi sini 0 0 -sini cosi 0 0 0 0 1 0 0 0 0 1 -- Tim Wegner April 22, 1989 */ #include /* see Fractint.c for a description of the "include" hierarchy */ #include "port.h" #include "prototyp.h" /* initialize a matrix and set to identity matrix (all 0's, 1's on diagonal) */ void identity(MATRIX m) { int i,j; for(i=0;i FLT_MAX) return(-1); vlength = sqrt(vlength); if(vlength < FLT_MIN) return(-1); v[0] /= vlength; v[1] /= vlength; v[2] /= vlength; return(0); } /* multiply source vector s by matrix m, result in target t */ /* used to apply transformations to a vector */ int vmult(VECTOR s, MATRIX m, VECTOR t) { VECTOR tmp; int i,j; for(j=0;j= 0.0) { v[0] = bad_value; /* clipping will catch these values */ v[1] = bad_value; /* so they won't plot values BEHIND viewer */ v[2] = bad_value; return(-1); } v[0] = (v[0]*view[2] - view[0]*v[2])/denom; v[1] = (v[1]*view[2] - view[1]*v[2])/denom; /* calculation of z if needed later */ /* v[2] = v[2]/denom;*/ return(0); } /* long version of vmult and perspective combined for speed */ longvmultpersp(LVECTOR s, LMATRIX m, LVECTOR t0, LVECTOR t, LVECTOR lview, int bitshift) { /* s: source vector */ /* m: transformation matrix */ /* t0: after transformation, before persp */ /* t: target vector */ /* lview: perspective viewer coordinates */ /* bitshift: fixed point conversion bitshift */ LVECTOR tmp; int i,j, k; overflow = 0; k = CMAX-1; /* shorten the math if non-perspective and non-illum */ if (lview[2] == 0 && t0[0] == 0) k--; for(j=0;j= 0) /* bail out if point is "behind" us */ { t[0] = bad_value; t[0] = t[0]<= 0) /* bail out if point is "behind" us */ { lv[0] = bad_value; lv[0] = lv[0]<