void Sphere::raycast(const Raycast& ray, RayHitList& reports) const { double a, b, c; params(ray, a, b, c); double discr = b*b - 4*a*c; if(discr > 0.0) { double disrcSqrt = glm::sqrt(discr); double t1 = (-b - disrcSqrt) / (2 * a); if(0.0 < t1 && t1 < ray.limit) { glm::dvec3 pt = ray.origin + ray.direction*t1; glm::dvec3 n = glm::normalize(pt - _center); reports.add(t1, ray, pt, n, RayHitReport::NO_TEXCOORD, _coating.get()); } double t2 = (-b + disrcSqrt) / (2 * a); if(0.0 < t2 && t2 < ray.limit) { glm::dvec3 pt = ray.origin + ray.direction*t2; glm::dvec3 n = glm::normalize(pt - _center); reports.add(t2, ray, pt, n, RayHitReport::NO_TEXCOORD, _coating.get()); } } else if(discr == 0.0) { double t = -b / (2 * a); if(0.0 < t && t < ray.limit) { glm::dvec3 pt = ray.origin + ray.direction*t; glm::dvec3 n = glm::normalize(pt - _center); reports.add(t, ray, pt, n, RayHitReport::NO_TEXCOORD, _coating.get()); } } }
void Disk::raycast(const Raycast& ray, RayHitList& reports) const { glm::dvec3 orig = glm::dvec3(_invTransform * glm::dvec4(ray.origin, 1.0)); glm::dvec3 dir = glm::dvec3(_invTransform * glm::dvec4(ray.direction, 0.0)); double dirDotNorm = glm::dot(_normal, dir); if(dirDotNorm != 0.0) { double t = -(glm::dot(_normal, orig) + _d) / dirDotNorm; if(0.0 < t && t < ray.limit) { if(glm::distance(orig + dir * t, _center) < _radius) { glm::dvec3 pt = ray.origin + ray.direction * t; reports.add(t, pt, _transformN, RayHitReport::NO_TEXCOORD, _coating.get(), _innerMat.get(), _outerMat.get()); } } } }
// ref : http://marctenbosch.com/photon/mbosch_intersection.pdf void Quadric::raycast(const Raycast& ray, RayHitList& reports) const { double a, b, c; params(ray, a, b, c); if(a != 0.0) { double dscr = b*b - 4*a*c; if(dscr > 0.0) { double dsrcSqrt = glm::sqrt(dscr); { double t = (-b - dsrcSqrt) / (2 * a); if(0.0 < t && t < ray.limit) { glm::dvec3 pt1 = ray.origin + ray.direction*t; glm::dvec3 n1 = computeNormal(_q, pt1); reports.add(t, ray, pt1, n1, RayHitReport::NO_TEXCOORD, _coating.get()); } } { double t = (-b + dsrcSqrt) / (2 * a); if(0.0 < t && t < ray.limit) { glm::dvec3 pt2 = ray.origin + ray.direction*t; glm::dvec3 n2 = computeNormal(_q, pt2); reports.add(t, ray, pt2, n2, RayHitReport::NO_TEXCOORD, _coating.get()); } } } else if (dscr == 0.0) { double t = -b / (2 * a); if(0.0 < t && t < ray.limit) { glm::dvec3 pt = ray.origin + ray.direction*t; glm::dvec3 n = computeNormal(_q, pt); reports.add(t, ray, pt, n, RayHitReport::NO_TEXCOORD, _coating.get()); } } } else { if(b != 0.0) { double t = -c / b; if(0.0 < t && t < ray.limit) { glm::dvec3 pt = ray.origin + ray.direction * t; glm::dvec3 n = computeNormal(_q, pt); reports.add(t, ray, pt, n, RayHitReport::NO_TEXCOORD, _coating.get()); } } } }