diff --git a/src/main.rs b/src/main.rs index 322d1ef..4009336 100644 --- a/src/main.rs +++ b/src/main.rs @@ -8,16 +8,22 @@ use indicatif::ProgressBar; use nalgebra::{Point3, Vector3}; use ray::Ray; -fn hit_sphere(center: Point3, radius: f64, ray: &Ray) -> bool { +fn hit_sphere(center: Point3, radius: f64, ray: &Ray) -> Option { let a = ray.dir.magnitude_squared(); let b = (-2.0 * ray.dir).dot(&(center - ray.orig)); let c = (center - ray.orig).magnitude_squared() - radius * radius; - return b * b - 4.0 * a * c > 0.0; + let discriminant = b * b - 4.0 * a * c; + if discriminant < 0.0 { + return None; + } + Some((-b - discriminant.sqrt()) / (2.0 * a)) } fn ray_color(ray: &Ray) -> Vector3 { - if hit_sphere(Point3::new(0.0, 0.0, -1.0), 0.5, ray) { - return Vector3::new(1.0, 0.0, 0.0); + let sphere_center = Point3::new(0.0, 0.0, -1.0); + if let Some(t) = hit_sphere(sphere_center, 0.5, ray) { + let normal = (ray.at(t) - sphere_center).normalize(); + return 0.5 * (normal + Vector3::new(1.0, 1.0, 1.0)); } let dir = ray.dir.normalize(); diff --git a/src/ray.rs b/src/ray.rs index f570691..4330378 100644 --- a/src/ray.rs +++ b/src/ray.rs @@ -9,4 +9,8 @@ impl Ray { pub fn new(orig: Point3, dir: Vector3) -> Self { Self { orig, dir } } + + pub fn at(&self, t: f64) -> Point3 { + self.orig + t * self.dir + } }