/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 }