import RayTrace;
import java.util.Vector;
import java.awt.Color;

public class SuperEllipsoid implements Renderable
{
	
	Vector3D center;
	Surface surface;
	float s;
 
	
	public SuperEllipsoid(Surface sur, Vector3D cntr, float ss) 
	{

		surface = sur;
		center = cntr;
		s=ss;
    }
	
	public boolean intersect(Ray ray) 
	{
		
		float dx = center.x - ray.origin.x;
        float dy = center.y - ray.origin.y;
        float dz = center.z - ray.origin.z;
        float v = ray.direction.dot(dx, dy, dz);

        // Do the following quick check to see if there is even a chance
        // that an intersection here might be closer than a previous one
        
		
		 if (v - Math.sqrt(3) > ray.t)
            return false;

		
		 
      
		  
		 float t = (float) (Math.sqrt(3) + v*v - dx*dx - dy*dy - dz*dz); 
		 
		  if (t < 0)
            return false;

			float topp = v + ((float) Math.sqrt(t));
		 
			float x,y,z;
			
			Vector3D vec = new Vector3D(ray.direction);
			vec.normalize();
		 for(float i = t;i<topp;i+=.05)
		 {
			
			x = ray.origin.x + i*vec.x - center.x;
			y = ray.origin.y + i*vec.y - center.y;
			z = ray.origin.z + i*vec.z - center.z;
			
			float eval = eval(x,y,z);
			
		
			
			if(eval > .9 && eval < 1.1)
			{
				
				
			   if(i < ray.t)
				{
				   
					ray.t = i;
					ray.object = this;
					return true;
				}
				else return false;
			}
		 }
											   
							
		 return false;
		 
											   
	
	}
	
	public Color Shade(Ray ray, Vector lights, Vector objects, Color bgnd) 
	{
		
        // An object shader doesn't really do too much other than
        // supply a few critical bits of geometric information
        // for a surface shader. It must must compute:
        //
        //   1. the point of intersection (p)
        //   2. a unit-length surface normal (n)
        //   3. a unit-length vector towards the ray's origin (v)
        //
        float px = ray.origin.x + ray.t*ray.direction.x;
        float py = ray.origin.y + ray.t*ray.direction.y;
        float pz = ray.origin.z + ray.t*ray.direction.z;

        Vector3D p = new Vector3D(px, py, pz);
        Vector3D v = new Vector3D(-ray.direction.x, -ray.direction.y, -ray.direction.z);
		
		
		/*
	
		This was my attempt, and because I was in D.C. until 9:30 fri night
		I didn't get to debug.
		
		
		
		
		Ray r1 = new Ray(ray.origin,new Vector3D((float) (ray.direction.x+.05),
												 (float) (ray.direction.y-.05),
												 ray.direction.z));
		
		Ray r2 = new Ray(ray.origin,new Vector3D((float) (ray.direction.x-.05),
												 (float)(ray.direction.y+.05),
												 ray.direction.z));
		
		this.intersect(r1);
		this.intersect(r2);
		
		float dx1 = r1.origin.x + r1.t*r1.direction.x;
        float dy1 = r1.origin.y + r1.t*r1.direction.y;
        float dz1 = r1.origin.z + r1.t*r1.direction.z;
		
		float dx2 = r2.origin.x + r2.t*r2.direction.x;
        float dy2 = r2.origin.y + r2.t*r2.direction.y;
        float dz2 = r2.origin.z + r2.t*r2.direction.z;
		
		Vector3D t1 = new Vector3D(dx1-px,dy1-py,dz1-pz);
		
		Vector3D t2 = new Vector3D(dx2-px,dy2-py,dz2-pz);
		
		t1.normalize();
		t2.normalize();
		
        Vector3D n = t1.cross(t2);
		
		*/
		
		Vector3D n = new Vector3D(px - center.x, py - center.y, pz - center.z);
        n.normalize();

        // The illumination model is applied
        // by the surface's Shade() method
        return surface.Shade(p, n, v, lights, objects, bgnd);
		
		}
	
	public float eval(float x, float y, float z)
	{
		return (float) (Math.pow(x*x,1/s) + Math.pow(y*y,1/s) + Math.pow(z*z,1/s)); 
	}
	
	public String toString() 
	{
		return ("SuperEllipsoid "+center+" s = "+s);
	}
	 
}
