//
import java.awt.*;
public class Sphere extends Shape
{
public Sphere(double cx, double cy, double cz, double r)
{
// YOUR CODE GOES HERE
center[0] = cx;
center[1] = cy;
center[2] = cz;
radius = r;
}
// RETURNS THE NUMBER OF ROOTS. ROOTS ARE PLACED IN t[]
private final double sq(double x)
{
return x*x;
}
private void normalize(double[] n)
{
double norm = Math.sqrt(n[0]*n[0]+n[1]*n[1]+n[2]*n[2]);
n[0] /= norm;
n[1] /= norm;
n[2] /= norm;
}
public int traceRay(double v[], double w[], double t[])
{
double x1, x2, x3;
double y1, y2, y3;
double z1, z2, z3;
x1 = v[0];
x2 = w[0] + v[0];
x3 = center[0];
y1 = v[1];
y2 = w[1] + v[1];
y3 = center[1];
z1 = v[2];
z2 = w[2] + v[2];
z3 = center[2];
double a, b, c;
a = sq(x2-x1) + sq(y2-y1) + sq(z2-z1);
b = 2*( (x2-x1)*(x1-x3) + (y2-y1)*(y1-y3) + (z2-z1)*(z1-z3) );
c = sq(x3) + sq(y3) + sq(z3) + sq(x1) + sq(y1) + sq(z1) - 2*(x3*x1 + y3*y1 + z3*z1) - sq(radius);
//We can solve with the quadratic equation (there may be 2 real solutions)
//The discriminant (part under the radical in the quad.eq.) will tell us how many.
double discrim;
discrim = sq(b) - 4*a*c;
//If the discriminant is less than zero, there was no collision
if( discrim < 0 )
return 0;
//If the discriminant is zero, there is one soln. (w/ multiplicity 2)
else if( discrim == 0 )
{
t[0] = -b/(2*a);
return 1;
}
//Otherwise, there are two solutions
else
{
double sqrt_discrim = Math.sqrt(discrim);
t[0] = ( -b - sqrt_discrim) / (2*a);
t[1] = ( -b + sqrt_discrim) / (2*a);
return 2;
}
}
private double[] array(double x, double y, double z)
{
return new double[]{x,y,z};
}
public void computeNormal(double p[], double n[])
{
//Given a point p on the surface, the normal is (p - center) / r
for(int i=0; i<3; i++)
{
n[i] = (p[i] - center[i]) / radius;
}
//We will now perturb the normal with noise to do bumpmapping
//This will be slow, but oh, well
//Ultimatly, we want n + (deriv - n*(n dot deriv)), normalized
if(Shape.bumpType == 0)
return;
double[] deriv = new double[3];
double pert;
double h = 0.0001;
pert = textureFactor(p, Shape.bumpType);
deriv[0] = textureFactor(new double[]{p[0]+h,p[1],p[2]}, bumpType) - pert;
deriv[1] = textureFactor(new double[]{p[0],p[1]+h,p[2]}, bumpType) - pert;
deriv[2] = textureFactor(new double[]{p[0],p[1],p[2]+h}, bumpType) - pert;
normalize(deriv);
double dotND = n[0]*deriv[0]+n[1]*deriv[1]+n[2]*deriv[2];
double disturb[] = new double[3];
for(int i=0; i<3; i++)
n[i] = n[i] + deriv[i] - n[i]*dotND;
/*
n[0] += (pertX - pert) / h;
n[1] += (pertY - pert) / h;
n[2] += (pertZ - pert) / h;
*/
normalize(n);
}
static final int toint(double d)
{
return (int)(10000*d);
}
static final double trans(double d)
{
return 30*(d);
}
double noise(double[] p, double freq, double amp)
{
//freq *= 5;
//freq *= 9;
//freq *= 15;
freq *= 25;
return Noise.noise(freq*p[0], freq*p[1], freq*p[2]) / amp;
}
double abs(double[] p, double freq, double amp)
{
return Math.abs( noise(p, freq, amp) );
}
public double textureFactor(double p[], int type)
{
double result;
switch(type)
{
case 1:
result = (abs(p,1,1)+abs(p,2,2)+abs(p,4,4)+abs(p,8,8)+abs(p,16,16)+abs(p,32, 32));
result = (Math.sin(30*p[0] + result)+1)/2.0;
break;
case 2:
result = (noise(p,1,1)+noise(p,2,2)+noise(p,4,4)+noise(p,8,8)+noise(p,16,16)+noise(p,32, 32));
break;
case 3:
result = noise(p,1,1);
break;
default:
result = 0;
break;
}
return result;
}
//255, 217, 160
//70, 12, 0
public Color textureColor(double p[])
{
//double[] colorMin = { 255.0/255.0, 217.0/255.0, 160.0/255.0 };
//double[] colorMax = { 70.0/255.0, 12.0/255.0, 0/255.0 };
double result;
result = textureFactor(p, Shape.noiseType);
//return new Color(d2i(result), d2i(result), d2i(result));
double[] out = new double[3];
for(int i=0; i<3; i++)
{
out[i] = colorMin[i]*(1-result) + colorMax[i]*(result);
}
return new Color(d2i(out[0]),d2i(out[1]),d2i(out[2]));
}
public Color materialColor(double p[])
{
return null;
}
private final double clamp(double x, double min, double max)
{
if( x < min )
return min;
else if( x > max )
return max;
else
return x;
}
private final int d2i(double d)
{
return (int)(255*clamp(d,0,1));
}
// YOU MIGHT WANT TO DECLARE SOME PERSISTENT VARIABLES
// OK
double center[] = new double[3];
double radius;
}