/Users/lyon/j4p/src/graphics/raytracers/rmiRaytracer/raytracer/SphereTarget.java

1    package graphics.raytracers.rmiRaytracer.raytracer; 
2     
3    class SphereTarget implements Target { 
4        Vec center; 
5        double radius, radiusSq; // precompute radiusSq since we use it a lot 
6        static Targets scene; 
7        static SceneConsts sConsts; 
8     
9        public SphereTarget(double x, double y, double z, double r) { 
10           center = new Vec(x, y, z); 
11           radius = r; 
12           radiusSq = r * r; 
13    
14           if (sConsts == null) 
15               sConsts = new SceneConsts(); 
16       } 
17    
18       public SphereTarget(Vec v, double r) { 
19           center = new Vec(v); 
20           radius = r; 
21           radiusSq = r * r; 
22    
23           if (sConsts == null) 
24               sConsts = new SceneConsts(); 
25       } 
26    
27       public SphereTarget() { 
28           center = new Vec(0, 0, 0); 
29           radius = radiusSq = 1; 
30    
31           if (sConsts == null) 
32               sConsts = new SceneConsts(); 
33       } 
34    
35       public void setScene(Targets s) { 
36           scene = s; 
37       } 
38    
39       public boolean isBelongingToScene() { 
40           return ((scene == null) ? false : true); 
41       } 
42    
43       public double intersectTest(Vec R0, Vec R1, int object) { 
44    
45           double t,          /* where the ray intersects */ 
46                   loc,        /* square distance from center of sphere to projP */ 
47                   tca,        /* how far is the 'closest approach' from VRP */ 
48                   thc;        /* length sqare of the half chord */ 
49           Vec vecoc;      /* vector to the center of the sphere from VRP */ 
50           boolean inside = false; 
51    
52           /* use the closest approach algorithm */ 
53           vecoc = new Vec(center); 
54           vecoc.sub(R0); 
55           loc = vecoc.dotProduct(vecoc); 
56    
57           if (loc <= radiusSq) 
58               inside = true; 
59    
60           tca = vecoc.dotProduct(R1);   /* find the closest approach */ 
61    
62           if ((inside != true) && (tca <= 0.0)) 
63               return (0.0);  /* object is behind the VRP */ 
64    
65           /* compute the half chord square from the ray intersection to the 
66              intersection normal. */ 
67           thc = (tca * tca) + radiusSq - loc; 
68           if (thc < 0.0) 
69               return (0.0);   /* ray misses the sphere */ 
70    
71           /* find the ray intersection */ 
72           if (inside == true) 
73               t = tca + Math.sqrt(thc); 
74           else 
75               t = tca - Math.sqrt(thc); 
76    
77           return (t); 
78       } 
79    
80       public int shade(int object, Vec R1, double t[]) { 
81    
82           Vec intersection, normal, lightSource; 
83           double intensity; 
84           double tShadow[] = new double[1]; 
85           tShadow[0] = 0; 
86    
87           /* calculate the intersection POINT on the object */ 
88           intersection = new Vec(R1); 
89           intersection.mult(t[0]); 
90           intersection.add(scene.VRP); 
91    
92           /* find the normal vector from sphere's center to the intersection */ 
93           normal = new Vec(intersection); 
94           normal.sub(center); 
95           normal.normalize(); 
96    
97           /* locate the light source from intersection */ 
98           lightSource = new Vec(scene.light); 
99           lightSource.sub(intersection); 
100          lightSource.normalize(); 
101   
102          /* check if the light can be "seen" by the intersection point */ 
103          intersectObjects(intersection, lightSource, tShadow, object, true); 
104   
105          intensity = lightSource.dotProduct(normal); 
106          if (intensity < 0.0) 
107              intensity = 0.0; 
108   
109          if (tShadow[0] > 0.0) /* something is in the way */ 
110              intensity = sConsts.globalShadowReflectance * 
111                      intensity;  /* pixel gets ambient 
112                                    light only */ 
113          else {   /* pixel gets all kinds of light */ 
114              intensity = intensity * sConsts.Ip 
115                      * sConsts.globalObjectReflectance; 
116          } 
117   
118          intensity = intensity + sConsts.ambientLightIntensity 
119                  * sConsts.ambientLightReflectance; 
120          if (intensity > 1.0) 
121              intensity = 1.0; 
122   
123          /* find the corresponding color in the color lookup table */ 
124          intensity = intensity * 255; 
125   
126          return ((int) intensity); 
127      } 
128   
129      int intersectObjects(Vec R0, Vec R1, double result[], int object, 
130                           boolean shadowCheck) { 
131          double minDist = 0.0, dist; 
132          int hit = -1; 
133   
134          for (int i = 0; i < scene.getSize(); i++) { 
135              if ((shadowCheck == true) && (object == i)) 
136                  continue; 
137              dist = ((Target) scene.getElementAt(i)).intersectTest(R0, 
138                      R1, i); 
139   
140              if (dist == 0.0) 
141                  continue; 
142   
143              /* save the first t */ 
144              if ((minDist == 0.0) && (dist > 0.0)) { 
145                  minDist = dist; 
146                  hit = i; 
147              } else if ((dist > 0.0) && (dist < minDist)) { 
148                  minDist = dist; 
149                  hit = i; 
150              } 
151          } 
152          result[0] = minDist; 
153          return hit; 
154      } 
155   
156      public void debug_test() { 
157          System.out.println("SphereTarget.debug_test(): center = " + 
158                  center.toString() + ", r = " + radius + ", r^2 = " 
159                  + radiusSq); 
160      } 
161  } 
162