home *** CD-ROM | disk | FTP | other *** search
/ DP Tool Club 8 / CDASC08.ISO / NEWS / RADIANCE / SRC / OT / SPHERE.C < prev    next >
C/C++ Source or Header  |  1993-10-07  |  3KB  |  109 lines

  1. /* Copyright (c) 1986 Regents of the University of California */
  2.  
  3. #ifndef lint
  4. static char SCCSid[] = "@(#)sphere.c 2.1 11/12/91 LBL";
  5. #endif
  6.  
  7. /*
  8.  *  sphere.c - routines for creating octrees for spheres.
  9.  *
  10.  *     7/28/85
  11.  */
  12.  
  13. #include  "standard.h"
  14.  
  15. #include  "octree.h"
  16.  
  17. #include  "object.h"
  18.  
  19. #include  "otypes.h"
  20.  
  21. #define  ROOT3        1.732050808
  22.  
  23. /*
  24.  *    Regrettably, the algorithm for determining a cube's location
  25.  *  with respect to a sphere is not simple.  First, a quick test is 
  26.  *  made to determine if the sphere and the bounding sphere of the cube 
  27.  *  are disjoint.  This of course means no intersection.  Failing this,
  28.  *  we determine if the cube lies inside the sphere.  The cube is
  29.  *  entirely inside if the bounding sphere on the cube is
  30.  *  contained within our sphere.  This means no intersection.  Otherwise,
  31.  *  if the cube radius is smaller than the sphere's and the cube center is
  32.  *  inside the sphere, we assume intersection.  If these tests fail,
  33.  *  we proceed as follows.
  34.  *    The sphere center is located in relation to the 6 cube faces,
  35.  *  and one of four things is done depending on the number of
  36.  *  planes the center lies between:
  37.  *
  38.  *    0:  The sphere is closest to a cube corner, find the
  39.  *        distance to that corner.
  40.  *
  41.  *    1:  The sphere is closest to a cube edge, find this
  42.  *        distance.
  43.  *
  44.  *    2:  The sphere is closest to a cube face, find the distance.
  45.  *
  46.  *    3:  The sphere has its center inside the cube.
  47.  *
  48.  *    In cases 0-2, if the closest part of the cube is within
  49.  *  the radius distance from the sphere center, we have intersection.
  50.  *  If it is not, the cube must be outside the sphere.
  51.  *    In case 3, there must be intersection, and no further
  52.  *  tests are necessary.
  53.  */
  54.  
  55.  
  56. o_sphere(o, cu)            /* determine if sphere intersects cube */
  57. OBJREC  *o;
  58. register CUBE  *cu;
  59. {
  60.     FVECT  v1;
  61.     double  d1, d2;
  62.     register FLOAT  *fa;
  63.     register int  i;
  64. #define  cent        fa
  65. #define  rad        fa[3]
  66.                     /* get arguments */
  67.     if (o->oargs.nfargs != 4)
  68.         objerror(o, USER, "bad # arguments");
  69.     fa = o->oargs.farg;
  70.     if (rad < -FTINY) {
  71.         objerror(o, WARNING, "negative radius");
  72.         o->otype = o->otype == OBJ_SPHERE ?
  73.                 OBJ_BUBBLE : OBJ_SPHERE;
  74.         rad = -rad;
  75.     } else if (rad <= FTINY)
  76.         objerror(o, USER, "zero radius");
  77.  
  78.     d1 = ROOT3/2.0 * cu->cusize;    /* bounding radius for cube */
  79.  
  80.     d2 = cu->cusize * 0.5;        /* get distance between centers */
  81.     for (i = 0; i < 3; i++)
  82.         v1[i] = cu->cuorg[i] + d2 - cent[i];
  83.     d2 = DOT(v1,v1);
  84.  
  85.     if (d2 > (rad+d1+FTINY)*(rad+d1+FTINY))    /* quick test */
  86.         return(O_MISS);            /* cube outside */
  87.     
  88.                     /* check sphere interior */
  89.     if (d1 < rad) {
  90.         if (d2 < (rad-d1-FTINY)*(rad-d1-FTINY))
  91.             return(O_MISS);        /* cube inside sphere */
  92.         if (d2 < (rad+FTINY)*(rad+FTINY))
  93.             return(O_HIT);        /* cube center inside */
  94.     }
  95.                     /* find closest distance */
  96.     for (i = 0; i < 3; i++)
  97.         if (cent[i] < cu->cuorg[i])
  98.             v1[i] = cu->cuorg[i] - cent[i];
  99.         else if (cent[i] > cu->cuorg[i] + cu->cusize)
  100.             v1[i] = cent[i] - (cu->cuorg[i] + cu->cusize);
  101.         else
  102.             v1[i] = 0;
  103.                     /* final intersection check */
  104.     if (DOT(v1,v1) <= (rad+FTINY)*(rad+FTINY))
  105.         return(O_HIT);
  106.     else
  107.         return(O_MISS);
  108. }
  109.