package graphics.raytracer;
class SphereTarget implements Target {
Vec center;
double radius, radiusSq; static Targets scene;
static SceneConsts sConsts;
public SphereTarget(double x, double y, double z, double r) {
center = new Vec(x, y, z);
radius = r;
radiusSq = r * r;
if (sConsts == null)
sConsts = new SceneConsts();
}
public SphereTarget(Vec v, double r) {
center = new Vec(v);
radius = r;
radiusSq = r * r;
if (sConsts == null)
sConsts = new SceneConsts();
}
public SphereTarget() {
center = new Vec(0, 0, 0);
radius = radiusSq = 1;
if (sConsts == null)
sConsts = new SceneConsts();
}
public void setScene(Targets s) {
scene = s;
}
public boolean isBelongingToScene() {
return ((scene == null) ? false : true);
}
public double intersectTest(Vec R0, Vec R1, int object) {
double t,
loc,
tca,
thc;
Vec vecoc;
boolean inside = false;
vecoc = new Vec(center);
vecoc.sub(R0);
loc = vecoc.dotProduct(vecoc);
if (loc <= radiusSq)
inside = true;
tca = vecoc.dotProduct(R1);
if ((inside != true) && (tca <= 0.0))
return (0.0);
thc = (tca * tca) + radiusSq - loc;
if (thc < 0.0)
return (0.0);
if (inside == true)
t = tca + Math.sqrt(thc);
else
t = tca - Math.sqrt(thc);
return (t);
}
public int shade(int object, Vec R1, double t[]) {
Vec intersection, normal, lightSource;
double intensity;
double tShadow[] = new double[1];
tShadow[0] = 0;
intersection = new Vec(R1);
intersection.mult(t[0]);
intersection.add(scene.VRP);
normal = new Vec(intersection);
normal.sub(center);
normal.normalize();
lightSource = new Vec(scene.light);
lightSource.sub(intersection);
lightSource.normalize();
intersectObjects(intersection, lightSource, tShadow, object, true);
intensity = lightSource.dotProduct(normal);
if (intensity < 0.0)
intensity = 0.0;
if (tShadow[0] > 0.0)
intensity = sConsts.globalShadowReflectance *
intensity;
else {
intensity = intensity * sConsts.Ip
* sConsts.globalObjectReflectance;
}
intensity = intensity + sConsts.ambientLightIntensity
* sConsts.ambientLightReflectance;
if (intensity > 1.0)
intensity = 1.0;
intensity = intensity * 255;
return ((int) intensity);
}
int intersectObjects(Vec R0, Vec R1, double result[], int object,
boolean shadowCheck) {
double minDist = 0.0, dist;
int hit = -1;
for (int i = 0; i < scene.getSize(); i++) {
if ((shadowCheck == true) && (object == i))
continue;
dist = ((Target) scene.getElementAt(i)).intersectTest(R0,
R1, i);
if (dist == 0.0)
continue;
if ((minDist == 0.0) && (dist > 0.0)) {
minDist = dist;
hit = i;
} else if ((dist > 0.0) && (dist < minDist)) {
minDist = dist;
hit = i;
}
}
result[0] = minDist;
return hit;
}
public void debug_test() {
System.out.println("SphereTarget.debug_test(): center = " +
center.toString() + ", r = " + radius + ", r^2 = "
+ radiusSq);
}
}