bool Torus::hit(const Ray& ray, double& tmin, ShadeRec& sr) const { if (!bbox.hit(ray)) return (false); double x1 = ray.o.x; double y1 = ray.o.y; double z1 = ray.o.z; double d1 = ray.d.x; double d2 = ray.d.y; double d3 = ray.d.z; double coeffs[5]; // coefficient array for the quartic equation double roots[4]; // solution array for the quartic equation // define the coefficients of the quartic equation double sum_d_sqrd = d1 * d1 + d2 * d2 + d3 * d3; double e = x1 * x1 + y1 * y1 + z1 * z1 - a * a - b * b; double f = x1 * d1 + y1 * d2 + z1 * d3; double four_a_sqrd = 4.0 * a * a; coeffs[0] = e * e - four_a_sqrd * (b * b - y1 * y1); // constant term coeffs[1] = 4.0 * f * e + 2.0 * four_a_sqrd * y1 * d2; coeffs[2] = 2.0 * sum_d_sqrd * e + 4.0 * f * f + four_a_sqrd * d2 * d2; coeffs[3] = 4.0 * sum_d_sqrd * f; coeffs[4] = sum_d_sqrd * sum_d_sqrd; // coefficient of t^4 // find roots of the quartic equation int num_real_roots = SolveQuartic(coeffs, roots); bool intersected = false; double t = kHugeValue; if (num_real_roots == 0) // ray misses the torus return(false); // find the smallest root greater than kEpsilon, if any // the roots array is not sorted for (int j = 0; j < num_real_roots; j++) if (roots[j] > kEpsilon) { intersected = true; if (roots[j] < t) t = roots[j]; } if(!intersected) return (false); tmin = t; sr.local_hit_point = ray.o + t * ray.d; sr.normal = compute_normal(sr.local_hit_point); return (true); }
bool ConcavePartTorus::shadow_hit(const Ray& ray, float& tmin) const { if (!shadows) return false; if (!bbox.hit(ray)) return false; double x1 = ray.o.x; double y1 = ray.o.y; double z1 = ray.o.z; double d1 = ray.d.x; double d2 = ray.d.y; double d3 = ray.d.z; double coeffs[5]; // coefficient array for the quartic equation double roots[4]; // solution array for the quartic equation // define the coefficients of the quartic equation double sum_d_sqrd = d1 * d1 + d2 * d2 + d3 * d3; double e = x1 * x1 + y1 * y1 + z1 * z1 - a * a - b * b; double f = x1 * d1 + y1 * d2 + z1 * d3; double four_a_sqrd = 4.0 * a * a; coeffs[0] = e * e - four_a_sqrd * (b * b - y1 * y1); // constant term coeffs[1] = 4.0 * f * e + 2.0 * four_a_sqrd * y1 * d2; coeffs[2] = 2.0 * sum_d_sqrd * e + 4.0 * f * f + four_a_sqrd * d2 * d2; coeffs[3] = 4.0 * sum_d_sqrd * f; coeffs[4] = sum_d_sqrd * sum_d_sqrd; // coefficient of t^4 // find roots of the quartic equation int num_real_roots = SolveQuartic(coeffs, roots); bool intersected = false; double t = kHugeValue; if (num_real_roots == 0) // ray misses the torus return false; // find the smallest root greater than kEpsilon, if any // the roots array is not sorted for (int j = 0; j < num_real_roots; j++) { if (roots[j] > kEpsilon) { if (roots[j] < t) { Vector3D hit = ray.o + roots[j] * ray.d; double phi = atan2(hit.x, hit.z); if (phi < 0.0) phi += TWO_PI; double theta = atan2(hit.y, sqrt(hit.x * hit.x + hit.z * hit.z) - a); if (theta < 0.0) theta += TWO_PI; bool good_theta; if (theta_max < theta_min) { good_theta = ((theta_min <= theta && theta <= 360) || (0 <= theta && theta <= theta_max)); } else { good_theta = (theta_min <= theta && theta <= theta_max); } if (phi_min <= phi && phi <= phi_max && good_theta) { intersected = true; t = roots[j]; } } } } if(!intersected) return false; tmin = t; return true; }