home *** CD-ROM | disk | FTP | other *** search
/ gondwana.ecr.mu.oz.au/pub/ / Graphics.tar / Graphics / atomart.tar.gz / atomart.tar / sphere.c < prev    next >
C/C++ Source or Header  |  1990-06-28  |  4KB  |  228 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.  * spherei
  14.  *
  15.  *    returns the closest hit for the ray r and sphere o.
  16.  */
  17. hlist *
  18. spherei(r, o)
  19.     register ray    *r;
  20.     register object    *o;
  21. {
  22.     vector        c;
  23.     hlist        *hp;
  24.     register float    b, d;
  25.  
  26.     if (o->raynumber == r->raynumber) {
  27.         if (o->lastt != 0.0) {
  28.             fetch(hp);
  29.             hp->t = o->lastt;
  30.             hp->obj = o;
  31.             hp->nxt = (hlist *)NULL;
  32.             return(hp);
  33.         } else
  34.             return((hlist *)NULL);
  35.     }
  36.  
  37.     o->raynumber = r->raynumber;
  38.     o->lastt = 0.0;
  39.  
  40.     vsub(c, r->org, o->u.sph->cent);
  41.  
  42.     b = -dprod(c, r->dir);
  43.     d = b * b - (dprod(c, c) - o->u.sph->radsqu);
  44.  
  45.     if (d < 0.0 || b < 0.0)
  46.         return((hlist *)NULL);
  47.     
  48.     d = sqrt((double)d);
  49.  
  50.     fetch(hp);
  51.     hp->t = b - d;
  52.  
  53.     if (hp->t < TOLERANCE) {
  54.         hp->t = b + d;
  55.         if (hp->t < TOLERANCE) {
  56.             release(hp);
  57.             return((hlist *)NULL);
  58.         }
  59.     }
  60.  
  61.     hp->obj = o;
  62.     hp->nxt = (hlist *)NULL;
  63.  
  64.     o->lastt = hp->t;
  65.  
  66.     return(hp);
  67. }
  68.  
  69. /*
  70.  * spheren
  71.  *
  72.  *    returns the normal to the sphere s
  73.  */
  74. void
  75. spheren(n, l, o)
  76.     register vector    *n;
  77.     register vector    *l;
  78.     register object    *o;
  79. {
  80.     vsub(*n, *l, o->u.sph->cent);
  81.  
  82.     normalise(*n);
  83. }
  84.  
  85. /*
  86.  * spherec
  87.  *
  88.  *    return the color of a sphere o at a the intersection point l.
  89.  *
  90.  */
  91. void
  92. spherec(o, txt, l, n, pcol, type)
  93.     object    *o;
  94.     texture    *txt;
  95.     vector    *l, *n;
  96.     pixel    *pcol;
  97.     int    type;
  98. {
  99.     vector    tmp, loc;
  100.     float    t, u, v, theta, phi;
  101.     int    w, h, indx;
  102.  
  103.     totexture(txt, loc, *l);
  104.  
  105.     t = -dprod(loc, txt->vref1);
  106.  
  107.     if (fabs(t) > 1.0)        /* precision check */
  108.         t = (t < 0.0) ? -1.0 : 1.0;
  109.  
  110.     phi = acos(t);
  111.  
  112.     v = phi / M_PI;
  113.  
  114.     if (v != 0.0 && v != 1.0) {
  115.         t = dprod(txt->vref2, loc) / sin(phi); 
  116.  
  117.         if (fabs(t) > 1.0)        /* precision check */
  118.             t = (t < 0.0) ? -1.0 : 1.0;
  119.  
  120.         theta = acos(t) / (2 * M_PI);
  121.  
  122.         xprod(tmp, txt->vref1, txt->vref2)
  123.  
  124.         if (dprod(tmp, loc) > 0)
  125.             u = theta;
  126.         else
  127.             u = 1 - theta;
  128.     } else
  129.         u = 0.0;
  130.  
  131.     w = u * txt->scalew;
  132.     h = v * txt->scaleh;
  133.  
  134.     indx = (w % txt->pixw + (h % txt->pixh) * txt->pixw) * 3;
  135.  
  136.     pcol->r = (unsigned char)txt->map[indx] / 255.0;
  137.     pcol->g = (unsigned char)txt->map[indx + 1] / 255.0;
  138.     pcol->b = (unsigned char)txt->map[indx + 2] / 255.0;
  139. }
  140.  
  141. /*
  142.  * sphereinit
  143.  *
  144.  *    initialise the function pointers and fields for a sphere object,
  145.  * returning its pointer.
  146.  */
  147. object *
  148. sphereinit(d)
  149.     details *d;
  150. {
  151.     object    *o;
  152.     tlist    *tl;
  153.     details    *ld;
  154.     float    radius;
  155.     sphere    *s;
  156.     matrix    tmp;
  157.     vector    cent, v;
  158.  
  159.     o = (object *)smalloc(sizeof(object));
  160.     o->type = SPHERE;
  161.     o->intersects = spherei;
  162.     o->normal = spheren;
  163.  
  164.     o->raynumber = 0;
  165.     o->lastt = 0.0;
  166.  
  167.     o->u.sph = s = (sphere *)smalloc(sizeof(sphere));
  168.  
  169.     cent.x = cent.y = cent.z = 0.0;
  170.     radius = 1.0;
  171.  
  172.     while (d != (details *)NULL) {
  173.         switch (d->type) {
  174.         case CENTER:
  175.             cent = d->u.v;
  176.             break;
  177.         case RADIUS:
  178.             radius = d->u.f;
  179.             break;
  180.         default:
  181.             warning("atomart: illegal field in sphere ignored.\n");
  182.         }
  183.         ld = d;
  184.         d = d->nxt;
  185.         free(ld);
  186.     }
  187.  
  188.     cent.x /= astackp->scales.x;
  189.     cent.y /= astackp->scales.y;
  190.     cent.z /= astackp->scales.z;
  191.  
  192.     mmult4(tmp, trans, astackp->m);
  193.  
  194.     cent.x -= tmp[3][0];
  195.     cent.y -= tmp[3][1];
  196.     cent.z -= tmp[3][2];
  197.  
  198.     v3x3tmult(s->cent, cent, tmp);
  199.  
  200.     s->rad = radius * astackp->maxscale;
  201.     s->radsqu = s->rad * s->rad;
  202.  
  203.     objtranslate(cent.x, cent.y, cent.z);
  204.  
  205.     scale(radius, radius, radius);
  206.               
  207.     setattributes(o);
  208.  
  209.     for (tl = o->s.txtlist; tl != (tlist *)NULL; tl = tl->nxt)
  210.         if (tl->txtcol == (void (*)())NULL) {
  211.             if (!tl->txt.refset) {
  212.                 tl->txt.vref1.y = 1.0;
  213.                 tl->txt.vref1.x = tl->txt.vref1.z = 0.0;
  214.                 tl->txt.vref2.x = 1.0;
  215.                 tl->txt.vref2.y = tl->txt.vref2.z = 0.0;
  216.             }
  217.  
  218.             tl->txtcol = spherec;
  219.  
  220.             v3x3tmult(v, tl->txt.vref1, astackp->m);
  221.             tl->txt.vref1 = v;
  222.             v3x3tmult(v, tl->txt.vref2, astackp->m);
  223.             tl->txt.vref2 = v;
  224.         }
  225.  
  226.     return(o);
  227. }
  228.