home *** CD-ROM | disk | FTP | other *** search
/ Graphics Plus / Graphics Plus.iso / general / raytrace / radiance / simplerd.lha / simplerad / FinalFTP / Light / geo.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-07-20  |  31.9 KB  |  1,115 lines

  1. /**********************************************************************/
  2. /* geo.c : Geometric operations                                       */
  3. /*                                                                    */
  4. /* Parts from "Illumination and Color in Computer Graphics", by Roy   */
  5. /* Hall.                                                              */
  6. /* Parts also adapted from Graphics Gems I (ed. James Arvo), 1989.    */
  7. /*                                                                    */
  8. /* Copyright (C) 1992, Bernard Kwok                                   */
  9. /* All rights reserved.                                               */
  10. /* Revision 1.0                                                       */
  11. /* May, 1992                                                          */
  12. /**********************************************************************/
  13. #include <stdio.h>
  14. #include <math.h>
  15. #include "misc.h"
  16. #include "geo.h"
  17.  
  18. /*====================================================================*/
  19. /* 2D operations */
  20. /*====================================================================*/
  21.  
  22. /**********************************************************************/
  23. /* 2D Dot product */
  24. /**********************************************************************/
  25. double vdot2(v) 
  26. Vector2 *v;
  27. { return((v->x * v->x) + (v->y * v->y)); }
  28.         
  29. /**********************************************************************/
  30. /* 2D length of vector */
  31. /**********************************************************************/
  32. double vlen2(a) 
  33.      Vector2 *a;
  34. { return(sqrt(vdot2(a))); }
  35.     
  36. /**********************************************************************/
  37. /* 2D negate vector */
  38. /**********************************************************************/
  39. Vector2 *vnegate2(v) 
  40.      Vector2 *v;
  41. { v->x = -v->x;  v->y = -v->y;  return(v); }
  42.  
  43. /**********************************************************************/
  44. /* 2D norm */
  45. /**********************************************************************/
  46. Vector2 *vnorm2(v) 
  47.      Vector2 *v;
  48. {
  49.   double len;
  50.   
  51.   if ((len=vlen2(v)) == 0.0)
  52.     fprintf(stderr,"Cannot normalize, 2d length is zero\n");
  53.   else { v->x /= len; v->y /= len; }
  54.   return(v);
  55. }
  56.  
  57. /**********************************************************************/
  58. /* 2D scale vector */
  59. /**********************************************************************/
  60. Vector2 *vscale2(v, newlen) 
  61.      Vector2 *v;
  62.      double newlen;
  63. {
  64.   double len;
  65.  
  66.   if ((len=vlen2(v)) == 0.0)
  67.     fprintf(stderr,"Cannot scale, 2d length is zero\n");
  68.   else { v->x *= newlen/len; v->y *= newlen/len; }
  69.   return(v);
  70. }
  71.  
  72. /**********************************************************************/
  73. /* 2d vector add */
  74. /**********************************************************************/
  75. Vector2 *vadd2(a, b, c)
  76.      Vector2 *a, *b, *c;
  77. {
  78.   c->x = a->x + b->x;  c->y = a->y + b->y;
  79.   return(c);
  80. }
  81.     
  82. /**********************************************************************/
  83. /* 2d vector subtract */
  84. /**********************************************************************/
  85. Vector2 *vsub2(a, b, c)
  86.      Vector2 *a, *b, *c;
  87. {
  88.   c->x = a->x - b->x;  c->y = a->y - b->y;
  89.   return(c);
  90. }
  91.  
  92. /**********************************************************************/
  93. /* 2d linearly interpolate between vectors by amount alpha */
  94. /**********************************************************************/
  95. Vector2 *vinterp2(lo, hi, alpha, result) 
  96.      Vector2 *lo, *hi, *result; 
  97.      double alpha;
  98. {
  99.   result->x = LERP(alpha, lo->x, hi->x);
  100.   result->y = LERP(alpha, lo->y, hi->y);
  101.   return(result);
  102. }
  103.  
  104. /**********************************************************************/
  105. /* 2d linear combination */
  106. /**********************************************************************/
  107. Vector2 *vcomb2(v1, v2, result, a, b) 
  108.      Vector2 *v1, *v2, *result;
  109.      double a, b;
  110. {
  111.   result->x = (a * v1->x) + (b * v2->x);
  112.   result->y = (a * v1->y) + (b * v2->y);
  113.   return(result);
  114. }
  115.  
  116. /**********************************************************************/
  117. /* 2d multiply two vectors together component-wise */
  118. /**********************************************************************/
  119. Vector2 *vmult2(a, b, result) 
  120. Vector2 *a, *b, *result;
  121. {
  122.   result->x = a->x * b->x;  result->y = a->y * b->y;
  123.   return(result);
  124. }
  125.  
  126. /**********************************************************************/
  127. /* 2D distance between two points */
  128. /**********************************************************************/
  129. double vdist2(a, b)
  130.      point2 *a, *b;
  131. {
  132.   double dx = a->x - b->x;
  133.   double dy = a->y - b->y;
  134.   return(sqrt((dx*dx)+(dy*dy)));
  135. }
  136.  
  137. /**********************************************************************/
  138. /* 2d perpendicular vector to the input vector a */
  139. /**********************************************************************/
  140. Vector2 *vperp2(a, ap)
  141. Vector2 *a, *ap;
  142. {
  143.   ap->x = -a->y; ap->y = a->x;
  144.   return(ap);
  145. }
  146.  
  147. /**********************************************************************/
  148. /* create, initialize, and return a new vector */
  149. /**********************************************************************/
  150. Vector2 *vnew2(x, y)
  151.      double x, y;
  152. {
  153.   Vector2 *v = NEWTYPE(Vector2);
  154.   v->x = x;  v->y = y; 
  155.   return(v);
  156. }
  157.     
  158. /**********************************************************************/
  159. /* create, initialize, and return a duplicate vector */
  160. /**********************************************************************/
  161. Vector2 *vdup2(a)
  162.      Vector2 *a;
  163. {
  164.   Vector2 *v = NEWTYPE(Vector2);
  165.   v->x = a->x;  v->y = a->y; 
  166.   return(v);
  167. }
  168.  
  169. /**********************************************************************/
  170. /* multiply a point by a matrix and return the transformed point */
  171. /**********************************************************************/
  172. point2 *vtransform2(p, m)
  173.      point2 *p;
  174.      Matrix3 *m;
  175. {
  176.   double x,y;
  177.   double w;
  178.     
  179.   x = (p->x * m->element[0][0]) + 
  180.     (p->y * m->element[1][0]) + m->element[2][0];
  181.   y = (p->x * m->element[0][1]) + 
  182.     (p->y * m->element[1][1]) + m->element[2][1];
  183.   w    = (p->x * m->element[0][2]) + 
  184.     (p->y * m->element[1][2]) + m->element[2][2];
  185.   p->x = x; p->y = y;
  186.   if (w != 0.0) { p->x /= w;  p->y /= w; }
  187.   else printf("V2MulpointByMatrix : point at infinity\n");
  188.   return(p);
  189. }
  190.  
  191. /**********************************************************************/
  192. /* multiply together matrices c = ab */
  193. /* note that c must not point to either of the input matrices */
  194. /**********************************************************************/
  195. Matrix3 *multmatrix2(a, b, c)
  196.      Matrix3 *a, *b, *c;
  197. {
  198.   int i,j,k;
  199.  
  200.   for (i=0; i<3; i++) {
  201.     for (j=0; j<3; j++) {
  202.       c->element[i][j] = 0;
  203.       for (k=0; k<3; k++) c->element[i][j] += 
  204.     a->element[i][k] * b->element[k][j];
  205.     }
  206.   }
  207. return(c);
  208. }
  209.  
  210. /*====================================================================*/
  211. /* 3D geometric routines */
  212. /*====================================================================*/
  213. /**********************************************************************/
  214. /* Two vertices are within some tolerance distance of each other */
  215. /**********************************************************************/
  216. int vsame(v1, v2, tolerance)
  217.      Vector *v1, *v2;
  218.      double tolerance;
  219. {
  220.   extern double vdist();
  221.  
  222.   if (_ABS(vdist(v1,v2)) < tolerance) 
  223.     return(1);
  224.   else
  225.     return(0);
  226. }
  227.  
  228. /**********************************************************************/
  229. /* find dot product of vectors v0 and v1 */
  230. /**********************************************************************/
  231. double dot(v0,v1)
  232.      Vector *v0, *v1;
  233. {  return (v0->x * v1->x) + (v0->y * v1->y) + (v0->z * v1->z); }
  234.  
  235. /**********************************************************************/
  236. /* Find cross product of vectors v0 and v1 */
  237. /**********************************************************************/
  238. Vector cross(v0, v1)
  239.      Vector *v0, *v1;
  240. {
  241.   Vector v2;
  242.  
  243.   v2.x = (v0->y * v1->z) - (v0->z * v1->y);
  244.   v2.y = (v0->z * v1->x) - (v0->x * v1->z);
  245.   v2.z = (v0->x * v1->y) - (v0->y * v1->x);
  246.   return v2;
  247. }
  248.  
  249. /**********************************************************************/
  250. /* Multiply a vector by a scalar */
  251. /**********************************************************************/
  252. Vector *vscalar(s, v)
  253.      double s;
  254.      Vector *v;
  255. {
  256.   Vector v1;
  257.  
  258.   v1.x = s * v->x; v1.y = s * v->y; v1.z = s * v->z;
  259.   return &v1;
  260. }
  261.  
  262. /**********************************************************************/
  263. /* Normalized vector v0 and return length, return negative length if */
  264. /* close to zero, or less than zero */
  265. /**********************************************************************/
  266. double norm(v0)
  267.      Vector *v0;
  268. {
  269.   double len;
  270.  
  271.   if ((len = dot(v0,v0)) <= 0.0) return FALSE;
  272.   len = sqrt((double)len);
  273.   if (len < MIN_VECTOR_LENGTH) return FALSE;
  274.   v0->x = v0->x / len;
  275.   v0->y = v0->y / len;
  276.   v0->z = v0->z / len;
  277.   return TRUE;
  278. }
  279.  
  280. /**********************************************************************/
  281. /* Create vector from 2 points, and return length */
  282. /**********************************************************************/
  283. double geo_line(p0, p1, v)
  284.      point3 *p0, *p1;
  285.      line *v;
  286. {
  287.   v->start = *p0;
  288.   v->dir.x = p1->x - p0->x;
  289.   v->dir.y = p1->y - p0->y;
  290.   v->dir.z = p1->z - p0->z;
  291.   return norm(&v->dir);
  292. }
  293.  
  294. /**********************************************************************/
  295. /* Add 2 vectors */
  296. /**********************************************************************/
  297. Vector *vadd(v0, v1)
  298.      Vector *v0, *v1;
  299. {
  300.   Vector add;
  301.   
  302.   add.x = v0->x + v1->x;
  303.   add.y = v0->y + v1->y;
  304.   add.z = v0->z + v1->z;
  305.   return &add;
  306. }
  307.  
  308. /**********************************************************************/
  309. /* Subtract vector v1 from v0 */
  310. /**********************************************************************/
  311. Vector *vsub(v0, v1)
  312.      Vector *v0, *v1;
  313. {
  314.   Vector sub;
  315.   
  316.   sub.x = v0->x - v1->x;
  317.   sub.y = v0->y - v1->y;
  318.   sub.z = v0->z - v1->z;
  319.   return ⊂
  320. }
  321.  
  322. /**********************************************************************/
  323. /* Vector negation */
  324. /**********************************************************************/
  325. Vector *vnegate(v) 
  326.      Vector *v;
  327.   v->x = -v->x;  v->y = -v->y;  v->z = -v->z;
  328.   return(v);
  329. }
  330.  
  331. /**********************************************************************/
  332. /* multiply two vectors together component-wise and return the result */
  333. /**********************************************************************/
  334. Vector *vmult(v1, v2, result) 
  335. Vector *v1, *v2, *result;
  336. {
  337.   result->x = v1->x * v2->x;
  338.   result->y = v1->y * v2->y;
  339.   result->z = v1->z * v2->z;
  340.   return(result);
  341. }
  342.  
  343. /**********************************************************************/
  344. /* return the distance between two points */
  345. /**********************************************************************/
  346. double vdist(a, b)
  347.      Vector *a, *b;
  348. {
  349.   double dx, dy, dz;
  350.  
  351.   dx = a->x - b->x; dy = a->y - b->y;  dz = a->z - b->z;
  352.   return(sqrt((dx*dx)+(dy*dy)+(dz*dz)));
  353. }
  354.  
  355. /**********************************************************************/
  356. /* Mid-point between 2 vectors */
  357. /**********************************************************************/
  358. Vector *vmiddle(v1,v2)
  359.      Vector *v1, *v2;
  360. {
  361.   Vector vmid;
  362.  
  363.   vmid.x = (v1->x + v2->x) / 2.0;
  364.   vmid.y = (v1->y + v2->y) / 2.0;
  365.   vmid.z = (v1->z + v2->z) / 2.0;
  366.   return(&vmid);
  367. }
  368.  
  369. /**********************************************************************/
  370. /* Length of a vector
  371. /**********************************************************************/
  372. double vlen(v) 
  373.      Vector *v;
  374.   double v_dot_v;
  375.   double len;
  376.  
  377.   v_dot_v = dot(v,v);
  378.   len = sqrt(v_dot_v);
  379.   return(len);
  380. }
  381.  
  382. /**********************************************************************/
  383. /* Vector scale */
  384. /**********************************************************************/
  385. Vector *vscale(v, newlen) 
  386.      Vector *v;
  387.      double newlen;
  388. {
  389.   double len = vlen(v);
  390.   if (len != 0.0) {
  391.     v->x *= newlen/len;   v->y *= newlen/len;  v->z *= newlen/len;
  392.   }
  393.   return(v);
  394. }
  395.  
  396. /**********************************************************************/
  397. /* Vector interpolation by alpha */
  398. /**********************************************************************/
  399. Vector *vinterp(lo, hi, alpha, result) 
  400.      Vector *lo, *hi, *result; 
  401.      double alpha;
  402. {
  403.   result->x = LERP(alpha, lo->x, hi->x);
  404.   result->y = LERP(alpha, lo->y, hi->y);
  405.   result->z = LERP(alpha, lo->z, hi->z);
  406.   return(result);
  407. }
  408.  
  409. /**********************************************************************/
  410. /* Vector linear combination: a*v0 + b*v1 */
  411. /**********************************************************************/
  412. Vector *vcomb(v0,v1,a,b)
  413.      Vector *v0, *v1;
  414.      double a,b;
  415. {
  416.   static Vector comb;
  417.   
  418.   comb.x = a * v0->x + b * v1->x;
  419.   comb.y = a * v0->y + b * v1->y;
  420.   comb.z = a * v0->z + b * v1->z;
  421.   return &comb;
  422. }
  423.  
  424. /**********************************************************************/
  425. /* New vector */
  426. /**********************************************************************/
  427. Vector *vnew(x, y, z)
  428.      double x, y, z;
  429. {
  430.   Vector *v = NEWTYPE(Vector);
  431.   v->x = x;  v->y = y;  v->z = z;
  432.   return(v);
  433. }
  434.  
  435. /**********************************************************************/
  436. /* New duplicate vector */
  437. /**********************************************************************/
  438. Vector *vdup(d)
  439. Vector *d;
  440. {
  441.   Vector *v = NEWTYPE(Vector);
  442.   v->x = d->x;  v->y = d->y;  v->z = d->z;
  443.   return(v);
  444. }
  445.  
  446. /**********************************************************************/
  447. /* Ideal reflection vector */
  448. /**********************************************************************/
  449. Vector *reflection(v,n)
  450.      Vector *v, *n;
  451. {
  452.   double n_dot_v;
  453.   static Vector rfl;
  454.  
  455.   n_dot_v = dot(n,v);
  456.   rfl.x = (2.0 * n_dot_v * n->x) - v->x;
  457.   rfl.y = (2.0 * n_dot_v * n->y) - v->y;
  458.   rfl.z = (2.0 * n_dot_v * n->z) - v->z;
  459.   return &rfl;
  460. }
  461.  
  462. /**********************************************************************/
  463. /* Ideal refraction vector (simple) */
  464. /**********************************************************************/
  465. Vector *refraction(v,n,ni,nt)
  466.      Vector *v, *n;
  467.      double ni, nt;
  468. {
  469.   static Vector t;
  470.   Vector sin_t, cos_v;
  471.   double len_sin_t, n_mult, n_dot_v, n_dot_t;
  472.   if ((n_dot_v = dot(n,v)) > 0.0) n_mult = ni / nt;
  473.   else n_mult = nt / ni;
  474.   cos_v.x = n_dot_v * n->x;
  475.   cos_v.y = n_dot_v * n->y;
  476.   cos_v.z = n_dot_v * n->z;
  477.   sin_t.x = (n_mult) * (cos_v.x = v->x);
  478.   sin_t.y = (n_mult) * (cos_v.y = v->y);
  479.   sin_t.z = (n_mult) * (cos_v.z = v->z);
  480.   if ((len_sin_t = dot(&sin_t, &sin_t)) > 1.0)
  481.     return NULL; /* internal reflection */
  482.   n_dot_t = sqrt(1.0 - len_sin_t);
  483.   if (n_dot_v < 0.0) n_dot_t = -n_dot_t;
  484.   t.x = sin_t.x - (n->x * n_dot_t);
  485.   t.y = sin_t.y - (n->y * n_dot_t);
  486.   t.z = sin_t.z - (n->z * n_dot_t);
  487.   return &t;
  488. }
  489.  
  490. /**********************************************************************/
  491. /* Halfway vector */
  492. /**********************************************************************/
  493. Vector *geo_h(l,v)
  494.      Vector *l, *v;
  495. {
  496.   static Vector h;
  497.   h.x = l->x + v->x;
  498.   h.y = l->y + v->y;
  499.   h.z = l->z + v->z;
  500.   if (!norm(&h)) return NULL;
  501.   return &h;
  502. }
  503.  
  504. /**********************************************************************/
  505. /* Halfway vector (refraction) */
  506. /**********************************************************************/
  507. Vector *geo_ht(l,t,ni,nt)
  508.      Vector *l, *t;
  509.      double ni, nt;
  510. {
  511.   float l_dot_t;
  512.   float divisor;
  513.   static Vector ht;
  514.  
  515.   l_dot_t = -(dot(l,t));
  516.   if (ni == nt) {
  517.     if (l_dot_t == 1.0) return l;
  518.     else return NULL;
  519.   }
  520.   if (ni < nt) {
  521.     if (l_dot_t < ni/nt) return NULL;
  522.     divisor = (nt / ni) - 1.0;
  523.     ht.x = -(((l->x + t->x) / divisor) + t->x);
  524.     ht.y = -(((l->y + t->y) / divisor) + t->y);
  525.     ht.z = -(((l->z + t->z) / divisor) + t->z);
  526.   } else {
  527.     if (l_dot_t < nt/ni) return NULL;
  528.     divisor = (ni / nt) - 1.0;
  529.     ht.x = ((l->x + t->x) / divisor) + l->x;
  530.     ht.y = ((l->y + t->y) / divisor) + l->y;
  531.     ht.z = ((l->z + t->z) / divisor) + l->z;
  532.   }
  533.   (void) norm(&ht);
  534.   return &ht;
  535. }
  536.  
  537. /* from optik originally */
  538. /**********************************************************************/
  539. /* This function is similar to pow() but works right only for */
  540. /* positive integer b (but a lot faster) */
  541. /**********************************************************************/
  542. double Power(a,b)
  543.      double a,b;
  544. {
  545.   register int power;
  546.   double result;
  547.   
  548.   result= 1.0;
  549.   power= (int) b;
  550.   while(power > 0) {
  551.     if(power & 1)
  552.       result *= a;
  553.     a *= a;
  554.     power >>= 1;
  555.   }
  556.   return(result);
  557. }
  558.  
  559. /**********************************************************************/
  560. /* Calculate normal for a polygon from its vertices */
  561. /**********************************************************************/
  562. Vector polynorm(vert,size)
  563.      register Vector vert[];
  564.      register int size;
  565. {
  566.   Vector n;
  567.   register int i,j;
  568.   
  569.   n.x = n.y = n.z= 0.0;
  570.   for(i=0;i<size;i++) {
  571.     j= (i+1)%size;
  572.     n.x += (vert[i].y-vert[j].y) * (vert[i].z+vert[j].z);
  573.     n.y += (vert[i].z-vert[j].z) * (vert[i].x+vert[j].x);
  574.     n.z += (vert[i].x-vert[j].x) * (vert[i].y+vert[j].y);
  575.   }
  576.   if(norm(&(n)) < 0.) {
  577.     /*    if(Option.debug)
  578.     printf("Sorry, a normal cannot be computed for one of the polygons.\n");
  579.     */
  580.     n.x = n.y = 0.;
  581.     n.z= 1.;
  582.   }
  583.   return(n);
  584. }
  585.  
  586. /**********************************************************************/
  587. /* Copy matrix M0 to M1 */
  588. /**********************************************************************/
  589. void copy_matrix(M0,M1)
  590.      register Matrix M0, M1;
  591. {
  592.   register int i,j;
  593.   
  594.   for(i=0;i<4;i++) for(j=0;j<4;j++) M1[i][j]= M0[i][j];
  595. }
  596.  
  597. /**********************************************************************/
  598. /* Are matrix M0 to M1 the same matrix */
  599. /**********************************************************************/
  600. int same_matrix(M0,M1)
  601.      register Matrix M0, M1;
  602. {
  603.   register int i,j;
  604.   
  605.   for(i=0;i<4;i++) for(j=0;j<4;j++) 
  606.     if (M1[i][j] != M0[i][j]) return 0;
  607.   return 1;
  608. }
  609.  
  610. /**********************************************************************/
  611. /* Are matrix M0 to M1 the same matrix */
  612. /**********************************************************************/
  613. int same_matrix3x3(M0,M1)
  614.      register Matrix M0, M1;
  615. {
  616.   register int i,j;
  617.   
  618.   for(i=0;i<3;i++) for(j=0;j<3;j++) 
  619.     if (M1[i][j] != M0[i][j]) return 0;
  620.   return 1;
  621. }
  622.  
  623. /**********************************************************************/
  624. /* Multiply matrix M2 = M0 * M1 */
  625. /**********************************************************************/
  626. void mult_matrix(M0, M1, M2)
  627.      register Matrix M0, M1, M2;
  628. {
  629.   double sum;
  630.   register int i, j, k;
  631.   
  632.   for(i=0;i<4;i++) for(j=0;j<4;j++) {
  633.     sum= 0.0;
  634.     for(k=0;k<4;k++)
  635.       sum += M0[i][k] * M1[k][j];
  636.     M2[i][j] = sum;
  637.   }
  638. }
  639.  
  640. /**********************************************************************/
  641. /* Scalar Multiply matrix M1 = s * M0 */
  642. /**********************************************************************/
  643. void smult_matrix(s, M0, M1)
  644.      double s;
  645.      register Matrix M0, M1;
  646. {
  647.   register int i, j;
  648.   
  649.   for(i=0;i<4;i++) for(j=0;j<4;j++) {
  650.     M1[i][j] = s * M0[i][j];
  651.   }
  652. }
  653. /**********************************************************************/
  654. /* 4x4 Matrix * vector */
  655. /**********************************************************************/
  656. Vector vrotate(v,M)
  657.      Vector v;
  658.      register Matrix M;
  659. {
  660.   Vector vPrime;
  661.   
  662.   vPrime.x= v.x * M[0][0] + v.y * M[1][0] + v.z * M[2][0]; 
  663.   vPrime.y= v.x * M[0][1] + v.y * M[1][1] + v.z * M[2][1]; 
  664.   vPrime.z= v.x * M[0][2] + v.y * M[1][2] + v.z * M[2][2]; 
  665.  
  666.   return(vPrime);
  667. }
  668.  
  669. /**********************************************************************/
  670. /* 4x4 Matrix * vector */
  671. /**********************************************************************/
  672. Vector vtransform(v,M)
  673.      Vector v;
  674.      register Matrix M;
  675. {
  676.   Vector vPrime;
  677.   
  678.   vPrime.x= v.x * M[0][0] + v.y * M[1][0] + v.z * M[2][0] + M[3][0];
  679.   vPrime.y= v.x * M[0][1] + v.y * M[1][1] + v.z * M[2][1] + M[3][1];
  680.   vPrime.z= v.x * M[0][2] + v.y * M[1][2] + v.z * M[2][2] + M[3][2];
  681.   return(vPrime);
  682. }
  683.  
  684. /**********************************************************************/
  685. /* Point transform */
  686. /**********************************************************************/
  687. point3 *ptransform(p, m)
  688.      point3 *p;
  689.      Matrix m;
  690. {
  691.   double x,y,z;
  692.   double w;
  693.   x = (p->x * m[0][0]) + (p->y * m[1][0]) + (p->z * m[2][0]) + m[3][0];
  694.   y = (p->x * m[0][1]) + (p->y * m[1][1]) + (p->z * m[2][1]) + m[3][1];
  695.   z = (p->x * m[0][2]) + (p->y * m[1][2]) + (p->z * m[2][2]) + m[3][2];
  696.   w = (p->x * m[0][3]) + (p->y * m[1][3]) + (p->z * m[2][3]) + m[3][3];
  697.   p->x = x; p->y = y; p->z = z;
  698.   if (w != 0.0) {
  699.     p->x /= w;  p->y /= w;  p->z /= w;
  700.   }
  701.   else printf("ptransform : point at Infinity.\n");
  702.   return(p);
  703. }
  704.  
  705. /**********************************************************************/
  706. /* Transpose a matrix */
  707. /**********************************************************************/
  708. void transpose_matrix(M,m)
  709.      Matrix M, m;
  710. {
  711.   int i,j;
  712.  
  713.   for (i=0;i<4;i++) for (j=0;j<4;j++)
  714.     m[j][i] = M[i][j];
  715. }
  716.  
  717. /**********************************************************************/
  718. /* Invert matrix a -> b (using determinant method) */
  719. /**********************************************************************/
  720. int invert_matrix(a,b)
  721.      Matrix a,b;
  722. {
  723.   double det;
  724.  
  725.   b[0][0]= a[1][1]*a[2][2] - a[1][2]*a[2][1];
  726.   b[1][0]= a[1][0]*a[2][2] - a[1][2]*a[2][0];
  727.   b[2][0]= a[1][0]*a[2][1] - a[1][1]*a[2][0];
  728.   
  729.   b[0][1]= a[0][1]*a[2][2] - a[0][2]*a[2][1];
  730.   b[1][1]= a[0][0]*a[2][2] - a[0][2]*a[2][0];
  731.   b[2][1]= a[0][0]*a[2][1] - a[0][1]*a[2][0];
  732.   
  733.   b[0][2]= a[0][1]*a[1][2] - a[0][2]*a[1][1];
  734.   b[1][2]= a[0][0]*a[1][2] - a[0][2]*a[1][0];
  735.   b[2][2]= a[0][0]*a[1][1] - a[0][1]*a[1][0];
  736.   
  737.   det= a[0][0]*b[0][0] - a[0][1]*b[1][0] + a[0][2]*b[2][0];
  738.   
  739.   /* matrix is singular */
  740.   if(det < DAMN_SMALL && det > -DAMN_SMALL) return(ERROR);
  741.  
  742.   b[0][0] /= det;
  743.   b[0][1] /= -det;
  744.   b[0][2] /= det;
  745.   b[1][0] /= -det;
  746.   b[1][1] /= det;
  747.   b[1][2] /= -det;
  748.   b[2][0] /= det;
  749.   b[2][1] /= -det;
  750.   b[2][2] /= det;
  751.   
  752.   b[3][0]= -(b[0][0]*a[3][0] + b[1][0]*a[3][1] + b[2][0]*a[3][2]);
  753.   b[3][1]= -(b[0][1]*a[3][0] + b[1][1]*a[3][1] + b[2][1]*a[3][2]);
  754.   b[3][2]= -(b[0][2]*a[3][0] + b[1][2]*a[3][1] + b[2][2]*a[3][2]);
  755.   b[3][3]= 1.;
  756.   b[0][3]= 0.;
  757.   b[1][3]= 0.;
  758.   b[2][3]= 0.;
  759.   return(OK);
  760. }
  761.  
  762. /**********************************************************************/
  763. /* create rotation by theta in z-axis matrix */
  764. /**********************************************************************/
  765. void cr_rotatez(theta,M)
  766.      double theta;
  767.      register Matrix M;
  768. {
  769.   double sine, cosine;
  770.   
  771.   sine= sin(theta);
  772.   cosine= cos(theta);
  773.   
  774.   copy_matrix(Identity,M);
  775.   M[0][0]= cosine;
  776.   M[1][0]= -sine;
  777.   M[0][1]= sine;
  778.   M[1][1]= cosine;
  779. }
  780.  
  781. /**********************************************************************/
  782. /* Rotate in x by angle a */ 
  783. /**********************************************************************/
  784. void rotatex_matrix(M,a)
  785.      Matrix M;   /* Current transformation matrix*/
  786.      double a;     /* Rotation angle        */
  787. {
  788.   double cosine, sine;
  789.   double t;
  790.   int i;
  791.  
  792.   cosine = cos(a);    
  793.   sine = sin(a);
  794.   for (i=0; i<4; i++) {
  795.     t = M[i][1];
  796.     M[i][1] = t*cosine - M[i][2]*sine;
  797.     M[i][2] = t*sine + M[i][2]*cosine;
  798.   }
  799. }
  800.  
  801. /**********************************************************************/
  802. /* Rotate in y by angle a */ 
  803. /**********************************************************************/
  804. void rotatey_matrix(M,a)
  805.      Matrix M;  /* Current transformation matrix*/
  806.      double a;    /* Rotation angle        */
  807. {
  808.   double cosine, sine;
  809.   double t;
  810.   int i;
  811.  
  812.   cosine = cos(a);
  813.   sine = sin(a);
  814.   /* printf("cosine(%g) = %g\n", a, cosine);
  815.   printf("sine(%g) = %g\n", a, sine); */
  816.  
  817.   for (i=0; i<4; i++) {
  818.     t = M[i][0];
  819.     M[i][0] = t*cosine + M[i][2]*sine;
  820.     M[i][2] = M[i][2]*cosine - t*sine;
  821.   }
  822. }
  823.  
  824.  
  825. /**********************************************************************/
  826. /* rotate in z */
  827. /**********************************************************************/
  828. void rotatez_matrix(M,a)
  829.      Matrix    M;            /* Current transformation matrix*/
  830.      double    a;            /* Rotation angle        */
  831. {
  832.   double cosine, sine;
  833.   double t;
  834.   int i;
  835.  
  836.   cosine = cos(a);    
  837.   sine = sin(a);
  838.   
  839.   for (i=0; i<4; i++) {
  840.     t = M[i][0];
  841.     M[i][0] = t*cosine - M[i][1]*sine;
  842.     M[i][1] = t*sine + M[i][1]*cosine;
  843.   }
  844. }
  845.  
  846. /**********************************************************************/
  847. /* scale matrix by sx, sy, sz */
  848. /**********************************************************************/
  849. void scale_matrix(M,sx,sy,sz)
  850.      Matrix    M;        /* Current transformation matrix */
  851.      double    sx, sy, sz;    /* Scale factors about x,y,z */
  852. {
  853.   int i;
  854.  
  855.   for (i=0; i<4; i++) {
  856.     M[i][0] *= sx;
  857.     M[i][1] *= sy;
  858.     M[i][2] *= sz;
  859.   }
  860. }
  861.  
  862. /**********************************************************************/
  863. /* translate matrix */
  864. /**********************************************************************/
  865. void translate_matrix(M,tx,ty,tz)
  866.      Matrix    M;            /* Current transformation matrix */
  867.      double    tx, ty, tz;    /* Translation distance */
  868. {
  869.   int i;
  870.  
  871.   for (i=0; i<4; i++) {
  872.     M[i][0] += M[i][3] * tx;
  873.     M[i][1] += M[i][3] * ty;
  874.     M[i][2] += M[i][3] * tz;
  875.   }
  876. }
  877.  
  878. /**********************************************************************/
  879. /* subtract matrices: m2 = m0 - m1 */
  880. /**********************************************************************/
  881. void subtract_matrix(m0, m1, m2)
  882.      Matrix    m0, m1, m2;
  883. {
  884.   int i,j;
  885.   
  886.   for (i=0; i<4; i++) for (j=0; j<4; j++) 
  887.     m2[i][j] = m0[i][j] - m1[i][j];
  888. }
  889.  
  890. /**********************************************************************/
  891. /* Add 2 matrices */
  892. /**********************************************************************/
  893. void add_matrix(m0, m1, m2)
  894.      Matrix    m0, m1, m2;
  895. {
  896.   int i,j;
  897.   
  898.   for (i=0; i<4; i++) for (j=0; j<4; j++) 
  899.     m2[i][j] = m0[i][j] + m1[i][j];
  900. }
  901.  
  902. /**********************************************************************/
  903. /* Perspetive transformation along z */
  904. /**********************************************************************/
  905. /* Perspective is along the z-axis with the eye at +z.   */
  906. void ZPerspective_matrix(M,d)
  907.      Matrix    M;            /* Current transformation matrix  */
  908.      double    d;            /* Perspective distance        */
  909. {
  910.   int i;
  911.   double f = 1.0 / d;
  912.  
  913.   for (i = 0; i < 4; i++) {
  914.     M[i][3] += M[i][2] * f;
  915.     M[i][2]  = 0.0;
  916.   }
  917. }
  918.  
  919. /*********************************************************************
  920.  * Reorthogonalize matrix R - that is find an orthogonal matrix that is
  921.  * "close" to R by computing an approximation to the orthogonal matrix
  922.  *
  923.  *           T  -1/2
  924.  *   RC = R(R R)
  925.  *                           T-1
  926.  * [RC is orthogonal because (RC) = (RC) ]
  927.  *                                                       -1/2
  928.  * To compute C, we evaluate the Taylor expansion of F(x) = (I + x)
  929.  * (where x = C - I) about x=0.
  930.  * This gives C = I - (1/2)x + (3/8)x^2 - (5/16)x^3 + ...
  931.  *
  932.  * Reorthogonalize matrix R - that is find an orthogonal matrix that is
  933.  * "close" to R by computing an approximation to the orthogonal matrix
  934.  *
  935.  *           T  -1/2
  936.  *   RC = R(R R)
  937.  *                        T-1
  938.  * [RC is orthogonal because (RC) = (RC) ]
  939.  *                                                       -1/2
  940.  * To compute C, we evaluate the Taylor expansion of F(x) = (I + x)
  941.  * (where x = C - I) about x=0.
  942.  * This gives C = I - (1/2)x + (3/8)x^2 - (5/16)x^3 + ...
  943.  *********************************************************************/
  944. static float coef[10] = {            /* From mathematica */
  945.   1, -1./2., 3/8., -5/16., 35/128., -63/256.,
  946.   231/1024., -429/2048., 6435/32768., -12155/65536. 
  947.   };
  948.  
  949. void reorthogonalize_matrix(R, r, limit)
  950.      Matrix R, r;
  951.      int limit;
  952. {
  953.   Matrix I, Temp, Xx, X_power, Sum;
  954.   int power;
  955.   
  956.   limit = MAX(limit, 10);
  957.  
  958.   transpose_matrix(R, Temp);    /* Rt */
  959.   mult_matrix(Temp, R, Temp);    /* RtR */
  960.   copy_matrix(Identity,I);      /* I */
  961.   subtract_matrix(Temp, I, Xx);    /* RtR - I */
  962.   copy_matrix(Identity,X_power);/* X^0 */
  963.   copy_matrix(Identity,Sum);    /* coef[0] * X^0 */
  964.  
  965.   for (power=1; power<limit; ++power) {
  966.     mult_matrix(X_power, Xx, X_power);
  967.     smult_matrix(coef[power], X_power, Temp);
  968.     add_matrix(Sum, Temp, Sum);
  969.   }
  970.   mult_matrix(R, Sum, r);
  971. }
  972.  
  973. /**********************************************************************/
  974. /* Find matrix adjoint */
  975. /**********************************************************************/
  976. void adjoint(in,out) 
  977.      Matrix in; Matrix out;
  978. {
  979.   double a1, a2, a3, a4, b1, b2, b3, b4;
  980.   double c1, c2, c3, c4, d1, d2, d3, d4;
  981.   double det3x3();
  982.  
  983.   /* assign to individual variable names to aid  */
  984.   /* selecting correct values  */
  985.  
  986.   a1 = in[0][0]; b1 = in[0][1]; 
  987.   c1 = in[0][2]; d1 = in[0][3];
  988.   a2 = in[1][0]; b2 = in[1][1]; 
  989.   c2 = in[1][2]; d2 = in[1][3];
  990.   a3 = in[2][0]; b3 = in[2][1];
  991.   c3 = in[2][2]; d3 = in[2][3];
  992.   a4 = in[3][0]; b4 = in[3][1]; 
  993.   c4 = in[3][2]; d4 = in[3][3];
  994.  
  995.   /* row column labeling reversed since we transpose rows & columns */
  996.   out[0][0]  =   det3x3( b2, b3, b4, c2, c3, c4, d2, d3, d4);
  997.   out[1][0]  = - det3x3( a2, a3, a4, c2, c3, c4, d2, d3, d4);
  998.   out[2][0]  =   det3x3( a2, a3, a4, b2, b3, b4, d2, d3, d4);
  999.   out[3][0]  = - det3x3( a2, a3, a4, b2, b3, b4, c2, c3, c4);
  1000.   out[0][1]  = - det3x3( b1, b3, b4, c1, c3, c4, d1, d3, d4);
  1001.   out[1][1]  =   det3x3( a1, a3, a4, c1, c3, c4, d1, d3, d4);
  1002.   out[2][1]  = - det3x3( a1, a3, a4, b1, b3, b4, d1, d3, d4);
  1003.   out[3][1]  =   det3x3( a1, a3, a4, b1, b3, b4, c1, c3, c4);
  1004.   out[0][2]  =   det3x3( b1, b2, b4, c1, c2, c4, d1, d2, d4);
  1005.   out[1][2]  = - det3x3( a1, a2, a4, c1, c2, c4, d1, d2, d4);
  1006.   out[2][2]  =   det3x3( a1, a2, a4, b1, b2, b4, d1, d2, d4);
  1007.   out[3][2]  = - det3x3( a1, a2, a4, b1, b2, b4, c1, c2, c4);
  1008.   out[0][3]  = - det3x3( b1, b2, b3, c1, c2, c3, d1, d2, d3);
  1009.   out[1][3]  =   det3x3( a1, a2, a3, c1, c2, c3, d1, d2, d3);
  1010.   out[2][3]  = - det3x3( a1, a2, a3, b1, b2, b3, d1, d2, d3);
  1011.   out[3][3]  =   det3x3( a1, a2, a3, b1, b2, b3, c1, c2, c3);
  1012. }
  1013.  
  1014. /**********************************************************************/
  1015. /* calculate the determinent of a 4x4 matrix. */
  1016. /**********************************************************************/
  1017. double det4x4( m ) 
  1018.      Matrix m;
  1019. {
  1020.   double ans;
  1021.   double a1, a2, a3, a4, b1, b2, b3, b4, c1, c2, c3, c4, d1, d2, d3, d4;
  1022.   double det3x3();
  1023.  
  1024.   /* assign to individual variable names to aid selecting */
  1025.   /*  correct elements */
  1026.  
  1027.   a1 = m[0][0]; b1 = m[0][1]; 
  1028.   c1 = m[0][2]; d1 = m[0][3];
  1029.   a2 = m[1][0]; b2 = m[1][1]; 
  1030.   c2 = m[1][2]; d2 = m[1][3];
  1031.   a3 = m[2][0]; b3 = m[2][1]; 
  1032.   c3 = m[2][2]; d3 = m[2][3];
  1033.   a4 = m[3][0]; b4 = m[3][1]; 
  1034.   c4 = m[3][2]; d4 = m[3][3];
  1035.  
  1036.   ans = a1 * det3x3( b2, b3, b4, c2, c3, c4, d2, d3, d4) -
  1037.     b1 * det3x3( a2, a3, a4, c2, c3, c4, d2, d3, d4) +
  1038.       c1 * det3x3( a2, a3, a4, b2, b3, b4, d2, d3, d4) -
  1039.     d1 * det3x3( a2, a3, a4, b2, b3, b4, c2, c3, c4);
  1040.   return ans;
  1041. }
  1042.  
  1043. /**********************************************************************/
  1044. /* calculate the determinent of a 3x3 matrix */
  1045. /**********************************************************************/
  1046. double det3x3( a1, a2, a3, b1, b2, b3, c1, c2, c3 )
  1047.      double a1, a2, a3, b1, b2, b3, c1, c2, c3;
  1048. {
  1049.   double ans;
  1050.   double det2x2();
  1051.  
  1052.   ans = a1 * det2x2( b2, b3, c2, c3 ) -
  1053.      b1 * det2x2( a2, a3, c2, c3 ) +
  1054.        c1 * det2x2( a2, a3, b2, b3 );
  1055.   return ans;
  1056. }
  1057.  
  1058. /**********************************************************************/
  1059. /* calculate the determinent of a 2x2 matrix. */
  1060. /**********************************************************************/
  1061. double det2x2( a, b, c, d)
  1062. double a, b, c, d; 
  1063. {
  1064.   return (a * d - b * c);
  1065. }
  1066.  
  1067.  
  1068. /*====================================================================*/
  1069. /* Output routines */
  1070. /*====================================================================*/
  1071.  
  1072. /**********************************************************************/
  1073. /* Print a vector */
  1074. /**********************************************************************/
  1075. void print_vector(fp, label,v)
  1076.      FILE *fp;
  1077.      char *label;
  1078.      Vector *v;
  1079. {
  1080.   fprintf(fp, "\t%s %g,%g,%g\n", label, v->x, v->y, v->z);
  1081. }
  1082.  
  1083. /**********************************************************************/
  1084. /* Print a vector */
  1085. /**********************************************************************/
  1086. void print_vector2(fp, label,v)
  1087.      FILE *fp;
  1088.      char *label;
  1089.      Vector2 *v;
  1090. {
  1091.   fprintf(fp, "\tVector: %s = %g,%g\n", label, v->x, v->y);
  1092. }
  1093.  
  1094. /**********************************************************************/
  1095. /* Print a matrix */
  1096. /**********************************************************************/
  1097. void print_matrix(fp, label, a)
  1098.      FILE *fp;
  1099.      char *label;
  1100.      register Matrix a;
  1101. {
  1102.   int i,j;
  1103.  
  1104.   fprintf(fp,"\tMatrix: %s\n", label);
  1105.   for(i=0;i<4;i++) {
  1106.     fprintf(fp,"\t");
  1107.     for(j=0;j<4;j++)
  1108.       fprintf(fp,"%10.6g  ",a[i][j]);
  1109.     fprintf(fp,"\n");
  1110.   }
  1111.   fprintf(fp,"\n");
  1112. }
  1113.