import java.util.Random;
public class GroSpheres extends MISApplet {
	static Random rnd_ = new Random();
	double F = 10;	
	Colorizer colorizer_ = new Colorizer();
	
	class Sphere {
		public Vector3D pos_ = new Vector3D(),
			color_ = new Vector3D(),
			glare_ = new Vector3D();
		public double shiny_,r_;
	}
	Sphere spheres_[] = new Sphere[512];
	public GroSpheres() {
		double sqrt3 = Math.sqrt(3.);
		for(int i=0; i<8; ++i) {
			Sphere s = spheres_[i] = new Sphere();
			s.pos_.set(0,rnd_.nextGaussian()*5);
			s.pos_.set(1,rnd_.nextGaussian()*5);
			s.pos_.set(2,rnd_.nextGaussian()*5-3*F);
			s.color_.set(0,rnd_.nextDouble());
			s.color_.set(1,rnd_.nextDouble());
			s.color_.set(2,rnd_.nextDouble());
			
			double britest = Math.max(s.color_.get(0),Math.max(s.color_.get(1),s.color_.get(2))),
				topmul = 1./britest;
			s.color_.times(rnd_.nextDouble()*topmul,s.glare_);
			s.r_ = Math.max(0.01,rnd_.nextGaussian()/2+2);
			s.shiny_ = rnd_.nextGaussian()*3+14;
		}
	}
    public void initFrame(double time) { 
		//double dt = time - lastt;
		System.out.println("frame.");
    }
	Vector3D v_ = new Vector3D(0,0,0), w_ = new Vector3D();
    public void setPixel(int x, int y, int rgb[]) { 
		w_.set(0,(double)(x - W/2) / (W/2));
		w_.set(1,(double)(H/2 - y) / (W/2));
		w_.set(2,-F);
		w_.set(3,0);
		w_.normalize();
		rayTrace(v_,w_,rgb);
    }
	Vector3D vmc_ = new Vector3D(),temp_=new Vector3D(),p_=new Vector3D(),pix_ = new Vector3D();
	public void rayTrace(Vector3D v,Vector3D w,int rgb[]) {
		double t = 1e40;
		pix_.set(0,0); pix_.set(1,0); pix_.set(2,0); 
		for(Sphere s : spheres_)
			if(s!=null) {
				v.subtract(s.pos_,vmc_);
				double A = w.dot(w),
					B = 2*vmc_.dot(w),
					C = vmc_.dot(vmc_) - s.r_*s.r_,
					Bsqm4AC = B*B - 4*A*C;
				if(Bsqm4AC<0)
					continue;
				double sqrtBsqm4AC = Math.sqrt(Bsqm4AC);
				if(-B-sqrtBsqm4AC < 0) // allow no negativity
					continue;
				double t0 = (-B-sqrtBsqm4AC)/(2*A);
				if(t0>t)
					continue;
				//System.out.println("blip.");
				t = t0;
				w.times(t0,temp_);
				temp_.add(v,p_);
				p_.subtract(s.pos_,temp_);
				temp_.normalize();
				colorizer_.colorize(temp_,s.color_,s.glare_,s.shiny_,pix_);
			}
		rgb[0] = (int)(pix_.get(0)*255.);
		rgb[1] = (int)(pix_.get(1)*255.);
		rgb[2] = (int)(pix_.get(2)*255.);		
	}
}
