home *** CD-ROM | disk | FTP | other *** search
- /**********************************************************************/
- /* geo.c : Geometric operations */
- /* */
- /* Parts from "Illumination and Color in Computer Graphics", by Roy */
- /* Hall. */
- /* Parts also adapted from Graphics Gems I (ed. James Arvo), 1989. */
- /* */
- /* Copyright (C) 1992, Bernard Kwok */
- /* All rights reserved. */
- /* Revision 1.0 */
- /* May, 1992 */
- /**********************************************************************/
- #include <stdio.h>
- #include <math.h>
- #include "misc.h"
- #include "geo.h"
-
- /*====================================================================*/
- /* 2D operations */
- /*====================================================================*/
-
- /**********************************************************************/
- /* 2D Dot product */
- /**********************************************************************/
- double vdot2(v)
- Vector2 *v;
- { return((v->x * v->x) + (v->y * v->y)); }
-
- /**********************************************************************/
- /* 2D length of vector */
- /**********************************************************************/
- double vlen2(a)
- Vector2 *a;
- { return(sqrt(vdot2(a))); }
-
- /**********************************************************************/
- /* 2D negate vector */
- /**********************************************************************/
- Vector2 *vnegate2(v)
- Vector2 *v;
- { v->x = -v->x; v->y = -v->y; return(v); }
-
- /**********************************************************************/
- /* 2D norm */
- /**********************************************************************/
- Vector2 *vnorm2(v)
- Vector2 *v;
- {
- double len;
-
- if ((len=vlen2(v)) == 0.0)
- fprintf(stderr,"Cannot normalize, 2d length is zero\n");
- else { v->x /= len; v->y /= len; }
- return(v);
- }
-
- /**********************************************************************/
- /* 2D scale vector */
- /**********************************************************************/
- Vector2 *vscale2(v, newlen)
- Vector2 *v;
- double newlen;
- {
- double len;
-
- if ((len=vlen2(v)) == 0.0)
- fprintf(stderr,"Cannot scale, 2d length is zero\n");
- else { v->x *= newlen/len; v->y *= newlen/len; }
- return(v);
- }
-
- /**********************************************************************/
- /* 2d vector add */
- /**********************************************************************/
- Vector2 *vadd2(a, b, c)
- Vector2 *a, *b, *c;
- {
- c->x = a->x + b->x; c->y = a->y + b->y;
- return(c);
- }
-
- /**********************************************************************/
- /* 2d vector subtract */
- /**********************************************************************/
- Vector2 *vsub2(a, b, c)
- Vector2 *a, *b, *c;
- {
- c->x = a->x - b->x; c->y = a->y - b->y;
- return(c);
- }
-
- /**********************************************************************/
- /* 2d linearly interpolate between vectors by amount alpha */
- /**********************************************************************/
- Vector2 *vinterp2(lo, hi, alpha, result)
- Vector2 *lo, *hi, *result;
- double alpha;
- {
- result->x = LERP(alpha, lo->x, hi->x);
- result->y = LERP(alpha, lo->y, hi->y);
- return(result);
- }
-
- /**********************************************************************/
- /* 2d linear combination */
- /**********************************************************************/
- Vector2 *vcomb2(v1, v2, result, a, b)
- Vector2 *v1, *v2, *result;
- double a, b;
- {
- result->x = (a * v1->x) + (b * v2->x);
- result->y = (a * v1->y) + (b * v2->y);
- return(result);
- }
-
- /**********************************************************************/
- /* 2d multiply two vectors together component-wise */
- /**********************************************************************/
- Vector2 *vmult2(a, b, result)
- Vector2 *a, *b, *result;
- {
- result->x = a->x * b->x; result->y = a->y * b->y;
- return(result);
- }
-
- /**********************************************************************/
- /* 2D distance between two points */
- /**********************************************************************/
- double vdist2(a, b)
- point2 *a, *b;
- {
- double dx = a->x - b->x;
- double dy = a->y - b->y;
- return(sqrt((dx*dx)+(dy*dy)));
- }
-
- /**********************************************************************/
- /* 2d perpendicular vector to the input vector a */
- /**********************************************************************/
- Vector2 *vperp2(a, ap)
- Vector2 *a, *ap;
- {
- ap->x = -a->y; ap->y = a->x;
- return(ap);
- }
-
- /**********************************************************************/
- /* create, initialize, and return a new vector */
- /**********************************************************************/
- Vector2 *vnew2(x, y)
- double x, y;
- {
- Vector2 *v = NEWTYPE(Vector2);
- v->x = x; v->y = y;
- return(v);
- }
-
- /**********************************************************************/
- /* create, initialize, and return a duplicate vector */
- /**********************************************************************/
- Vector2 *vdup2(a)
- Vector2 *a;
- {
- Vector2 *v = NEWTYPE(Vector2);
- v->x = a->x; v->y = a->y;
- return(v);
- }
-
- /**********************************************************************/
- /* multiply a point by a matrix and return the transformed point */
- /**********************************************************************/
- point2 *vtransform2(p, m)
- point2 *p;
- Matrix3 *m;
- {
- double x,y;
- double w;
-
- x = (p->x * m->element[0][0]) +
- (p->y * m->element[1][0]) + m->element[2][0];
- y = (p->x * m->element[0][1]) +
- (p->y * m->element[1][1]) + m->element[2][1];
- w = (p->x * m->element[0][2]) +
- (p->y * m->element[1][2]) + m->element[2][2];
- p->x = x; p->y = y;
- if (w != 0.0) { p->x /= w; p->y /= w; }
- else printf("V2MulpointByMatrix : point at infinity\n");
- return(p);
- }
-
- /**********************************************************************/
- /* multiply together matrices c = ab */
- /* note that c must not point to either of the input matrices */
- /**********************************************************************/
- Matrix3 *multmatrix2(a, b, c)
- Matrix3 *a, *b, *c;
- {
- int i,j,k;
-
- for (i=0; i<3; i++) {
- for (j=0; j<3; j++) {
- c->element[i][j] = 0;
- for (k=0; k<3; k++) c->element[i][j] +=
- a->element[i][k] * b->element[k][j];
- }
- }
- return(c);
- }
-
- /*====================================================================*/
- /* 3D geometric routines */
- /*====================================================================*/
- /**********************************************************************/
- /* Two vertices are within some tolerance distance of each other */
- /**********************************************************************/
- int vsame(v1, v2, tolerance)
- Vector *v1, *v2;
- double tolerance;
- {
- extern double vdist();
-
- if (_ABS(vdist(v1,v2)) < tolerance)
- return(1);
- else
- return(0);
- }
-
- /**********************************************************************/
- /* find dot product of vectors v0 and v1 */
- /**********************************************************************/
- double dot(v0,v1)
- Vector *v0, *v1;
- { return (v0->x * v1->x) + (v0->y * v1->y) + (v0->z * v1->z); }
-
- /**********************************************************************/
- /* Find cross product of vectors v0 and v1 */
- /**********************************************************************/
- Vector cross(v0, v1)
- Vector *v0, *v1;
- {
- Vector v2;
-
- v2.x = (v0->y * v1->z) - (v0->z * v1->y);
- v2.y = (v0->z * v1->x) - (v0->x * v1->z);
- v2.z = (v0->x * v1->y) - (v0->y * v1->x);
- return v2;
- }
-
- /**********************************************************************/
- /* Multiply a vector by a scalar */
- /**********************************************************************/
- Vector *vscalar(s, v)
- double s;
- Vector *v;
- {
- Vector v1;
-
- v1.x = s * v->x; v1.y = s * v->y; v1.z = s * v->z;
- return &v1;
- }
-
- /**********************************************************************/
- /* Normalized vector v0 and return length, return negative length if */
- /* close to zero, or less than zero */
- /**********************************************************************/
- double norm(v0)
- Vector *v0;
- {
- double len;
-
- if ((len = dot(v0,v0)) <= 0.0) return FALSE;
- len = sqrt((double)len);
- if (len < MIN_VECTOR_LENGTH) return FALSE;
- v0->x = v0->x / len;
- v0->y = v0->y / len;
- v0->z = v0->z / len;
- return TRUE;
- }
-
- /**********************************************************************/
- /* Create vector from 2 points, and return length */
- /**********************************************************************/
- double geo_line(p0, p1, v)
- point3 *p0, *p1;
- line *v;
- {
- v->start = *p0;
- v->dir.x = p1->x - p0->x;
- v->dir.y = p1->y - p0->y;
- v->dir.z = p1->z - p0->z;
- return norm(&v->dir);
- }
-
- /**********************************************************************/
- /* Add 2 vectors */
- /**********************************************************************/
- Vector *vadd(v0, v1)
- Vector *v0, *v1;
- {
- Vector add;
-
- add.x = v0->x + v1->x;
- add.y = v0->y + v1->y;
- add.z = v0->z + v1->z;
- return &add;
- }
-
- /**********************************************************************/
- /* Subtract vector v1 from v0 */
- /**********************************************************************/
- Vector *vsub(v0, v1)
- Vector *v0, *v1;
- {
- Vector sub;
-
- sub.x = v0->x - v1->x;
- sub.y = v0->y - v1->y;
- sub.z = v0->z - v1->z;
- return ⊂
- }
-
- /**********************************************************************/
- /* Vector negation */
- /**********************************************************************/
- Vector *vnegate(v)
- Vector *v;
- {
- v->x = -v->x; v->y = -v->y; v->z = -v->z;
- return(v);
- }
-
- /**********************************************************************/
- /* multiply two vectors together component-wise and return the result */
- /**********************************************************************/
- Vector *vmult(v1, v2, result)
- Vector *v1, *v2, *result;
- {
- result->x = v1->x * v2->x;
- result->y = v1->y * v2->y;
- result->z = v1->z * v2->z;
- return(result);
- }
-
- /**********************************************************************/
- /* return the distance between two points */
- /**********************************************************************/
- double vdist(a, b)
- Vector *a, *b;
- {
- double dx, dy, dz;
-
- dx = a->x - b->x; dy = a->y - b->y; dz = a->z - b->z;
- return(sqrt((dx*dx)+(dy*dy)+(dz*dz)));
- }
-
- /**********************************************************************/
- /* Mid-point between 2 vectors */
- /**********************************************************************/
- Vector *vmiddle(v1,v2)
- Vector *v1, *v2;
- {
- Vector vmid;
-
- vmid.x = (v1->x + v2->x) / 2.0;
- vmid.y = (v1->y + v2->y) / 2.0;
- vmid.z = (v1->z + v2->z) / 2.0;
- return(&vmid);
- }
-
- /**********************************************************************/
- /* Length of a vector
- /**********************************************************************/
- double vlen(v)
- Vector *v;
- {
- double v_dot_v;
- double len;
-
- v_dot_v = dot(v,v);
- len = sqrt(v_dot_v);
- return(len);
- }
-
- /**********************************************************************/
- /* Vector scale */
- /**********************************************************************/
- Vector *vscale(v, newlen)
- Vector *v;
- double newlen;
- {
- double len = vlen(v);
- if (len != 0.0) {
- v->x *= newlen/len; v->y *= newlen/len; v->z *= newlen/len;
- }
- return(v);
- }
-
- /**********************************************************************/
- /* Vector interpolation by alpha */
- /**********************************************************************/
- Vector *vinterp(lo, hi, alpha, result)
- Vector *lo, *hi, *result;
- double alpha;
- {
- result->x = LERP(alpha, lo->x, hi->x);
- result->y = LERP(alpha, lo->y, hi->y);
- result->z = LERP(alpha, lo->z, hi->z);
- return(result);
- }
-
- /**********************************************************************/
- /* Vector linear combination: a*v0 + b*v1 */
- /**********************************************************************/
- Vector *vcomb(v0,v1,a,b)
- Vector *v0, *v1;
- double a,b;
- {
- static Vector comb;
-
- comb.x = a * v0->x + b * v1->x;
- comb.y = a * v0->y + b * v1->y;
- comb.z = a * v0->z + b * v1->z;
- return &comb;
- }
-
- /**********************************************************************/
- /* New vector */
- /**********************************************************************/
- Vector *vnew(x, y, z)
- double x, y, z;
- {
- Vector *v = NEWTYPE(Vector);
- v->x = x; v->y = y; v->z = z;
- return(v);
- }
-
- /**********************************************************************/
- /* New duplicate vector */
- /**********************************************************************/
- Vector *vdup(d)
- Vector *d;
- {
- Vector *v = NEWTYPE(Vector);
- v->x = d->x; v->y = d->y; v->z = d->z;
- return(v);
- }
-
- /**********************************************************************/
- /* Ideal reflection vector */
- /**********************************************************************/
- Vector *reflection(v,n)
- Vector *v, *n;
- {
- double n_dot_v;
- static Vector rfl;
-
- n_dot_v = dot(n,v);
- rfl.x = (2.0 * n_dot_v * n->x) - v->x;
- rfl.y = (2.0 * n_dot_v * n->y) - v->y;
- rfl.z = (2.0 * n_dot_v * n->z) - v->z;
- return &rfl;
- }
-
- /**********************************************************************/
- /* Ideal refraction vector (simple) */
- /**********************************************************************/
- Vector *refraction(v,n,ni,nt)
- Vector *v, *n;
- double ni, nt;
- {
- static Vector t;
- Vector sin_t, cos_v;
- double len_sin_t, n_mult, n_dot_v, n_dot_t;
- if ((n_dot_v = dot(n,v)) > 0.0) n_mult = ni / nt;
- else n_mult = nt / ni;
- cos_v.x = n_dot_v * n->x;
- cos_v.y = n_dot_v * n->y;
- cos_v.z = n_dot_v * n->z;
- sin_t.x = (n_mult) * (cos_v.x = v->x);
- sin_t.y = (n_mult) * (cos_v.y = v->y);
- sin_t.z = (n_mult) * (cos_v.z = v->z);
- if ((len_sin_t = dot(&sin_t, &sin_t)) > 1.0)
- return NULL; /* internal reflection */
- n_dot_t = sqrt(1.0 - len_sin_t);
- if (n_dot_v < 0.0) n_dot_t = -n_dot_t;
- t.x = sin_t.x - (n->x * n_dot_t);
- t.y = sin_t.y - (n->y * n_dot_t);
- t.z = sin_t.z - (n->z * n_dot_t);
- return &t;
- }
-
- /**********************************************************************/
- /* Halfway vector */
- /**********************************************************************/
- Vector *geo_h(l,v)
- Vector *l, *v;
- {
- static Vector h;
- h.x = l->x + v->x;
- h.y = l->y + v->y;
- h.z = l->z + v->z;
- if (!norm(&h)) return NULL;
- return &h;
- }
-
- /**********************************************************************/
- /* Halfway vector (refraction) */
- /**********************************************************************/
- Vector *geo_ht(l,t,ni,nt)
- Vector *l, *t;
- double ni, nt;
- {
- float l_dot_t;
- float divisor;
- static Vector ht;
-
- l_dot_t = -(dot(l,t));
- if (ni == nt) {
- if (l_dot_t == 1.0) return l;
- else return NULL;
- }
- if (ni < nt) {
- if (l_dot_t < ni/nt) return NULL;
- divisor = (nt / ni) - 1.0;
- ht.x = -(((l->x + t->x) / divisor) + t->x);
- ht.y = -(((l->y + t->y) / divisor) + t->y);
- ht.z = -(((l->z + t->z) / divisor) + t->z);
- } else {
- if (l_dot_t < nt/ni) return NULL;
- divisor = (ni / nt) - 1.0;
- ht.x = ((l->x + t->x) / divisor) + l->x;
- ht.y = ((l->y + t->y) / divisor) + l->y;
- ht.z = ((l->z + t->z) / divisor) + l->z;
- }
- (void) norm(&ht);
- return &ht;
- }
-
- /* from optik originally */
- /**********************************************************************/
- /* This function is similar to pow() but works right only for */
- /* positive integer b (but a lot faster) */
- /**********************************************************************/
- double Power(a,b)
- double a,b;
- {
- register int power;
- double result;
-
- result= 1.0;
- power= (int) b;
- while(power > 0) {
- if(power & 1)
- result *= a;
- a *= a;
- power >>= 1;
- }
- return(result);
- }
-
- /**********************************************************************/
- /* Calculate normal for a polygon from its vertices */
- /**********************************************************************/
- Vector polynorm(vert,size)
- register Vector vert[];
- register int size;
- {
- Vector n;
- register int i,j;
-
- n.x = n.y = n.z= 0.0;
- for(i=0;i<size;i++) {
- j= (i+1)%size;
- n.x += (vert[i].y-vert[j].y) * (vert[i].z+vert[j].z);
- n.y += (vert[i].z-vert[j].z) * (vert[i].x+vert[j].x);
- n.z += (vert[i].x-vert[j].x) * (vert[i].y+vert[j].y);
- }
- if(norm(&(n)) < 0.) {
- /* if(Option.debug)
- printf("Sorry, a normal cannot be computed for one of the polygons.\n");
- */
- n.x = n.y = 0.;
- n.z= 1.;
- }
- return(n);
- }
-
- /**********************************************************************/
- /* Copy matrix M0 to M1 */
- /**********************************************************************/
- void copy_matrix(M0,M1)
- register Matrix M0, M1;
- {
- register int i,j;
-
- for(i=0;i<4;i++) for(j=0;j<4;j++) M1[i][j]= M0[i][j];
- }
-
- /**********************************************************************/
- /* Are matrix M0 to M1 the same matrix */
- /**********************************************************************/
- int same_matrix(M0,M1)
- register Matrix M0, M1;
- {
- register int i,j;
-
- for(i=0;i<4;i++) for(j=0;j<4;j++)
- if (M1[i][j] != M0[i][j]) return 0;
- return 1;
- }
-
- /**********************************************************************/
- /* Are matrix M0 to M1 the same matrix */
- /**********************************************************************/
- int same_matrix3x3(M0,M1)
- register Matrix M0, M1;
- {
- register int i,j;
-
- for(i=0;i<3;i++) for(j=0;j<3;j++)
- if (M1[i][j] != M0[i][j]) return 0;
- return 1;
- }
-
- /**********************************************************************/
- /* Multiply matrix M2 = M0 * M1 */
- /**********************************************************************/
- void mult_matrix(M0, M1, M2)
- register Matrix M0, M1, M2;
- {
- double sum;
- register int i, j, k;
-
- for(i=0;i<4;i++) for(j=0;j<4;j++) {
- sum= 0.0;
- for(k=0;k<4;k++)
- sum += M0[i][k] * M1[k][j];
- M2[i][j] = sum;
- }
- }
-
- /**********************************************************************/
- /* Scalar Multiply matrix M1 = s * M0 */
- /**********************************************************************/
- void smult_matrix(s, M0, M1)
- double s;
- register Matrix M0, M1;
- {
- register int i, j;
-
- for(i=0;i<4;i++) for(j=0;j<4;j++) {
- M1[i][j] = s * M0[i][j];
- }
- }
- /**********************************************************************/
- /* 4x4 Matrix * vector */
- /**********************************************************************/
- Vector vrotate(v,M)
- Vector v;
- register Matrix M;
- {
- Vector vPrime;
-
- vPrime.x= v.x * M[0][0] + v.y * M[1][0] + v.z * M[2][0];
- vPrime.y= v.x * M[0][1] + v.y * M[1][1] + v.z * M[2][1];
- vPrime.z= v.x * M[0][2] + v.y * M[1][2] + v.z * M[2][2];
-
- return(vPrime);
- }
-
- /**********************************************************************/
- /* 4x4 Matrix * vector */
- /**********************************************************************/
- Vector vtransform(v,M)
- Vector v;
- register Matrix M;
- {
- Vector vPrime;
-
- vPrime.x= v.x * M[0][0] + v.y * M[1][0] + v.z * M[2][0] + M[3][0];
- vPrime.y= v.x * M[0][1] + v.y * M[1][1] + v.z * M[2][1] + M[3][1];
- vPrime.z= v.x * M[0][2] + v.y * M[1][2] + v.z * M[2][2] + M[3][2];
- return(vPrime);
- }
-
- /**********************************************************************/
- /* Point transform */
- /**********************************************************************/
- point3 *ptransform(p, m)
- point3 *p;
- Matrix m;
- {
- double x,y,z;
- double w;
- x = (p->x * m[0][0]) + (p->y * m[1][0]) + (p->z * m[2][0]) + m[3][0];
- y = (p->x * m[0][1]) + (p->y * m[1][1]) + (p->z * m[2][1]) + m[3][1];
- z = (p->x * m[0][2]) + (p->y * m[1][2]) + (p->z * m[2][2]) + m[3][2];
- w = (p->x * m[0][3]) + (p->y * m[1][3]) + (p->z * m[2][3]) + m[3][3];
- p->x = x; p->y = y; p->z = z;
- if (w != 0.0) {
- p->x /= w; p->y /= w; p->z /= w;
- }
- else printf("ptransform : point at Infinity.\n");
- return(p);
- }
-
- /**********************************************************************/
- /* Transpose a matrix */
- /**********************************************************************/
- void transpose_matrix(M,m)
- Matrix M, m;
- {
- int i,j;
-
- for (i=0;i<4;i++) for (j=0;j<4;j++)
- m[j][i] = M[i][j];
- }
-
- /**********************************************************************/
- /* Invert matrix a -> b (using determinant method) */
- /**********************************************************************/
- int invert_matrix(a,b)
- Matrix a,b;
- {
- double det;
-
- b[0][0]= a[1][1]*a[2][2] - a[1][2]*a[2][1];
- b[1][0]= a[1][0]*a[2][2] - a[1][2]*a[2][0];
- b[2][0]= a[1][0]*a[2][1] - a[1][1]*a[2][0];
-
- b[0][1]= a[0][1]*a[2][2] - a[0][2]*a[2][1];
- b[1][1]= a[0][0]*a[2][2] - a[0][2]*a[2][0];
- b[2][1]= a[0][0]*a[2][1] - a[0][1]*a[2][0];
-
- b[0][2]= a[0][1]*a[1][2] - a[0][2]*a[1][1];
- b[1][2]= a[0][0]*a[1][2] - a[0][2]*a[1][0];
- b[2][2]= a[0][0]*a[1][1] - a[0][1]*a[1][0];
-
- det= a[0][0]*b[0][0] - a[0][1]*b[1][0] + a[0][2]*b[2][0];
-
- /* matrix is singular */
- if(det < DAMN_SMALL && det > -DAMN_SMALL) return(ERROR);
-
- b[0][0] /= det;
- b[0][1] /= -det;
- b[0][2] /= det;
- b[1][0] /= -det;
- b[1][1] /= det;
- b[1][2] /= -det;
- b[2][0] /= det;
- b[2][1] /= -det;
- b[2][2] /= det;
-
- b[3][0]= -(b[0][0]*a[3][0] + b[1][0]*a[3][1] + b[2][0]*a[3][2]);
- b[3][1]= -(b[0][1]*a[3][0] + b[1][1]*a[3][1] + b[2][1]*a[3][2]);
- b[3][2]= -(b[0][2]*a[3][0] + b[1][2]*a[3][1] + b[2][2]*a[3][2]);
- b[3][3]= 1.;
- b[0][3]= 0.;
- b[1][3]= 0.;
- b[2][3]= 0.;
- return(OK);
- }
-
- /**********************************************************************/
- /* create rotation by theta in z-axis matrix */
- /**********************************************************************/
- void cr_rotatez(theta,M)
- double theta;
- register Matrix M;
- {
- double sine, cosine;
-
- sine= sin(theta);
- cosine= cos(theta);
-
- copy_matrix(Identity,M);
- M[0][0]= cosine;
- M[1][0]= -sine;
- M[0][1]= sine;
- M[1][1]= cosine;
- }
-
- /**********************************************************************/
- /* Rotate in x by angle a */
- /**********************************************************************/
- void rotatex_matrix(M,a)
- Matrix M; /* Current transformation matrix*/
- double a; /* Rotation angle */
- {
- double cosine, sine;
- double t;
- int i;
-
- cosine = cos(a);
- sine = sin(a);
- for (i=0; i<4; i++) {
- t = M[i][1];
- M[i][1] = t*cosine - M[i][2]*sine;
- M[i][2] = t*sine + M[i][2]*cosine;
- }
- }
-
- /**********************************************************************/
- /* Rotate in y by angle a */
- /**********************************************************************/
- void rotatey_matrix(M,a)
- Matrix M; /* Current transformation matrix*/
- double a; /* Rotation angle */
- {
- double cosine, sine;
- double t;
- int i;
-
- cosine = cos(a);
- sine = sin(a);
- /* printf("cosine(%g) = %g\n", a, cosine);
- printf("sine(%g) = %g\n", a, sine); */
-
- for (i=0; i<4; i++) {
- t = M[i][0];
- M[i][0] = t*cosine + M[i][2]*sine;
- M[i][2] = M[i][2]*cosine - t*sine;
- }
- }
-
-
- /**********************************************************************/
- /* rotate in z */
- /**********************************************************************/
- void rotatez_matrix(M,a)
- Matrix M; /* Current transformation matrix*/
- double a; /* Rotation angle */
- {
- double cosine, sine;
- double t;
- int i;
-
- cosine = cos(a);
- sine = sin(a);
-
- for (i=0; i<4; i++) {
- t = M[i][0];
- M[i][0] = t*cosine - M[i][1]*sine;
- M[i][1] = t*sine + M[i][1]*cosine;
- }
- }
-
- /**********************************************************************/
- /* scale matrix by sx, sy, sz */
- /**********************************************************************/
- void scale_matrix(M,sx,sy,sz)
- Matrix M; /* Current transformation matrix */
- double sx, sy, sz; /* Scale factors about x,y,z */
- {
- int i;
-
- for (i=0; i<4; i++) {
- M[i][0] *= sx;
- M[i][1] *= sy;
- M[i][2] *= sz;
- }
- }
-
- /**********************************************************************/
- /* translate matrix */
- /**********************************************************************/
- void translate_matrix(M,tx,ty,tz)
- Matrix M; /* Current transformation matrix */
- double tx, ty, tz; /* Translation distance */
- {
- int i;
-
- for (i=0; i<4; i++) {
- M[i][0] += M[i][3] * tx;
- M[i][1] += M[i][3] * ty;
- M[i][2] += M[i][3] * tz;
- }
- }
-
- /**********************************************************************/
- /* subtract matrices: m2 = m0 - m1 */
- /**********************************************************************/
- void subtract_matrix(m0, m1, m2)
- Matrix m0, m1, m2;
- {
- int i,j;
-
- for (i=0; i<4; i++) for (j=0; j<4; j++)
- m2[i][j] = m0[i][j] - m1[i][j];
- }
-
- /**********************************************************************/
- /* Add 2 matrices */
- /**********************************************************************/
- void add_matrix(m0, m1, m2)
- Matrix m0, m1, m2;
- {
- int i,j;
-
- for (i=0; i<4; i++) for (j=0; j<4; j++)
- m2[i][j] = m0[i][j] + m1[i][j];
- }
-
- /**********************************************************************/
- /* Perspetive transformation along z */
- /**********************************************************************/
- /* Perspective is along the z-axis with the eye at +z. */
- void ZPerspective_matrix(M,d)
- Matrix M; /* Current transformation matrix */
- double d; /* Perspective distance */
- {
- int i;
- double f = 1.0 / d;
-
- for (i = 0; i < 4; i++) {
- M[i][3] += M[i][2] * f;
- M[i][2] = 0.0;
- }
- }
-
- /*********************************************************************
- * Reorthogonalize matrix R - that is find an orthogonal matrix that is
- * "close" to R by computing an approximation to the orthogonal matrix
- *
- * T -1/2
- * RC = R(R R)
- * T-1
- * [RC is orthogonal because (RC) = (RC) ]
- * -1/2
- * To compute C, we evaluate the Taylor expansion of F(x) = (I + x)
- * (where x = C - I) about x=0.
- * This gives C = I - (1/2)x + (3/8)x^2 - (5/16)x^3 + ...
- *
- * Reorthogonalize matrix R - that is find an orthogonal matrix that is
- * "close" to R by computing an approximation to the orthogonal matrix
- *
- * T -1/2
- * RC = R(R R)
- * T-1
- * [RC is orthogonal because (RC) = (RC) ]
- * -1/2
- * To compute C, we evaluate the Taylor expansion of F(x) = (I + x)
- * (where x = C - I) about x=0.
- * This gives C = I - (1/2)x + (3/8)x^2 - (5/16)x^3 + ...
- *********************************************************************/
- static float coef[10] = { /* From mathematica */
- 1, -1./2., 3/8., -5/16., 35/128., -63/256.,
- 231/1024., -429/2048., 6435/32768., -12155/65536.
- };
-
- void reorthogonalize_matrix(R, r, limit)
- Matrix R, r;
- int limit;
- {
- Matrix I, Temp, Xx, X_power, Sum;
- int power;
-
- limit = MAX(limit, 10);
-
- transpose_matrix(R, Temp); /* Rt */
- mult_matrix(Temp, R, Temp); /* RtR */
- copy_matrix(Identity,I); /* I */
- subtract_matrix(Temp, I, Xx); /* RtR - I */
- copy_matrix(Identity,X_power);/* X^0 */
- copy_matrix(Identity,Sum); /* coef[0] * X^0 */
-
- for (power=1; power<limit; ++power) {
- mult_matrix(X_power, Xx, X_power);
- smult_matrix(coef[power], X_power, Temp);
- add_matrix(Sum, Temp, Sum);
- }
- mult_matrix(R, Sum, r);
- }
-
- /**********************************************************************/
- /* Find matrix adjoint */
- /**********************************************************************/
- void adjoint(in,out)
- Matrix in; Matrix out;
- {
- double a1, a2, a3, a4, b1, b2, b3, b4;
- double c1, c2, c3, c4, d1, d2, d3, d4;
- double det3x3();
-
- /* assign to individual variable names to aid */
- /* selecting correct values */
-
- a1 = in[0][0]; b1 = in[0][1];
- c1 = in[0][2]; d1 = in[0][3];
- a2 = in[1][0]; b2 = in[1][1];
- c2 = in[1][2]; d2 = in[1][3];
- a3 = in[2][0]; b3 = in[2][1];
- c3 = in[2][2]; d3 = in[2][3];
- a4 = in[3][0]; b4 = in[3][1];
- c4 = in[3][2]; d4 = in[3][3];
-
- /* row column labeling reversed since we transpose rows & columns */
- out[0][0] = det3x3( b2, b3, b4, c2, c3, c4, d2, d3, d4);
- out[1][0] = - det3x3( a2, a3, a4, c2, c3, c4, d2, d3, d4);
- out[2][0] = det3x3( a2, a3, a4, b2, b3, b4, d2, d3, d4);
- out[3][0] = - det3x3( a2, a3, a4, b2, b3, b4, c2, c3, c4);
- out[0][1] = - det3x3( b1, b3, b4, c1, c3, c4, d1, d3, d4);
- out[1][1] = det3x3( a1, a3, a4, c1, c3, c4, d1, d3, d4);
- out[2][1] = - det3x3( a1, a3, a4, b1, b3, b4, d1, d3, d4);
- out[3][1] = det3x3( a1, a3, a4, b1, b3, b4, c1, c3, c4);
- out[0][2] = det3x3( b1, b2, b4, c1, c2, c4, d1, d2, d4);
- out[1][2] = - det3x3( a1, a2, a4, c1, c2, c4, d1, d2, d4);
- out[2][2] = det3x3( a1, a2, a4, b1, b2, b4, d1, d2, d4);
- out[3][2] = - det3x3( a1, a2, a4, b1, b2, b4, c1, c2, c4);
- out[0][3] = - det3x3( b1, b2, b3, c1, c2, c3, d1, d2, d3);
- out[1][3] = det3x3( a1, a2, a3, c1, c2, c3, d1, d2, d3);
- out[2][3] = - det3x3( a1, a2, a3, b1, b2, b3, d1, d2, d3);
- out[3][3] = det3x3( a1, a2, a3, b1, b2, b3, c1, c2, c3);
- }
-
- /**********************************************************************/
- /* calculate the determinent of a 4x4 matrix. */
- /**********************************************************************/
- double det4x4( m )
- Matrix m;
- {
- double ans;
- double a1, a2, a3, a4, b1, b2, b3, b4, c1, c2, c3, c4, d1, d2, d3, d4;
- double det3x3();
-
- /* assign to individual variable names to aid selecting */
- /* correct elements */
-
- a1 = m[0][0]; b1 = m[0][1];
- c1 = m[0][2]; d1 = m[0][3];
- a2 = m[1][0]; b2 = m[1][1];
- c2 = m[1][2]; d2 = m[1][3];
- a3 = m[2][0]; b3 = m[2][1];
- c3 = m[2][2]; d3 = m[2][3];
- a4 = m[3][0]; b4 = m[3][1];
- c4 = m[3][2]; d4 = m[3][3];
-
- ans = a1 * det3x3( b2, b3, b4, c2, c3, c4, d2, d3, d4) -
- b1 * det3x3( a2, a3, a4, c2, c3, c4, d2, d3, d4) +
- c1 * det3x3( a2, a3, a4, b2, b3, b4, d2, d3, d4) -
- d1 * det3x3( a2, a3, a4, b2, b3, b4, c2, c3, c4);
- return ans;
- }
-
- /**********************************************************************/
- /* calculate the determinent of a 3x3 matrix */
- /**********************************************************************/
- double det3x3( a1, a2, a3, b1, b2, b3, c1, c2, c3 )
- double a1, a2, a3, b1, b2, b3, c1, c2, c3;
- {
- double ans;
- double det2x2();
-
- ans = a1 * det2x2( b2, b3, c2, c3 ) -
- b1 * det2x2( a2, a3, c2, c3 ) +
- c1 * det2x2( a2, a3, b2, b3 );
- return ans;
- }
-
- /**********************************************************************/
- /* calculate the determinent of a 2x2 matrix. */
- /**********************************************************************/
- double det2x2( a, b, c, d)
- double a, b, c, d;
- {
- return (a * d - b * c);
- }
-
-
- /*====================================================================*/
- /* Output routines */
- /*====================================================================*/
-
- /**********************************************************************/
- /* Print a vector */
- /**********************************************************************/
- void print_vector(fp, label,v)
- FILE *fp;
- char *label;
- Vector *v;
- {
- fprintf(fp, "\t%s %g,%g,%g\n", label, v->x, v->y, v->z);
- }
-
- /**********************************************************************/
- /* Print a vector */
- /**********************************************************************/
- void print_vector2(fp, label,v)
- FILE *fp;
- char *label;
- Vector2 *v;
- {
- fprintf(fp, "\tVector: %s = %g,%g\n", label, v->x, v->y);
- }
-
- /**********************************************************************/
- /* Print a matrix */
- /**********************************************************************/
- void print_matrix(fp, label, a)
- FILE *fp;
- char *label;
- register Matrix a;
- {
- int i,j;
-
- fprintf(fp,"\tMatrix: %s\n", label);
- for(i=0;i<4;i++) {
- fprintf(fp,"\t");
- for(j=0;j<4;j++)
- fprintf(fp,"%10.6g ",a[i][j]);
- fprintf(fp,"\n");
- }
- fprintf(fp,"\n");
- }
-