home *** CD-ROM | disk | FTP | other *** search
/ Otherware / Otherware_1_SB_Development.iso / mac / developm / source / povsrc.sit / SOURCE / POLY.C < prev    next >
Encoding:
C/C++ Source or Header  |  1992-07-03  |  25.0 KB  |  819 lines

  1. /****************************************************************************
  2. *                poly.c
  3. *
  4. *  This module implements the code for general 3 variable polynomial shapes
  5. *
  6. *  This file was written by Alexander Enzmann.  He wrote the code for
  7. *  4th - 6th order shapes and generously provided us these enhancements.
  8. *
  9. *  from Persistence of Vision Raytracer 
  10. *  Copyright 1992 Persistence of Vision Team
  11. *---------------------------------------------------------------------------
  12. *  Copying, distribution and legal info is in the file povlegal.doc which
  13. *  should be distributed with this file. If povlegal.doc is not available
  14. *  or for more info please contact:
  15. *
  16. *       Drew Wells [POV-Team Leader] 
  17. *       CIS: 73767,1244  Internet: 73767.1244@compuserve.com
  18. *       Phone: (213) 254-4041
  19. * This program is based on the popular DKB raytracer version 2.12.
  20. * DKBTrace was originally written by David K. Buck.
  21. * DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins.
  22. *
  23. *****************************************************************************/
  24.  
  25. #include "frame.h"
  26. #include "vector.h"
  27. #include "povproto.h"
  28.  
  29. /* Basic form of a quartic equation
  30.    a00*x^4+a01*x^3*y+a02*x^3*z+a03*x^3+a04*x^2*y^2+
  31.    a05*x^2*y*z+a06*x^2*y+a07*x^2*z^2+a08*x^2*z+a09*x^2+
  32.    a10*x*y^3+a11*x*y^2*z+a12*x*y^2+a13*x*y*z^2+a14*x*y*z+
  33.    a15*x*y+a16*x*z^3+a17*x*z^2+a18*x*z+a19*x+a20*y^4+
  34.    a21*y^3*z+a22*y^3+a23*y^2*z^2+a24*y^2*z+a25*y^2+a26*y*z^3+
  35.    a27*y*z^2+a28*y*z+a29*y+a30*z^4+a31*z^3+a32*z^2+a33*z+a34
  36. */
  37.  
  38. #define COEFF_LIMIT 1.0e-20
  39.  
  40. #define LEFT_MARGIN 0
  41. #define RIGHT_MARGIN 72
  42.  
  43. int binomial[11][12] = {
  44.    { 0, 1,  0,  0,   0,   0,   0,   0,   0, 0,  0,  0},
  45.    { 0, 1,  1,  0,   0,   0,   0,   0,   0, 0,  0,  0},
  46.    { 0, 1,  2,  1,   0,   0,   0,   0,   0, 0,  0,  0},
  47.    { 0, 1,  3,  3,   1,   0,   0,   0,   0, 0,  0,  0},
  48.    { 0, 1,  4,  6,   4,   1,   0,   0,   0, 0,  0,  0},
  49.    { 0, 1,  5, 10,  10,   5,   1,   0,   0, 0,  0,  0},
  50.    { 0, 1,  6, 15,  20,  15,   6,   1,   0, 0,  0,  0},
  51.    { 0, 1,  7, 21,  35,  35,  21,   7,   1, 0,  0,  0},
  52.    { 0, 1,  8, 28,  56,  70,  56,  28,   8, 1,  0,  0},
  53.    { 0, 1,  9, 36,  84, 126, 126,  84,  36, 9,  1,  0},
  54.    { 0, 1, 10, 45, 120, 210, 252, 210, 120, 45, 10, 1}};
  55.  
  56. int factorials[MAX_ORDER+1] = {1, 1, 2, 6, 24, 120, 720, 5040};
  57. int term_counts[MAX_ORDER+1] = {1, 4, 10, 20, 35, 56, 84, 120};
  58.  
  59. METHODS Poly_Methods =
  60. { Object_Intersect, All_Poly_Intersections,
  61.    Inside_Poly, Poly_Normal, Copy_Poly,
  62.    Translate_Poly, Rotate_Poly,
  63.    Scale_Poly, Invert_Poly};
  64.  
  65. extern long Ray_Poly_Tests, Ray_Poly_Tests_Succeeded;
  66.  
  67. static void transform PARAMS((int order,DBL *Coeffs,MATRIX *q));
  68. static int roll PARAMS((int order,int x,int y,int z));
  69. static void unroll PARAMS((int order,int index,int *x,int *y,int *z,int *w));
  70. /*static void show_poly PARAMS((char *label, int Order, DBL *Coeffs));*/
  71. static int intersect PARAMS((RAY *Ray, int Order, DBL *Coeffs, DBL *Depths));
  72. static int intersect_quartic PARAMS((RAY *Ray, POLY *Shape, DBL *Depths));
  73. static void quartic_normal PARAMS((VECTOR *Result, OBJECT *Object,
  74. VECTOR *Intersection_Point));
  75. static DBL inside PARAMS((VECTOR *point, int Order, DBL *Coeffs));
  76. static void normalp PARAMS((VECTOR *Result, int Order, DBL *Coeffs,
  77. VECTOR *Intersection_Point));
  78. static DBL do_partial_term PARAMS((MATRIX *q, int row, int pwr, int i,
  79. int j, int k, int l));
  80.  
  81. int All_Poly_Intersections(Object, Ray, Depth_Queue)
  82. OBJECT *Object;
  83. RAY *Ray;
  84. PRIOQ *Depth_Queue;
  85. {
  86.    POLY *Shape = (POLY *) Object;
  87.    DBL Depths[MAX_ORDER], len;
  88.    VECTOR Intersection_Point, dv;
  89.    INTERSECTION Local_Element;
  90.    int cnt, i, j, Intersection_Found;
  91.    RAY New_Ray;
  92.  
  93.    /* Transform the ray into the polynomial's space */
  94.    if (Shape->Transform != NULL) {
  95.       MInverseTransformVector(&New_Ray.Initial, &Ray->Initial,
  96.          Shape->Transform);
  97.       MInvTransVector(&New_Ray.Direction, &Ray->Direction, Shape->Transform);
  98.    }
  99.    else {
  100.       New_Ray.Initial.x = Ray->Initial.x;
  101.       New_Ray.Initial.y = Ray->Initial.y;
  102.       New_Ray.Initial.z = Ray->Initial.z;
  103.       New_Ray.Direction.x = Ray->Direction.x;
  104.       New_Ray.Direction.y = Ray->Direction.y;
  105.       New_Ray.Direction.z = Ray->Direction.z;
  106.    }
  107.  
  108.       len = sqrt(New_Ray.Direction.x * New_Ray.Direction.x +
  109.          New_Ray.Direction.y * New_Ray.Direction.y +
  110.          New_Ray.Direction.z * New_Ray.Direction.z);
  111.    if (len == 0.0)
  112.       return 0;
  113.    else {
  114.       New_Ray.Direction.x /= len;
  115.       New_Ray.Direction.y /= len;
  116.       New_Ray.Direction.z /= len;
  117.    }
  118.  
  119.       Intersection_Found = FALSE;
  120.    Ray_Poly_Tests++;
  121.    if (Shape->Order == 4)
  122.       cnt = intersect_quartic(&New_Ray, Shape, Depths);
  123.    else
  124.       cnt = intersect(&New_Ray, Shape->Order, Shape->Coeffs, &Depths[0]);
  125.  
  126.    if (cnt > 0) Ray_Poly_Tests_Succeeded++;
  127.    for (i=0;i<cnt;i++) {
  128.       if (Depths[i] < 0) goto l0;
  129.       for (j=0;j<i;j++)
  130.          if (Depths[i] == Depths[j]) goto l0;
  131.       VScale(Intersection_Point, New_Ray.Direction, Depths[j]);
  132.       VAdd(Intersection_Point, Intersection_Point, New_Ray.Initial);
  133.       /* Transform the point into world space */
  134.       if (Shape->Transform != NULL)
  135.          MTransformVector(&Intersection_Point, &Intersection_Point,
  136.             Shape->Transform);
  137.  
  138.       VSub(dv, Intersection_Point, Ray->Initial);
  139.       VLength(len, dv);
  140.       Local_Element.Depth = len;
  141.       Local_Element.Object = Shape->Parent_Object;
  142.       Local_Element.Point = Intersection_Point;
  143.       Local_Element.Shape = (SHAPE *)Shape;
  144.       pq_add (Depth_Queue, &Local_Element);
  145.       Intersection_Found = TRUE;
  146. l0:;
  147.    }
  148.    return (Intersection_Found);
  149. }
  150.  
  151. /* Given the powers return the index into the polynomial */
  152. static int roll(order, x, y, z)
  153. int order, x, y, z;
  154. {
  155.    int xstart, ystart, zstart;
  156.    xstart = binomial[order-x+2][order-x];
  157.    order = order - x;
  158.    ystart = binomial[order-y+1][order-y];
  159.    order = order - y;
  160.    zstart = binomial[order-z][order-z];
  161.    return xstart+ystart+zstart;
  162. }
  163.  
  164. /* Given the index into the polynomial, return the powers. */
  165. static void unroll(order, index, x, y, z, w)
  166. int order, index, *x, *y, *z, *w;
  167. {
  168.    int i, torder;
  169.    if (index==0) { *x = order; *y = 0; *z = 0; *w = 0; return; }
  170.    else if (order==1)
  171.       if (index == 1) { *x = 0; *y = 1; *z = 0; *w = 0; return; }
  172.       else { *x = 0; *y = 0; *z = 3 - index; *w = order-(*x+*y+*z); return; }
  173.    else for (i=0;binomial[3+i][i+1]<=index;i++);
  174.    torder = order;
  175.    *x = torder - i; index -= binomial[2+i][i]; torder = i;
  176.    if (index==0) { *y = torder; *z = 0; *w = 0; return; }
  177.    else if (torder==1) { *y = 0; *z = 2-index; *w = order-(*x+*y+*z); return; }
  178.    else for (i=0;binomial[2+i][i+1]<=index;i++);
  179.    *y = torder - i; index -= binomial[1+i][i]; torder = i;
  180.    *z = torder - index;
  181.    *w = order - (*x + *y + *z);
  182. }
  183.  
  184.    /* REMOVED UNUSED ROUTINE 3/27/92
  185. static void show_poly(label, Order, Coeffs)
  186.    char *label;
  187.    int Order;
  188.    DBL *Coeffs;
  189. {
  190.    int i,j,cnt,col;
  191.    int wp, xp, yp, zp;
  192.    char term[40];
  193.    j = 0;
  194.    printf("%s", label);
  195.    col = strlen(label);
  196.  
  197.  
  198.    for (i=0;i<term_counts[Order];i++)
  199.       if (Coeffs[i] != 0.0) {
  200.      if (j) cnt = STRLN(sprintf(&term[0], " + %.5lg", Coeffs[i]));
  201.      else cnt = STRLN(sprintf(&term[0], "%.5lg", Coeffs[i]));
  202.      unroll(Order, i, &xp, &yp, &zp, &wp);
  203.      if (xp == 1) cnt += STRLN(sprintf(&term[cnt], "*x"));
  204.      else if (xp > 1) cnt += STRLN(sprintf(&term[cnt], "*x^%d", xp));
  205.      if (yp == 1) cnt += STRLN(sprintf(&term[cnt], "*y"));
  206.      else if (yp > 1) cnt += STRLN(sprintf(&term[cnt], "*y^%d", yp));
  207.      if (zp == 1) cnt += STRLN(sprintf(&term[cnt], "*z"));
  208.      else if (zp > 1) cnt += STRLN(sprintf(&term[cnt], "*z^%d", zp));
  209.      j = 1;
  210.      if (col+cnt>RIGHT_MARGIN) { printf("\n"); col=LEFT_MARGIN; }
  211.      printf("%s", &term[0]);
  212.      col += cnt;
  213.      }
  214. }
  215. */
  216.  
  217. /* Intersection of a ray and an arbitrary polynomial function */
  218. static int intersect(Ray, Order, Coeffs, Depths)
  219. RAY *Ray;
  220. int Order;
  221. DBL *Coeffs, *Depths;
  222. {
  223.    MATRIX q;
  224.    DBL *a, t[MAX_ORDER+1];
  225.    int i, j;
  226.    /* Determine the coefficients of t^n, where the line is represented
  227.       as (x,y,z) + (xx,yy,zz)*t.  */
  228.    if ((a = (DBL *)malloc(term_counts[Order] * sizeof(DBL))) == NULL) {
  229.       printf("Cannot allocate memory for coefficients in poly intersect()\n");
  230.       exit(1);
  231.    }
  232.    for (i=0;i<term_counts[Order];i++)
  233.       a[i] = Coeffs[i];
  234.    MZero((MATRIX *)&q[0][0]);
  235.    q[0][0] = Ray->Direction.x; q[3][0] = Ray->Initial.x;
  236.    q[0][1] = Ray->Direction.y; q[3][1] = Ray->Initial.y;
  237.    q[0][2] = Ray->Direction.z; q[3][2] = Ray->Initial.z;
  238.    transform(Order, a, (MATRIX *)&q[0][0]);
  239.    /* The equation is now in terms of one variable.  Use numerical
  240.       techniques to solve the polynomial that represents the intersections. */
  241.    for (i=0;i<=Order;i++) {
  242.       t[i] = a[binomial[3+i][4]-1];
  243.       if (t[i] > -COEFF_LIMIT && t[i] < COEFF_LIMIT)
  244.          t[i] = 0.0;
  245.    }
  246.    free(a);
  247.    for (i=0,j=Order;i<=Order;i++)
  248.       if (t[i] != 0.0)
  249.          break;
  250.       else
  251.          j -= 1;
  252.    if (j > 2)
  253.       return polysolve(j, &t[i], Depths);
  254.    else if (j > 0)
  255.       return solve_quadratic(&t[i], Depths);
  256.    else
  257.       return 0;
  258. }
  259.  
  260. static DBL inside(point, Order, Coeffs)
  261. VECTOR *point;
  262. int Order;
  263. DBL *Coeffs;
  264. {
  265.    DBL x[MAX_ORDER+1], y[MAX_ORDER+1], z[MAX_ORDER+1], Result;
  266.    int i, k0, k1, k2, k3;
  267.    x[0] = 1.0; y[0] = 1.0; z[0] = 1.0;
  268.    x[1] = point->x; y[1] = point->y; z[1] = point->z;
  269.    for (i=2;i<=MAX_ORDER;i++) {
  270.       x[i] = x[1] * x[i-1]; y[i] = y[1] * y[i-1]; z[i] = z[1] * z[i-1];
  271.    }
  272.    Result = 0.0;
  273.    for (i=0;i<term_counts[Order];i++) {
  274.       unroll(Order, i, &k0, &k1, &k2, &k3);
  275.       Result += Coeffs[i] * x[k0] * y[k1] * z[k2];
  276.    }
  277.  
  278.    /* The Epsilon fudge factor is so that points really near the
  279.       surface are considered inside the surface */
  280.    return (Result>-EPSILON?(Result<EPSILON?0.0:Result):
  281.    Result);
  282. }
  283.  
  284. /* Normal to a polynomial */
  285. static void normalp(Result, Order, Coeffs, Intersection_Point)
  286. VECTOR *Result;
  287. int Order;
  288. DBL *Coeffs;
  289. VECTOR *Intersection_Point;
  290. {
  291.    int i, xp, yp, zp, wp;
  292.    DBL *a,x[MAX_ORDER+1],y[MAX_ORDER+1],z[MAX_ORDER+1];
  293.    x[0] = 1.0; y[0] = 1.0; z[0] = 1.0;
  294.    x[1] = Intersection_Point->x;
  295.    y[1] = Intersection_Point->y;
  296.    z[1] = Intersection_Point->z;
  297.    for (i=2;i<=Order;i++) {
  298.       x[i] = Intersection_Point->x * x[i-1];
  299.       y[i] = Intersection_Point->y * y[i-1];
  300.       z[i] = Intersection_Point->z * z[i-1];
  301.    }
  302.    a = Coeffs;
  303.    Result->x = 0.0; Result->y = 0.0; Result->z = 0.0;
  304.    for (i=0;i<term_counts[Order];i++) {
  305.       unroll(Order, i, &xp, &yp, &zp, &wp);
  306.       if (xp >= 1) Result->x += xp * a[i] * x[xp-1] * y[yp] * z[zp];
  307.       if (yp >= 1) Result->y += yp * a[i] * x[xp] * y[yp-1] * z[zp];
  308.       if (zp >= 1) Result->z += zp * a[i] * x[xp] * y[yp] * z[zp-1];
  309.    }
  310.    VTemp = sqrt(Result->x * Result->x +
  311.       Result->y * Result->y +
  312.       Result->z * Result->z);
  313.    if (VTemp > 0.0) {
  314.       Result->x /= VTemp;
  315.       Result->y /= VTemp;
  316.       Result->z /= VTemp;
  317.    }
  318.    else {
  319.       Result->x = 1.0;
  320.       Result->y = 0.0;
  321.       Result->z = 0.0;
  322.    }
  323. }
  324.  
  325. static DBL
  326. do_partial_term(q, row, pwr, i, j, k, l)
  327. MATRIX *q;
  328. int row, pwr, i, j, k, l;
  329. {
  330.    DBL result;
  331.    int n;
  332.  
  333.    result = (DBL)(factorials[pwr] /
  334.       (factorials[i]*factorials[j]*factorials[k]*factorials[l]));
  335.    if (i>0) for (n=0;n<i;n++) result *= (*q)[0][row];
  336.    if (j>0) for (n=0;n<j;n++) result *= (*q)[1][row];
  337.    if (k>0) for (n=0;n<k;n++) result *= (*q)[2][row];
  338.    if (l>0) for (n=0;n<l;n++) result *= (*q)[3][row];
  339.    return result;
  340. }
  341.  
  342. /* Using the transformation matrix q, transform the general polynomial
  343.    equation given by a. */
  344.  
  345. static void transform(order, Coeffs, q)
  346. int order;
  347. DBL *Coeffs;
  348. MATRIX *q;
  349. {
  350.    int term_index, partial_index;
  351.    int ip, i, i0, i1, i2, i3;
  352.    int jp, j, j0, j1, j2, j3;
  353.    int kp, k, k0, k1, k2, k3;
  354.    int wp;
  355.    DBL *b, partial_term;
  356.    DBL tempx, tempy, tempz;
  357.  
  358.    for (i=0;i<4;i++) for (j=0;j<4;j++)
  359.       if ((*q)[i][j] > -COEFF_LIMIT && (*q)[i][j] < COEFF_LIMIT)
  360.          (*q)[i][j] = 0.0;
  361.    if ((b = (DBL *)malloc(term_counts[order] * sizeof(DBL))) == NULL) {
  362.       printf("Cannot allocate memory for b in poly transform()\n");
  363.       exit(1);
  364.    }
  365.    for (i=0;i<term_counts[order];i++)
  366.       b[i] = 0.0;
  367.    for (term_index=0;term_index<term_counts[order];term_index++) {
  368.       if (Coeffs[term_index] != 0.0) {
  369.          unroll(order, term_index, &ip, &jp, &kp, &wp);
  370.          /* Step through terms in: (q[0][0]*x+q[0][1]*y+q[0][2]*z+q[0][3])^i */
  371.          for (i=0;i<term_counts[ip];i++) {
  372.             unroll(ip, i, &i0, &i1, &i2, &i3);
  373.             tempx = do_partial_term(q, 0, ip, i0, i1, i2, i3);
  374.             if (tempx != 0.0) {
  375.  
  376.                /* Step through terms in:
  377.             (q[1][0]*x+q[1][1]*y+q[1][2]*z+q[1][3])^j */
  378.                for (j=0;j<term_counts[jp];j++) {
  379.                   unroll(jp, j, &j0, &j1, &j2, &j3);
  380.                   tempy = do_partial_term(q, 1, jp, j0, j1, j2, j3);
  381.                   if (tempy != 0.0) {
  382.  
  383.                      /* Step through terms in:
  384.                   (q[2][0]*x+q[2][1]*y+q[2][2]*z+q[2][3])^k */
  385.                      for (k=0;k<term_counts[kp];k++) {
  386.                         unroll(kp, k, &k0, &k1, &k2, &k3);
  387.                         tempz = do_partial_term(q, 2, kp, k0, k1, k2, k3);
  388.                         if (tempz != 0.0) {
  389.                            /* Figure out it's index, and add into result */
  390.                            partial_index=roll(order,i0+j0+k0,i1+j1+k1,i2+j2+k2);
  391.                            partial_term=Coeffs[term_index]*tempx*tempy*tempz;
  392.                            b[partial_index] += partial_term;
  393.                         }
  394.                      }
  395.                   }
  396.                }
  397.             }
  398.          }
  399.       }
  400.    }
  401.    for (i=0;i<term_counts[order];i++)
  402.       if (b[i] > -1.0e-4 && b[i] < 1.0e-4)
  403.          Coeffs[i] = 0.0;
  404.       else
  405.          Coeffs[i] = b[i];
  406.    free(b);
  407.    /*show_poly("New poly: ", order, Coeffs);
  408. printf("\n");
  409. */
  410. }
  411.  
  412. /* Intersection of a ray and a quartic */
  413. static int intersect_quartic(Ray, Shape, Depths)
  414. RAY *Ray;
  415. POLY *Shape;
  416. DBL *Depths;
  417. {
  418.    DBL x,y,z,x2,y2,z2,x3,y3,z3,x4,y4,z4;
  419.    DBL xx,yy,zz,xx2,yy2,zz2,xx3,yy3,zz3,xx4,yy4,zz4;
  420.    DBL *a, t[5];
  421.    DBL x_z,x_zz,xx_z,xx_zz,x_y,x_yy,xx_y,xx_yy,y_z,y_zz,yy_z,yy_zz,temp;
  422.  
  423.    x = Ray->Initial.x;
  424.    y = Ray->Initial.y;
  425.    z = Ray->Initial.z;
  426.    xx = Ray->Direction.x;
  427.    yy = Ray->Direction.y;
  428.    zz = Ray->Direction.z;
  429.    x2 = x * x;  y2 = y * y;  z2 = z * z;
  430.    x3 = x * x2; y3 = y * y2; z3 = z * z2;
  431.    x4 = x * x3; y4 = y * y3; z4 = z * z3;
  432.    xx2 = xx * xx;  yy2 = yy * yy;  zz2 = zz * zz;
  433.    xx3 = xx * xx2; yy3 = yy * yy2; zz3 = zz * zz2;
  434.    xx4 = xx * xx3; yy4 = yy * yy3; zz4 = zz * zz3;
  435.    a = Shape->Coeffs;
  436.    x_z = x * z; x_zz = x * zz; xx_z = xx * z; xx_zz = xx * zz;
  437.    x_y = x * y; x_yy = x * yy; xx_y = xx * y; xx_yy = xx * yy;
  438.    y_z = y * z; y_zz = y * zz; yy_z = yy * z; yy_zz = yy * zz;
  439.  
  440.    /*
  441.       Determine the coefficients of t^n, where the line is represented
  442.       as (x,y,z) + (xx,yy,zz)*t.
  443.    */
  444.    temp =  a[ 0]*xx4;
  445.    temp += a[ 1]*xx3*yy;
  446.    temp += a[ 2]*xx3*zz;
  447.    temp += a[ 4]*xx2*yy2;
  448.    temp += a[ 5]*xx2*yy_zz;
  449.    temp += a[ 7]*xx2*zz2;
  450.    temp += a[10]*xx*yy3;
  451.    temp += a[11]*xx_zz*yy2;
  452.    temp += a[13]*xx_yy*zz2;
  453.    temp += a[16]*xx*zz3;
  454.    temp += a[20]*yy4;
  455.    temp += a[21]*yy3*zz;
  456.    temp += a[23]*yy2*zz2;
  457.    temp += a[26]*yy*zz3;
  458.    temp += a[30]*zz4;
  459.  
  460.    t[0] = temp;
  461.  
  462.    temp = 4*a[ 0]*x*xx3;
  463.    temp += a[ 1]*(3*xx2*x_yy+xx3*y);
  464.    temp += a[ 2]*(3*xx2*x_zz+xx3*z);
  465.    temp += a[ 3]*xx3;
  466.    temp += a[ 4]*(2*x*xx*yy2+2*xx2*y*yy);
  467.    temp += a[ 5]*(xx2*(y_zz+yy_z)+2*x_yy*xx_zz);
  468.    temp += a[ 6]*xx2*yy;
  469.    temp += a[ 7]*(2*x*xx*zz2+2*xx2*z*zz);
  470.    temp += a[ 8]*xx2*zz;
  471.    temp += a[10]*(x*yy3+3*xx_y*yy2);
  472.    temp += a[11]*(xx*(2*y*yy_zz+yy2*z)+x_zz*yy2);
  473.    temp += a[12]*xx*yy2;
  474.    temp += a[13]*(xx*(y*zz2+2*yy_z*zz)+x_yy*zz2);
  475.    temp += a[14]*xx_yy*zz;
  476.    temp += a[16]*(x*zz3+3*xx_z*zz2);
  477.    temp += a[17]*xx*zz2;
  478.    temp += 4*a[20]*y*yy3;
  479.    temp += a[21]*(3*yy2*y_zz+yy3*z);
  480.    temp += a[22]*yy3;
  481.    temp += zz*(2*a[23]*yy*(y_zz+yy_z)+
  482.       a[24]*yy2+
  483.       zz*(a[26]*(y_zz+3*yy_z)+
  484.       a[27]*yy+zz*(4*a[30]*z+a[31])));
  485.    t[1] = temp;
  486.  
  487.    temp = 6*a[ 0]*x2*xx2;
  488.    temp += 3*a[ 1]*x*xx*(x_yy+xx_y);
  489.    temp += 3*a[ 2]*x*xx*(x_zz+xx_z);
  490.    temp += 3*a[ 3]*x*xx2;
  491.    temp += a[ 4]*(x2*yy2+4*x_yy*xx_y+xx2*y2);
  492.    temp += a[ 5]*(x2*yy_zz+2*x*xx*(y_zz+yy_z)+xx2*y_z);
  493.    temp += a[ 6]*(2*x*xx_yy+xx2*y);
  494.    temp += a[ 7]*(x2*zz2+4*x_zz*xx_z+xx2*z2);
  495.    temp += a[ 8]*(2*x*xx_zz+xx2*z);
  496.    temp += a[ 9]*xx2;
  497.    temp += a[10]*(3*x_y*yy2+3*xx_yy*y2);
  498.    temp += a[11]*(x_yy*(2*y_zz+yy_z)+xx*(y2*zz+2*y*yy_z));
  499.    temp += a[12]*(x*yy2+2*xx_y*yy);
  500.    temp += a[13]*(x_zz*(y_zz+2*yy_z)+xx*(2*y_z*zz+yy*z2));
  501.    temp += a[14]*(x_yy*zz+xx*(y_zz+yy_z));
  502.    temp += a[15]*xx_yy;
  503.    temp += a[16]*(3*x_z*zz2+3*xx_zz*z2);
  504.    temp += a[17]*(x*zz2+2*xx_z*zz);
  505.    temp += a[18]*xx_zz;
  506.    temp += 6*a[20]*y2*yy2;
  507.    temp += 3*a[21]*y*yy*(y_zz+yy_z);
  508.    temp += 3*a[22]*y*yy2;
  509.    temp += a[23]*(y2*zz2+4*y_zz*yy_z+yy2*z2);
  510.    temp += a[24]*(2*y*yy_zz+yy2*z);
  511.    temp += a[25]*yy2;
  512.    temp += zz*(3*a[26]*z*(y_zz+yy_z)+
  513.       a[27]*(y_zz+2*yy_z)+
  514.       a[28]*yy+
  515.       6*a[30]*z2*zz+
  516.       3*a[31]*z*zz+
  517.       a[32]*zz);
  518.    t[2] = temp;
  519.  
  520.    temp = 4*a[ 0]*x3*xx;
  521.    temp += a[ 1]*x2*(x_yy+3*xx_y);
  522.    temp += a[ 2]*x2*(x_zz+3*xx_z);
  523.    temp += 3*a[ 3]*x2*xx;
  524.    temp += 2*a[ 4]*x_y*(x_yy+xx_y);
  525.    temp += a[ 5]*x*(x*(y_zz+yy_z)+2*xx_y*z);
  526.    temp += a[ 6]*x*(x_yy+2*xx_y);
  527.    temp += 2*a[ 7]*x_z*(x_zz+xx_z);
  528.    temp += a[ 8]*x*(x_zz+2*xx_z);
  529.    temp += 2*a[ 9]*x*xx;
  530.    temp += a[10]*(3*x_yy*y2-xx*y3);
  531.    temp += a[11]*(x_y*(y_zz+2*yy_z)+xx_z*y2);
  532.    temp += a[12]*(2*x_y*yy+xx*y2);
  533.    temp += a[13]*(x_z*(2*y_zz+yy_z)+xx_y*z2);
  534.    temp += a[14]*(x*(y_zz+yy_z)+xx_y*z);
  535.    temp += a[15]*(x_yy+xx_y);
  536.    temp += a[16]*(3*x_zz*z2+xx*z3);
  537.    temp += a[17]*(2*x_z*zz+xx*z2);
  538.    temp += a[18]*(x_zz+xx_z);
  539.    temp += a[19]*xx;
  540.    temp += 4*a[20]*y3*yy;
  541.    temp += a[21]*y2*(y_zz+3*yy_z);
  542.    temp += 3*a[22]*y2*yy;
  543.    temp += 2*a[23]*y_z*(y_zz+yy_z);
  544.    temp += a[24]*y*(y_zz+2*yy_z);
  545.    temp += 2*a[25]*y*yy;
  546.    temp += a[26]*(3*y_zz*z2+yy*z3);
  547.    temp += a[27]*(2*y_z*zz+yy*z2);
  548.    temp += a[28]*(y_zz+yy_z);
  549.    temp += a[29]*yy;
  550.    temp += zz*(4*a[30]*z3+3*a[31]*z2+2*a[32]*z+a[33]);
  551.    t[3] = temp;
  552.  
  553.    temp = a[ 0]*x4;
  554.    temp += a[ 1]*x3*y;
  555.    temp += a[ 2]*x3*z;
  556.    temp += a[ 3]*x3;
  557.    temp += a[ 4]*x2*y2;
  558.    temp += a[ 5]*x2*y_z;
  559.    temp += a[ 6]*x2*y;
  560.    temp += a[ 7]*x2*z2;
  561.    temp += a[ 8]*x2*z;
  562.    temp += a[ 9]*x2;
  563.    temp += a[10]*x*y3;
  564.    temp += a[11]*x*y2*z;
  565.    temp += a[12]*x*y2;
  566.    temp += a[13]*x_y*z2;
  567.    temp += a[14]*x_y*z;
  568.    temp += a[15]*x_y;
  569.    temp += a[16]*x*z3;
  570.    temp += a[17]*x*z2;
  571.    temp += a[18]*x_z;
  572.    temp += a[19]*x;
  573.    temp += a[20]*y4;
  574.    temp += a[21]*y3*z;
  575.    temp += a[22]*y3;
  576.    temp += a[23]*y2*z2;
  577.    temp += a[24]*y2*z;
  578.    temp += a[25]*y2;
  579.    temp += a[26]*y*z3;
  580.    temp += a[27]*y*z2;
  581.    temp += a[28]*y_z;
  582.    temp += a[29]*y;
  583.    temp += a[30]*z4;
  584.    temp += a[31]*z3;
  585.    temp += a[32]*z2;
  586.    temp += a[33]*z;
  587.    temp += a[34];
  588.    t[4] = temp;
  589.  
  590.    if (Shape->Sturm_Flag)
  591.       if (t[0] == 0.0)
  592.          if (t[1] == 0.0)
  593.             return solve_quadratic(&t[2], Depths);
  594.          else
  595.             return polysolve(3, &t[1], Depths);
  596.       else
  597.          return polysolve(4, &t[0], Depths);
  598.    else
  599.       return solve_quartic(&t[0], Depths);
  600. }
  601.  
  602. #ifdef TEST
  603. /* Normal to a quartic */
  604. static void quartic_normal(Result, Object, Intersection_Point)
  605. VECTOR *Result, *Intersection_Point;
  606. OBJECT *Object;
  607. {
  608.    POLY *Shape = (POLY *) Object;
  609.    DBL *a,x,y,z,x2,y2,z2,x3,y3,z3,temp;
  610.  
  611.    a = Shape->Coeffs;
  612.    x = Intersection_Point->x;
  613.    y = Intersection_Point->y;
  614.    z = Intersection_Point->z;
  615.    x2 = x * x;  y2 = y * y;  z2 = z * z;
  616.    x3 = x * x2; y3 = y * y2; z3 = z * z2;
  617.  
  618.    temp = a[ 4]*y2+y*(a[ 5]*z+a[ 6])+a[ 7]*z2+a[ 8]*z+a[ 9];
  619.    Result->x = 4*a[ 0]*x3+3*x2*(a[ 1]*y+a[ 2]*z+a[ 3])+
  620.    2*x*(temp)+
  621.    a[10]*y3+y2*(a[11]*z+a[12])+y*(a[13]*z2+a[14]*z+a[15])+
  622.    a[16]*z3+a[17]*z2+a[18]*z+a[19];
  623.  
  624.    temp = 3*a[10]*y2+2*y*(a[11]*z+a[12])+a[13]*z2+a[14]*z+a[15];
  625.    Result->y = a[ 1]*x3+x2*(2*a[ 4]*y+a[ 5]*z+a[ 6])+
  626.    x*(temp)+
  627.    4*a[20]*y3+3*y2*(a[21]*z+a[22])+2*y*(a[23]*z2+a[24]*z+a[25])+
  628.    a[26]*z3+a[27]*z2+a[28]*z+a[29];
  629.  
  630.    temp = a[11]*y2+y*(2*a[13]*z+a[14])+3*a[16]*z2+2*a[17]*z+a[18];
  631.    Result->z = a[ 2]*x3+x2*(a[ 5]*y+2*a[ 7]*z+a[ 8])+
  632.    x*(temp)+
  633.    a[21]*y3+y2*(2*a[23]*z+a[24])+y*(3*a[26]*z2+2*a[27]*z+a[28])+
  634.    4*a[30]*z3+3*a[31]*z2+2*a[32]*z+a[33];
  635.  
  636.    VTemp=Result->x * Result->x + Result->y * Result->y + Result->z * Result->z;
  637.    VTemp=sqrt(VTemp);
  638.    if (VTemp > 0.0) {
  639.       Result->x /= VTemp;
  640.       Result->y /= VTemp;
  641.       Result->z /= VTemp;
  642.    }
  643.    else {
  644.       Result->x = 1.0;
  645.       Result->y = 0.0;
  646.       Result->z = 0.0;
  647.    }
  648. }
  649. #endif
  650.  
  651. /* Normal to a quartic */
  652. static void quartic_normal(Result, Object, Intersection_Point)
  653. VECTOR *Result, *Intersection_Point;
  654. OBJECT *Object;
  655. {
  656.    POLY *Shape = (POLY *) Object;
  657.    DBL *a,x,y,z,x2,y2,z2,x3,y3,z3;
  658.  
  659.    a = Shape->Coeffs;
  660.    x = Intersection_Point->x;
  661.    y = Intersection_Point->y;
  662.    z = Intersection_Point->z;
  663.    x2 = x * x;  y2 = y * y;  z2 = z * z;
  664.    x3 = x * x2; y3 = y * y2; z3 = z * z2;
  665.  
  666.    Result->x = 4*a[ 0]*x3+3*x2*(a[ 1]*y+a[ 2]*z+a[ 3])+
  667.    2*x*(a[ 4]*y2+y*(a[ 5]*z+a[ 6])+a[ 7]*z2+a[ 8]*z+a[ 9])+
  668.    a[10]*y3+y2*(a[11]*z+a[12])+y*(a[13]*z2+a[14]*z+a[15])+
  669.    a[16]*z3+a[17]*z2+a[18]*z+a[19];
  670.  
  671.    Result->y = a[ 1]*x3+x2*(2*a[ 4]*y+a[ 5]*z+a[ 6])+
  672.    x*(3*a[10]*y2+2*y*(a[11]*z+a[12])+a[13]*z2+a[14]*z+a[15])+
  673.    4*a[20]*y3+3*y2*(a[21]*z+a[22])+2*y*(a[23]*z2+a[24]*z+a[25])+
  674.    a[26]*z3+a[27]*z2+a[28]*z+a[29];
  675.  
  676.    Result->z = a[ 2]*x3+x2*(a[ 5]*y+2*a[ 7]*z+a[ 8])+
  677.    x*(a[11]*y2+y*(2*a[13]*z+a[14])+3*a[16]*z2+2*a[17]*z+a[18])+
  678.    a[21]*y3+y2*(2*a[23]*z+a[24])+y*(3*a[26]*z2+2*a[27]*z+a[28])+
  679.    4*a[30]*z3+3*a[31]*z2+2*a[32]*z+a[33];
  680.    VTemp = sqrt(Result->x*Result->x+Result->y*Result->y+Result->z*Result->z);
  681.    if (VTemp > 0.0) {
  682.       Result->x /= VTemp;
  683.       Result->y /= VTemp;
  684.       Result->z /= VTemp;
  685.    }
  686.    else {
  687.       Result->x = 1.0;
  688.       Result->y = 0.0;
  689.       Result->z = 0.0;
  690.    }
  691. }
  692.  
  693. int Inside_Poly (Test_Point, Object)
  694. VECTOR *Test_Point;
  695. OBJECT *Object;
  696. {
  697.    VECTOR New_Point;
  698.    POLY *Shape = (POLY *) Object;
  699.    DBL Result;
  700.  
  701.    /* Transform the point into polynomial's space */
  702.    if (Shape->Transform != NULL)
  703.       MInverseTransformVector(&New_Point, Test_Point, Shape->Transform);
  704.    else
  705.       New_Point = *Test_Point;
  706.  
  707.    Result = inside(&New_Point, Shape->Order, Shape->Coeffs);
  708.    if (Result < Small_Tolerance)
  709.       return ((int)(1-Shape->Inverted));
  710.    else
  711.       return ((int)Shape->Inverted);
  712. }
  713.  
  714. /* Normal to a polynomial */
  715. void Poly_Normal(Result, Object, Intersection_Point)
  716. VECTOR *Result, *Intersection_Point;
  717. OBJECT *Object;
  718. {
  719.    POLY *Shape = (POLY *) Object;
  720.    VECTOR New_Point;
  721.  
  722.    /* Transform the point into the polynomials space */
  723.    if (Shape->Transform != NULL)
  724.       MInverseTransformVector(&New_Point, Intersection_Point, Shape->Transform);
  725.    else {
  726.       New_Point.x = Intersection_Point->x;
  727.       New_Point.y = Intersection_Point->y;
  728.       New_Point.z = Intersection_Point->z;
  729.    }
  730.  
  731.       if (Shape->Order == 4)
  732.          quartic_normal(Result, Object, &New_Point);
  733.       else
  734.          normalp(Result, Shape->Order, Shape->Coeffs, &New_Point);
  735.  
  736.    /* Transform back to world space */
  737.    if (Shape->Transform != NULL)
  738.       MTransNormal(Result, Result, Shape->Transform);
  739.    VNormalize(*Result, *Result);
  740. }
  741.  
  742. /* Make a copy of a polynomial object */
  743. void *Copy_Poly(Object)
  744. OBJECT *Object;
  745. {
  746.    POLY *Shape = (POLY *)Object;
  747.    POLY *New_Shape = Get_Poly_Shape(Shape->Order);
  748.    int i;
  749.  
  750.    New_Shape->Shape_Texture = Shape->Shape_Texture;
  751.    New_Shape->Shape_Colour = Shape->Shape_Colour;
  752.    New_Shape->Next_Object = NULL;
  753.    New_Shape->Sturm_Flag = Shape->Sturm_Flag;
  754.    New_Shape->Inverted = Shape->Inverted;
  755.  
  756.    /* Copy any associated transformation */
  757.    if (Shape->Transform != NULL) {
  758.       New_Shape->Transform = Get_Transformation();
  759.       memcpy(New_Shape->Transform, Shape->Transform, sizeof(TRANSFORMATION));
  760.    }
  761.    for (i=0;i<term_counts[New_Shape->Order];i++)
  762.       New_Shape->Coeffs[i] = Shape->Coeffs[i];
  763.  
  764.    /* Copy any associated texture */
  765.    if (Shape->Shape_Texture != NULL)
  766.       New_Shape->Shape_Texture = Copy_Texture (Shape->Shape_Texture);
  767.  
  768.    return (void *)(New_Shape);
  769. }
  770.  
  771. void Translate_Poly (Object, Vector)
  772. OBJECT *Object;
  773. VECTOR *Vector;
  774. {
  775.    TRANSFORMATION Transform;
  776.    POLY *Shape = (POLY *)Object;
  777.    if (Shape->Transform == NULL)
  778.       Shape->Transform = Get_Transformation();
  779.    Get_Translation_Transformation(&Transform, Vector);
  780.    Compose_Transformations(Shape->Transform, &Transform);
  781.  
  782.    Translate_Texture (&Shape->Shape_Texture, Vector);
  783. }
  784.  
  785. void Rotate_Poly (Object, Vector)
  786. OBJECT *Object;
  787. VECTOR *Vector;
  788. {
  789.    TRANSFORMATION Transform;
  790.    POLY *Shape = (POLY *)Object;
  791.    if (Shape->Transform == NULL)
  792.       Shape->Transform = Get_Transformation();
  793.    Get_Rotation_Transformation(&Transform, Vector);
  794.    Compose_Transformations(Shape->Transform, &Transform);
  795.  
  796.    Rotate_Texture (&Shape->Shape_Texture, Vector);
  797. }
  798.  
  799. void Scale_Poly (Object, Vector)
  800. OBJECT *Object;
  801. VECTOR *Vector;
  802. {
  803.    TRANSFORMATION Transform;
  804.    POLY *Shape = (POLY *)Object;
  805.    if (Shape->Transform == NULL)
  806.       Shape->Transform = Get_Transformation();
  807.    Get_Scaling_Transformation(&Transform, Vector);
  808.    Compose_Transformations(Shape->Transform, &Transform);
  809.  
  810.    Scale_Texture (&Shape->Shape_Texture, Vector);
  811. }
  812.  
  813. void Invert_Poly (Object)
  814. OBJECT *Object;
  815. {
  816.    ((POLY *) Object)->Inverted = 1 - ((POLY *)Object)->Inverted;
  817. }
  818.