/Users/lyon/j4p/src/graphics/raytracers/raytracer/tracer/Sphere.java

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