42 lines
1.4 KiB
C++
42 lines
1.4 KiB
C++
#include "Sphere.h"
|
|
#include "Ray.h"
|
|
|
|
bool Sphere::intersect(
|
|
const Ray &ray, const double min_t, double &t, Eigen::Vector3d &n) const {
|
|
/* Based on
|
|
* Fundamentals in Computer Graphics - Fourth Edition, Chapter 4.4.1. Ray-Sphere Intersection.
|
|
* Steve Marschner & Peter Shirley
|
|
*/
|
|
|
|
/* Intersection points occur when points on the ray satisfy the implicit equation. */
|
|
|
|
const double a = ray.direction.dot(ray.direction);
|
|
const double b = ray.direction.dot(ray.origin - center);
|
|
const double c = (ray.origin - center).dot(ray.origin - center) - radius * radius;
|
|
const double discriminant = (2 * b) * (2 * b) - 4 * a * c;
|
|
|
|
/* If the discriminant is less than zero, the ray does not intersect with the sphere. */
|
|
if (discriminant < 0) return false;
|
|
|
|
/* Calculate the first intersection t. */
|
|
const double under_root = b * b - a * c;
|
|
const double ta = (0 - b - sqrt(under_root)) / a;
|
|
double tb = (0 - b + sqrt(under_root)) / a;
|
|
/* Choose the smallest that is still larger than min_t. */
|
|
if (ta < min_t && tb < min_t) {
|
|
return false;
|
|
} else if (ta < min_t) {
|
|
t = tb;
|
|
} else if (tb < min_t) {
|
|
t = ta;
|
|
} else {
|
|
t = std::min(ta, tb);
|
|
}
|
|
|
|
/* Calculate the surface normal vector at the point of intersection. */
|
|
n = 2 * (ray.origin + t * ray.direction - center);
|
|
/* Normalize the vector. */
|
|
n = n.normalized();
|
|
|
|
return true;
|
|
}
|