package graphics.tracer;
class Sphere implements Target {
private Vec3f center;
private float radius;
private float radiusSq;
private static Scene scene;
public static Sphere makeSphere(
double x, double y, double z, double r) {
return
new Sphere(
(float) x,
(float) y,
(float) z,
(float) r);
}
public Sphere(float x, float y, float z, float r) {
center = new Vec3f(x, y, z);
radius = r;
radiusSq = r * r;
}
public Vec3f getCenter() {
return center;
}
public float getRadius() {
return radius;
}
public static final float sqrt(float f) {
return (float) Math.sqrt(f);
}
public static final float sqrt(double f) {
return (float) Math.sqrt(f);
}
public Sphere(Vec3f v, float r) {
center = new Vec3f(v);
radius = r;
radiusSq = r * r;
}
public void initScene(Scene s) {
scene = s;
}
public boolean initScene() {
return ((scene == null) ? false : true);
}
public float intersectTest(Vec3f R0, Vec3f R1, int object) {
float t,
loc,
tca,
thc;
Vec3f vecoc;
boolean inside = false;
vecoc = new Vec3f(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);
thc = (float) ((tca * tca) + radiusSq - loc);
if (thc < 0)
return (0);
if (inside == true)
t = tca + sqrt(thc);
else
t = tca - sqrt(thc);
return (t);
}
public int shade(int object, Vec3f R1, float t[]) {
Vec3f intersection, normal, lightSource;
float tShadow[] = new float[1];
tShadow[0] = 0;
intersection = new Vec3f(R1);
intersection.mult(t[0]);
intersection.add(scene.getEye());
normal = new Vec3f(intersection);
normal.sub(center);
normal.normalize();
lightSource = new Vec3f(scene.getLight());
lightSource.sub(intersection);
lightSource.normalize();
intersectObjects(
intersection, lightSource, tShadow, object, true);
float intensity = lightSource.dotProduct(normal);
if (intensity < 0)
intensity = 0;
if (tShadow[0] > 0)
intensity = SceneConsts.Gs * intensity;
else {
intensity = intensity * SceneConsts.Ip * SceneConsts.GKd;
}
intensity = intensity + SceneConsts.GIa * SceneConsts.GKa;
if (intensity > 1)
intensity = 1;
intensity = intensity * 255;
return ((int) intensity);
}
int intersectObjects(
Vec3f R0, Vec3f R1,
float result[], int object,
boolean shadowCheck) {
float minDist = 0;
float dist;
int hit = -1;
for (int i = 0; i < scene.getNumberOfTargets(); i++) {
if ((shadowCheck == true) && (object == i))
continue;
dist = scene.getTargetAt(i).intersectTest(R0, R1, i);
if (dist == 0) continue;
if ((minDist == 0) && (dist > 0)) {
minDist = dist;
hit = i;
} else if ((dist > 0) && (dist < minDist)) {
minDist = dist;
hit = i;
}
}
result[0] = minDist;
return hit;
}
}