ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/ot/sphere.c
Revision: 2.6
Committed: Wed Apr 20 18:51:35 2016 UTC (8 years, 7 months ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: rad5R4, rad5R2, rad5R1, rad5R3, HEAD
Changes since 2.5: +8 -6 lines
Log Message:
Changed zero-radius sphere from error to warning

File Contents

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