home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / altsrcs / 2 / 2213 / hsphere.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-12-28  |  4.4 KB  |  261 lines

  1.  
  2. /*
  3.  * hsphere.c - This module contain all of the code that relates to
  4.  *             hallow spheres.
  5.  *
  6.  * Copyright (C) 1990, Kory Hamzeh
  7.  */
  8.  
  9. #include <stdio.h>
  10. #include <malloc.h>
  11. #include <math.h>
  12.  
  13. #include "rt.h"
  14. #include "externs.h"
  15.  
  16.  
  17. int Hsphere_intersect(), Hsphere_normal();
  18.  
  19.  
  20. /*
  21.  * Build_hsphere()
  22.  *
  23.  * Given some info on a sphere object, build a complete object stucture.
  24.  */
  25.  
  26. Build_hsphere(s)
  27. HSPHERE *s;
  28. {
  29.     OBJECT *o;
  30.  
  31.     if(nobjects == MAX_PRIMS)
  32.     {
  33.     fprintf(stderr, "%s: too many objects specified\n", my_name);
  34.     exit(1);
  35.     }
  36.  
  37.     if((o = (OBJECT *) malloc(sizeof(OBJECT))) == NULL)
  38.     {
  39.     fprintf(stderr, "%s: malloc failed\n", my_name);
  40.     exit(1);
  41.     }
  42.  
  43.     s->radius2 = s->radius * s->radius;
  44.     s->i_radius2 = s->i_radius * s->i_radius;
  45.     
  46.     o->type = T_HSPHERE;
  47.     o->obj  = s;
  48.     o->surf = cur_surface;
  49.     o->inter = Hsphere_intersect;
  50.     o->normal = Hsphere_normal;
  51.  
  52.     objects[nobjects++] = o;
  53.  
  54.     /*
  55.      * Setup of bounding box for this puppy.
  56.      */
  57.  
  58.     o->b_min.x = s->center.x - s->radius;
  59.     o->b_min.y = s->center.y - s->radius;
  60.     o->b_min.z = s->center.z - s->radius;
  61.  
  62.     o->b_max.x = s->center.x + s->radius;
  63.     o->b_max.y = s->center.y + s->radius;
  64.     o->b_max.z = s->center.z + s->radius;
  65.     
  66. }
  67.  
  68.  
  69. /*
  70.  * Hsphere_intersect()
  71.  *
  72.  * Check given sphere for intersection with given ray. Return TRUE if
  73.  * an intersection takes place.
  74.  */
  75.  
  76. Hsphere_intersect(obj, ray, inter)
  77. OBJECT *obj;
  78. RAY *ray;
  79. INTERSECT *inter;
  80. {
  81.     HSPHERE *s;
  82.     VECTOR oc;
  83.     double l2oc, tca, t2hc, i_t2hc, disc, i_disc;
  84.     double t, i_t;
  85.     int which, inside1, inside2;
  86.     
  87.     s = obj->obj;
  88.  
  89.     /* calculate the origin to center vector */
  90.     
  91.     VecSub(s->center, ray->pos, oc);
  92.     l2oc = VecDot(oc, oc);
  93.  
  94.     /* find out the closest approach along the ray */
  95.     tca = VecDot(oc, ray->dir);
  96.     t2hc = s->radius2 - l2oc + (tca * tca);
  97.     i_t2hc = s->i_radius2 - l2oc + (tca * tca);
  98.     
  99.     /* if the discriminator < 0, then the ray will not hit */
  100.     if(t2hc < MIN_T)
  101.     {
  102.     if(i_t2hc < MIN_T)
  103.     {
  104.         return (0);            /* didn't hit either one */
  105.     }
  106.     else
  107.     {
  108.         which = 2;            /* hit the inside one    */
  109.     }
  110.     }
  111.     else
  112.     {
  113.     if(i_t2hc < MIN_T)        /* hit the outside one    */
  114.     {
  115.         which = 1;
  116.     }
  117.     else
  118.     {
  119.         which = 0;            /* don't know yet    */
  120.     }
  121.     }
  122.  
  123.     /* only find the sqrt root of the one we need */
  124.     switch(which)
  125.     {
  126.     case 0 :        /* damm it jim! We need both! */
  127.     disc = sqrt(t2hc);
  128.     i_disc = sqrt(i_t2hc);
  129.     if(l2oc > s->radius2 + MIN_T)
  130.     {
  131.         inside1 = 0;
  132.         t = tca - disc;
  133.     }
  134.     else
  135.     {
  136.         inside1 = 1;
  137.         t = tca + disc;
  138.     }
  139.     
  140.     /* reverse the inside flag for this one */
  141.     if(l2oc > s->i_radius2 + MIN_T)
  142.     {
  143.         inside2 = 1;
  144.         i_t = tca - i_disc;
  145.     }
  146.     else
  147.     {
  148.         inside2 = 0;
  149.         i_t = tca + i_disc;
  150.     }
  151.  
  152.     /*
  153.      * figure out which of the spheres we hit. If we have
  154.      * hit both, then take the close one.
  155.      */
  156.  
  157.     if(t < MIN_T)    /* didn't hit the outside one, try the inside */
  158.     {
  159.         if(i_t < MIN_T) /* yikes!! All this cpu time and we missed both */
  160.         {
  161.         return (0);
  162.         }
  163.         else
  164.         {            /* we hit this one */
  165.         inter->t = i_t;
  166.         inter->inside = inside2;
  167.         inter->obj = obj;
  168.         return (1);
  169.         }
  170.     }
  171.     else
  172.     {
  173.         inter->obj = obj;
  174.         if(i_t < MIN_T)    /* hit the outside one only    */
  175.         {
  176.         inter->t = t;
  177.         inter->inside = inside1;
  178.         return (1);
  179.         }
  180.         else        /* hit both, chose the close one */
  181.         {
  182.         if(i_t < t - MIN_T)
  183.         {
  184.             inter->t = i_t;
  185.             inter->inside = inside2;
  186.         }
  187.         else
  188.         {
  189.             inter->t = t;
  190.             inter->inside = inside1;
  191.         }
  192.         return (1);
  193.         }
  194.     }
  195.     break;
  196.  
  197.     case 1 :
  198.     disc = sqrt(t2hc);
  199.     /* if ray is inside object, set the inside flag */
  200.     if(l2oc > s->radius2 + MIN_T)
  201.     {
  202.         inter->inside = 0;
  203.         t = tca - disc;
  204.     }
  205.     else
  206.     {
  207.         inter->inside = 1;
  208.         t = tca + disc;
  209.     }
  210.     break;
  211.  
  212.     case 2 :
  213.     i_disc = sqrt(i_t2hc);
  214.     /* if ray is inside object, set the inside flag to FALSE */
  215.     if(l2oc > s->i_radius2 + MIN_T)
  216.     {
  217.         inter->inside = 1;
  218.         t = tca - i_disc;
  219.     }
  220.     else
  221.     {
  222.         inter->inside = 0;
  223.         t = tca + i_disc;
  224.     }
  225.     break;
  226.     }
  227.     
  228.  
  229.     if(t < MIN_T)
  230.     return (0);
  231.  
  232.     inter->obj = obj;
  233.     inter->t = t;
  234.  
  235.     return (1);
  236.     
  237. }
  238.  
  239.  
  240. /*
  241.  * Hsphere_normal()
  242.  *
  243.  * Return the normal to a sphere at a given point along the surface.
  244.  */
  245.  
  246. Hsphere_normal(sphere, ray, ip, normal)
  247. HSPHERE *sphere;
  248. RAY    *ray;
  249. VECTOR *ip;
  250. VECTOR *normal;
  251. {
  252.  
  253.     VecSub(*ip, sphere->center, *normal);
  254.     VecNormalize(normal);
  255.     if(VecDot(ray->dir, *normal) >= 0)
  256.     VecNegate(*normal);
  257. }
  258.  
  259.  
  260.  
  261.