Back to index

radiance  4R0+20100331
sphere.c
Go to the documentation of this file.
00001 #ifndef lint
00002 static const char    RCSid[] = "$Id: sphere.c,v 2.5 2004/03/30 16:13:00 schorsch Exp $";
00003 #endif
00004 /*
00005  *  sphere.c - routines for creating octrees for spheres.
00006  *
00007  *     7/28/85
00008  */
00009 
00010 #include  "standard.h"
00011 
00012 #include  "octree.h"
00013 
00014 #include  "object.h"
00015 
00016 #include  "otypes.h"
00017 
00018 #define  ROOT3              1.732050808
00019 
00020 /*
00021  *     Regrettably, the algorithm for determining a cube's location
00022  *  with respect to a sphere is not simple.  First, a quick test is 
00023  *  made to determine if the sphere and the bounding sphere of the cube 
00024  *  are disjoint.  This of course means no intersection.  Failing this,
00025  *  we determine if the cube lies inside the sphere.  The cube is
00026  *  entirely inside if the bounding sphere on the cube is
00027  *  contained within our sphere.  This means no intersection.  Otherwise,
00028  *  if the cube radius is smaller than the sphere's and the cube center is
00029  *  inside the sphere, we assume intersection.  If these tests fail,
00030  *  we proceed as follows.
00031  *     The sphere center is located in relation to the 6 cube faces,
00032  *  and one of four things is done depending on the number of
00033  *  planes the center lies between:
00034  *
00035  *     0:  The sphere is closest to a cube corner, find the
00036  *            distance to that corner.
00037  *
00038  *     1:  The sphere is closest to a cube edge, find this
00039  *            distance.
00040  *
00041  *     2:  The sphere is closest to a cube face, find the distance.
00042  *
00043  *     3:  The sphere has its center inside the cube.
00044  *
00045  *     In cases 0-2, if the closest part of the cube is within
00046  *  the radius distance from the sphere center, we have intersection.
00047  *  If it is not, the cube must be outside the sphere.
00048  *     In case 3, there must be intersection, and no further
00049  *  tests are necessary.
00050  */
00051 
00052 
00053 int
00054 o_sphere(                   /* determine if sphere intersects cube */
00055        OBJREC  *o,
00056        register CUBE  *cu
00057 )
00058 {
00059        FVECT  v1;
00060        double  d1, d2;
00061        register RREAL  *fa;
00062        register int  i;
00063 #define  cent        fa
00064 #define  rad         fa[3]
00065                                    /* get arguments */
00066        if (o->oargs.nfargs != 4)
00067               objerror(o, USER, "bad # arguments");
00068        fa = o->oargs.farg;
00069        if (rad < -FTINY) {
00070               objerror(o, WARNING, "negative radius");
00071               o->otype = o->otype == OBJ_SPHERE ?
00072                             OBJ_BUBBLE : OBJ_SPHERE;
00073               rad = -rad;
00074        } else if (rad <= FTINY)
00075               objerror(o, USER, "zero radius");
00076 
00077        d1 = ROOT3/2.0 * cu->cusize;       /* bounding radius for cube */
00078 
00079        d2 = cu->cusize * 0.5;             /* get distance between centers */
00080        for (i = 0; i < 3; i++)
00081               v1[i] = cu->cuorg[i] + d2 - cent[i];
00082        d2 = DOT(v1,v1);
00083 
00084        if (d2 > (rad+d1+FTINY)*(rad+d1+FTINY))   /* quick test */
00085               return(O_MISS);                    /* cube outside */
00086        
00087                                    /* check sphere interior */
00088        if (d1 < rad) {
00089               if (d2 < (rad-d1-FTINY)*(rad-d1-FTINY))
00090                      return(O_MISS);             /* cube inside sphere */
00091               if (d2 < (rad+FTINY)*(rad+FTINY))
00092                      return(O_HIT);              /* cube center inside */
00093        }
00094                                    /* find closest distance */
00095        for (i = 0; i < 3; i++)
00096               if (cent[i] < cu->cuorg[i])
00097                      v1[i] = cu->cuorg[i] - cent[i];
00098               else if (cent[i] > cu->cuorg[i] + cu->cusize)
00099                      v1[i] = cent[i] - (cu->cuorg[i] + cu->cusize);
00100               else
00101                      v1[i] = 0;
00102                                    /* final intersection check */
00103        if (DOT(v1,v1) <= (rad+FTINY)*(rad+FTINY))
00104               return(O_HIT);
00105        else
00106               return(O_MISS);
00107 }