bool Torus::shadowHit(const Ray& ray, float& tmin) const { if(!castsShadows) return false; if(!bbox.hit(ray)) return false; glm::vec3 origin = ray.getOrigin(); glm::vec3 dir = ray.getDirection(); float coefs[5]; float roots[4]; //define coefficients float sumDSquared = glm::dot(dir,dir); float e = glm::dot(origin,origin) - sweptRadiusSQ - tubeRadiusSQ; float f = glm::dot(origin,dir); float fourASquared = 4.0f * sweptRadiusSQ; coefs[0] = e * e - fourASquared * (tubeRadiusSQ - origin.y * origin.y); coefs[1] = 4.0f * f * e + 2.0f * fourASquared * origin.y * dir.y; coefs[2] = 2.0f * sumDSquared * e + 4.0f * f * f + fourASquared * dir.y * dir.y; coefs[3] = 4.0f * sumDSquared * f; coefs[4] = sumDSquared * sumDSquared; int numRealRoots = solveQuartic(coefs,roots); bool intersected = false; float t = kHugeValue; if(numRealRoots == 0) return false; for(int i=0;i<numRealRoots;i++) if(roots[i] > KEpsilon) { intersected = true; if(roots[i] < t) t = roots[i]; } if(!intersected) return false; tmin = t; return true; }
float TorusObject::hit_test(const Ray &ray, Vector &normal, const Point *max_pos, bool *inside) { Ray inv_ray; inv_ray.origin = mul_point(inv_trans, ray.origin); inv_ray.direction = mul_vec(inv_trans, ray.direction); inv_ray.direction.normalize(); double x1 = inv_ray.origin.x; double y1 = inv_ray.origin.y; double z1 = inv_ray.origin.z; double d1 = inv_ray.direction.x; double d2 = inv_ray.direction.y; double d3 = inv_ray.direction.z; double coeffs[5]; // coefficient array double roots[4]; // solution array //define the coefficients double sum_d_sqrd = d1*d1 + d2*d2 + d3*d3; double e = x1*x1 + y1*y1 + z1*z1 - radius*radius - thickness*thickness; double f = x1*d1 + y1*d2 + z1*d3; double four_a_sqrd = 4.0 * radius*radius; coeffs[0] = e*e - four_a_sqrd * (thickness*thickness-y1*y1); // constante 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 //fin the roots int num_real_roots = solveQuartic(coeffs, roots); bool intersected = false; double t = FLT_MAX; if ( num_real_roots == 0) // ray misses the torus return -1.0; //find the smallest root greater than FLT_EPSILON, if any for( int j = 0; j < num_real_roots; j++) { if(roots[j] > FLT_EPSILON) { intersected = true; if(roots[j] < t) t = roots[j]; } } double max_t; if(max_pos) max_t = (max_pos->x - ray.origin.x) / ray.direction.x; else max_t = FLT_MAX; if( t > max_t || !intersected) return -1.0; Point hit = inv_ray.origin + t*inv_ray.direction; normal = compute_normal(hit); normal = mul_vec(inv_trans, normal); normal.normalize(); return t; }