Back to index

radiance  4R0+20100331
o_cone.c
Go to the documentation of this file.
00001 #ifndef lint
00002 static const char    RCSid[] = "$Id: o_cone.c,v 2.6 2007/11/21 18:51:04 greg Exp $";
00003 #endif
00004 /*
00005  *  o_cone.c - routines for intersecting cubes with cones.
00006  *
00007  *     2/3/86
00008  */
00009 
00010 #include  "standard.h"
00011 #include  "octree.h"
00012 #include  "object.h"
00013 #include  "cone.h"
00014 #include  "plocate.h"
00015 
00016 #define  ROOT3              1.732050808
00017 
00018 /*
00019  *     The algorithm used to detect cube intersection with cones is
00020  *  recursive.  First, we approximate the cube to be a sphere.  Then
00021  *  we test for cone intersection with the sphere by testing the
00022  *  segment of the cone which is nearest the sphere's center.
00023  *     If the cone has points within the cube's bounding sphere,
00024  *  we must check for intersection with the cube.  This is done with
00025  *  the 3D line clipper.  The same cone segment is used in this test.
00026  *  If the clip fails, we still cannot be sure there is no intersection,
00027  *  so we subdivide the cube and recurse.
00028  *     If none of the sub-cubes intersect, then our cube does not intersect.
00029  */
00030 
00031 extern double  mincusize;          /* minimum cube size */
00032 
00033 static int findcseg(FVECT ep0, FVECT ep1, CONE *co, FVECT p);
00034 
00035 
00036 
00037 extern int
00038 o_cone(              /* determine if cone intersects cube */
00039        OBJREC  *o,
00040        register CUBE  *cu
00041 )
00042 {
00043        CONE  *co;
00044        FVECT  ep0, ep1;
00045 #ifdef STRICT
00046        FVECT  cumin, cumax;
00047        CUBE  cukid;
00048        register int  j;
00049 #endif
00050        double  r;
00051        FVECT  p;
00052        register int  i;
00053                                    /* get cone arguments */
00054        co = getcone(o, 0);
00055                                    /* get cube center */
00056        r = cu->cusize * 0.5;
00057        for (i = 0; i < 3; i++)
00058               p[i] = cu->cuorg[i] + r;
00059        r *= ROOT3;                 /* bounding radius for cube */
00060 
00061        if (findcseg(ep0, ep1, co, p)) {
00062                                    /* check min. distance to cone */
00063               if (dist2lseg(p, ep0, ep1) > (r+FTINY)*(r+FTINY))
00064                      return(O_MISS);
00065 #ifdef  STRICT
00066                                    /* get cube boundaries */
00067               for (i = 0; i < 3; i++)
00068                      cumax[i] = (cumin[i] = cu->cuorg[i]) + cu->cusize;
00069                                    /* closest segment intersects? */
00070               if (clip(ep0, ep1, cumin, cumax))
00071                      return(O_HIT);
00072        }
00073                                    /* check sub-cubes */
00074        cukid.cusize = cu->cusize * 0.5;
00075        if (cukid.cusize < mincusize)
00076               return(O_HIT);              /* cube too small */
00077        cukid.cutree = EMPTY;
00078 
00079        for (j = 0; j < 8; j++) {
00080               for (i = 0; i < 3; i++) {
00081                      cukid.cuorg[i] = cu->cuorg[i];
00082                      if (1<<i & j)
00083                             cukid.cuorg[i] += cukid.cusize;
00084               }
00085               if (o_cone(o, &cukid))
00086                      return(O_HIT);       /* sub-cube intersects */
00087        }
00088        return(O_MISS);                    /* no intersection */
00089 #else
00090        }
00091        return(O_HIT);                     /* assume intersection */
00092 #endif
00093 }
00094 
00095 
00096 static int
00097 findcseg(     /* find line segment from cone closest to p */
00098        FVECT  ep0,
00099        FVECT  ep1,
00100        register CONE  *co,
00101        FVECT  p
00102 )
00103 {
00104        double  d;
00105        FVECT  v;
00106        register int  i;
00107                                    /* find direction from axis to point */
00108        VSUB(v, p, CO_P0(co));
00109        d = DOT(v, co->ad);
00110        for (i = 0; i < 3; i++)
00111               v[i] -= d*co->ad[i];
00112        if (normalize(v) == 0.0)
00113               return(0);
00114                                    /* find endpoints of segment */
00115        for (i = 0; i < 3; i++) {
00116               ep0[i] = CO_R0(co)*v[i] + CO_P0(co)[i];
00117               ep1[i] = CO_R1(co)*v[i] + CO_P1(co)[i];
00118        }
00119        return(1);                  /* return distance from axis */
00120 }