home *** CD-ROM | disk | FTP | other *** search
/ gondwana.ecr.mu.oz.au/pub/ / Graphics.tar / Graphics / atomart.tar.gz / atomart.tar / poly.c < prev    next >
C/C++ Source or Header  |  1990-06-23  |  5KB  |  278 lines

  1. #include <math.h>
  2. #include <stdio.h>
  3. #include "atomart.h"
  4. #include "macro.h"
  5. #include "gram.h"
  6.  
  7. extern attr    *astackp;
  8. extern hlist    *fhlist;
  9.  
  10. extern matrix    trans;
  11.  
  12. /*
  13.  * polygoni
  14.  *
  15.  *    returns the intersection point between the ray r and the polygon
  16.  * in o.
  17.  */
  18. hlist *
  19. polygoni(r, o)
  20.     ray    *r;
  21.     object    *o;
  22. {
  23.     register float        t;
  24.     register polygon    *poly;
  25.     register edge        *e;
  26.     hlist            *hp;
  27.     vector            v;
  28.  
  29.     poly = o->u.ply;
  30.  
  31.     hp = (hlist *)NULL;
  32.         
  33.     t = dprod(poly->n, r->dir);
  34.  
  35.     if (t == 0.0)
  36.         return((hlist *)NULL);
  37.  
  38.     t = -(dprod(poly->n, r->org) + poly->cnst) / t;
  39.  
  40.     if (t < TOLERANCE)
  41.         return((hlist *)NULL);
  42.  
  43.     v.x = r->org.x + t * r->dir.x;
  44.     v.y = r->org.y + t * r->dir.y;
  45.     v.z = r->org.z + t * r->dir.z;
  46.  
  47.     for (e = poly->edges; e != (edge *)NULL; e = e->nxt) 
  48.         if ((dprod(e->n, v) + e->cnst) > 0.0)
  49.             break;
  50.  
  51.     if (e == (edge *)NULL) {
  52.         fetch(hp);
  53.         hp->t = t;
  54.         hp->obj = o;
  55.         hp->nxt = (hlist *)NULL;
  56.     }
  57.  
  58.     return(hp);
  59. }
  60.  
  61. /*
  62.  * polygonn
  63.  *
  64.  *    returns the normal to a polygon with index number indx
  65.  */
  66. void
  67. polygonn(n, l, o)
  68.     vector    *n, *l;
  69.     object    *o;
  70. {
  71.     *n = o->u.ply->n;
  72. }
  73.  
  74. /*
  75.  * getaxis
  76.  *
  77.  *    get the major axis of v.
  78.  */
  79. int
  80. getaxis(v)
  81.     vector    v;
  82. {
  83.     int    axis;
  84.  
  85.     if (fabs(v.x) > fabs(v.y))
  86.         if (fabs(v.x) > fabs(v.z))
  87.             axis = XAXIS;
  88.         else
  89.             axis = ZAXIS;
  90.     else
  91.         if (fabs(v.y) > fabs(v.z))
  92.             axis = YAXIS;
  93.         else
  94.             axis = ZAXIS;
  95.  
  96.     return(axis);
  97. }
  98.  
  99. /*
  100.  * polygonc
  101.  *
  102.  *    returns the colour of polygon o at point l
  103.  */
  104. void
  105. polygonc(o, txt, l, n, pcol, type)
  106.     object  *o;
  107.     texture *txt;
  108.     vector  *l, *n;
  109.     pixel   *pcol;
  110.     int     type;
  111. {
  112.     int    indx, w, h;
  113.     vector    loc, tmp;
  114.     float    xlensq, ylensq, zlensq;
  115.  
  116.     totexture(txt, loc, *l);
  117.  
  118.     xlensq = (loc.x - txt->vref1.x) * (loc.x - txt->vref1.x);
  119.     ylensq = (loc.y - txt->vref1.y) * (loc.y - txt->vref1.y);
  120.     zlensq = (loc.z - txt->vref1.z) * (loc.z - txt->vref1.z);
  121.  
  122.     switch (txt->axis) {
  123.     case XAXIS:
  124.         w = sqrt((double)(zlensq + xlensq)) * txt->scalew;
  125.         h = sqrt((double)(ylensq + xlensq)) * txt->scaleh;
  126.         break;
  127.     case YAXIS:
  128.         w = sqrt((double)(xlensq + ylensq)) * txt->scalew;
  129.         h = sqrt((double)(zlensq + ylensq)) * txt->scaleh;
  130.         break;
  131.     case ZAXIS:
  132.         w = sqrt((double)(xlensq + zlensq)) * txt->scalew;
  133.         h = sqrt((double)(ylensq + zlensq)) * txt->scaleh;
  134.         break;
  135.     default:
  136.         fatal("atomart: bad axis in polyc.\n");
  137.     }
  138.  
  139.     indx = (w % txt->pixw + (h % txt->pixh) * txt->pixw) * 3;
  140.  
  141.     pcol->r = (unsigned char)txt->map[indx] / 255.0;
  142.     pcol->g = (unsigned char)txt->map[indx + 1] / 255.0;
  143.     pcol->b = (unsigned char)txt->map[indx + 2] / 255.0;
  144. }
  145.  
  146. /*
  147.  * polygoninit
  148.  *
  149.  *    initialise the function pointers and fields for a polygon
  150.  */
  151. object *
  152. polygoninit(d)
  153.     details *d;
  154. {
  155.     object        *o;
  156.     polygon        *poly;
  157.     int        i, count;
  158.     matrix        m;
  159.     tlist        *tl;
  160.     vector        v, v1, v2, ovt[MAXVERTS], vt[MAXVERTS];
  161.     float        maxx, maxy, maxz, minx, miny, minz;
  162.     float        xlensq, ylensq, zlensq;
  163.     edge        *e;
  164.     details        *ld;
  165.  
  166.     o = (object *)smalloc(sizeof(object));
  167.     o->type = POLYGON;
  168.     o->normal = polygonn;
  169.     o->intersects = polygoni;
  170.  
  171.     setattributes(o);
  172.  
  173.     mmult4(m, trans, astackp->m);
  174.  
  175.     poly = o->u.ply = (polygon *)smalloc(sizeof(polygon));
  176.  
  177.     count = 0;
  178.     while (d != (details *)NULL) {
  179.         switch (d->type) {
  180.         case VERTEX:
  181.                     /* transform vertex into ray space */
  182.             ovt[count] = d->u.v;
  183.             d->u.v.x -= m[3][0];
  184.             d->u.v.y -= m[3][1];
  185.             d->u.v.z -= m[3][2];
  186.             v3x3tmult(vt[count], d->u.v, m);
  187.             vt[count].x /= astackp->scales.x;
  188.             vt[count].y /= astackp->scales.y;
  189.             vt[count].z /= astackp->scales.z;
  190.             count++;
  191.             break;
  192.         default:
  193.             warning("atomart: illegal field in polygon ignored.\n");
  194.         }
  195.         ld = d;
  196.         d = d->nxt;
  197.         free(ld);
  198.     }
  199.  
  200.     vsub(v1, vt[0], vt[1]);
  201.     vsub(v2, vt[0], vt[count - 1]);
  202.  
  203.     xprod(poly->n, v1, v2);
  204.  
  205.     normalise(poly->n);
  206.  
  207.     poly->cnst = -dprod(poly->n, vt[0]);
  208.  
  209.     poly->edges = (edge *)NULL;
  210.  
  211.     for (i = 0; i != count; i++) {
  212.         e = (edge *)smalloc(sizeof(edge));
  213.         v.x = vt[(i + 1) % count].x - vt[i].x;
  214.         v.y = vt[(i + 1) % count].y - vt[i].y;
  215.         v.z = vt[(i + 1) % count].z - vt[i].z;
  216.         xprod(e->n, v, poly->n);
  217.         normalise(e->n);
  218.         e->cnst = -dprod(e->n, vt[i]);
  219.         e->nxt = poly->edges;
  220.         poly->edges = e;
  221.     }
  222.  
  223.     minx = maxx = ovt[0].x;
  224.     miny = maxy = ovt[0].y;
  225.     minz = maxz = ovt[0].z;
  226.  
  227.     for (i = 1; i != count; i++) {
  228.         minmax(minx, maxx, ovt[i].x);
  229.         minmax(miny, maxy, ovt[i].y);
  230.         minmax(minz, maxz, ovt[i].z);
  231.     }
  232.  
  233.     for (tl = o->s.txtlist; tl != (tlist *)NULL; tl = tl->nxt) {
  234.         if (tl->txtcol == (void (*)())NULL) {
  235.  
  236.             tl->txtcol = polygonc;
  237.  
  238.             /*
  239.              * find major axis of polygon normal
  240.              */
  241.             vsub(v1, ovt[0], ovt[1]);
  242.             vsub(v2, ovt[0], ovt[count - 1]);
  243.  
  244.             xprod(v, v1, v2);
  245.  
  246.             tl->txt.axis = getaxis(v);
  247.  
  248.             tl->txt.vref1 = ovt[count - 1];
  249.  
  250.             /*
  251.              * adjust scale so relative to 0 to 1
  252.              */
  253.             xlensq = (minx - maxx) * (minx - maxx);
  254.             ylensq = (miny - maxy) * (miny - maxy);
  255.             zlensq = (minz - maxz) * (minz - maxz);
  256.  
  257.             switch (tl->txt.axis) {
  258.             case XAXIS:
  259.                 tl->txt.scalew /= sqrt((double)(zlensq + xlensq));
  260.                 tl->txt.scaleh /= sqrt((double)(ylensq + xlensq));
  261.                 break;
  262.             case YAXIS:
  263.                 tl->txt.scalew /= sqrt((double)(xlensq + ylensq));
  264.                 tl->txt.scaleh /= sqrt((double)(zlensq + ylensq));
  265.                 break;
  266.             case ZAXIS:
  267.                 tl->txt.scalew /= sqrt((double)(xlensq + zlensq));
  268.                 tl->txt.scaleh /= sqrt((double)(ylensq + zlensq));
  269.                 break;
  270.             default:
  271.                 fatal("atomart: bad axis in polygoninit.\n");
  272.             }
  273.         }
  274.     }
  275.  
  276.     return(o);
  277. }
  278.