A src/hittable.rs => src/hittable.rs +13 -0
@@ 0,0 1,13 @@
+use crate::vec3::*;
+use crate::ray::*;
+
+#[derive(Debug, Clone, Copy, Default)]
+pub struct HitRecord {
+ pub p: Point3,
+ pub normal: Vec3,
+ pub t: f64,
+}
+
+pub trait Hittable {
+ fn hit(&self, r: &Ray, t_min: f64, t_max: f64) -> Option<HitRecord>;
+}
M src/main.rs => src/main.rs +6 -0
@@ 4,6 4,12 @@ use vec3::*;
mod ray;
use ray::*;
+mod hittable;
+use hittable::*;
+
+mod sphere;
+use sphere::*;
+
fn hit_sphere(center: &Point3, radius: f64, r: &Ray) -> f64 {
let oc = r.origin() - *center;
let a = r.direction().length_squared();
A src/sphere.rs => src/sphere.rs +47 -0
@@ 0,0 1,47 @@
+use crate::vec3::*;
+use crate::ray::*;
+use crate::hittable::*;
+
+#[derive(Debug, Clone, Copy, Default)]
+pub struct Sphere {
+ center: Point3,
+ radius: f64,
+}
+
+impl Sphere {
+ fn new(center: Point3, radius: f64) -> Self {
+ Self{center, radius}
+ }
+}
+
+impl Hittable for Sphere {
+ fn hit(&self, r: &Ray, t_min: f64, t_max: f64) -> Option<HitRecord> {
+ let oc = r.origin() - self.center;
+ let a = r.direction().length_squared();
+ let half_b = dot(&oc, &r.direction());
+ let c = oc.length_squared() - self.radius*self.radius;
+ let discriminant = half_b*half_b - a*c;
+
+ if discriminant > 0.0 {
+ let root = discriminant.sqrt();
+
+ let temp = (-half_b - root) / a;
+ if temp < t_max && temp > t_min {
+ let t = temp;
+ let p = r.at(t);
+ let normal = (p - self.center) / self.radius;
+ return Some(HitRecord{t, p, normal})
+ }
+
+ let temp = (-half_b + root) / a;
+ if temp < t_max && temp > t_min {
+ let t = temp;
+ let p = r.at(t);
+ let normal = (p - self.center) / self.radius;
+ return Some(HitRecord{t, p, normal})
+ }
+ }
+
+ return None;
+ }
+}