//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; }