//Finds the intersection between a ray and the cone
//Stores information about intersection in the Hit data structure if its the first intersection
bool Cone::intersect(const Ray &r,Hit &h) const{
	//Find intersection between ray and infinite cone of same parameters
	Vec p = r.getOrigin();
	Vec d = r.getDirection();
	double gamma = cos(theta);
	Matrix M;
	M.setToIdentity();
	M*=gamma*gamma;
	M=Matrix::MakeOuterProduct(dir) - M;
	M.set(3,3,1);
	Vec delta = p - origin;

	double a = d.Dot(M*d);
	double b = 2*d.Dot(M*delta);
	double c = delta.Dot(M*delta);
	double determinant=b*b-4.0*a*c;
	bool intersect = false;
	double t;
	Vec norm;
	//Checks if there are any real intersections with infinite cone
	if(determinant>0){
		intersect = true;
		t = (-b + sqrt(determinant)) / (2.0 * a);
		double t2 = (-b - sqrt(determinant)) / (2.0 * a);
		//Finds the intersection with a smaller t, and checks to see if the intersection is with the portion of the specified cone
		if(t2 < t || t < INTERSECT_EPSILON || !validIntersection(t,r)){
			t = t2;
			if(t < INTERSECT_EPSILON || !validIntersection(t,r)){
				intersect = false;
			}
		}
		if(intersect){
			if(h.getT()>t){
				norm = getNormal(r.getDirection()*t+r.getOrigin());
				norm.Normalize();
				if(norm.Dot(d)>0){
					norm *= -1;
				}
			}
		}
	}
	//checks for intersection with the end cap
	double num = dir.Dot(origin+dir*height-p);
	double den = dir.Dot(d);
	if(den!=0){
		double tc = num/den;
		double dist = (d*tc+p-(origin+dir*height)).Length();
		if(radius()>=dist  && tc > INTERSECT_EPSILON && tc < t){
			t = tc;
			intersect = true;
			norm = dir;
			if(norm.Dot(d)>0){
				norm *= -1;
			}
		}
	}
	//Checks if the intersection is closer than the one stored in the hit data structure
	if(intersect && h.getT() > t){
		h.set(t,material,norm);
		h.setObject(this);
	}
	return intersect;
}