This commit is contained in:
2022-06-30 09:54:25 +02:00
commit a86dbb516c
9 changed files with 721 additions and 0 deletions

64
src/hittable.rs Normal file
View File

@ -0,0 +1,64 @@
use crate::{Point3, Ray, Vec3};
use crate::material::{Material};
#[derive(Debug, Clone, Copy)]
pub struct HitRecord<'material> {
pub point: Point3,
pub normal: Vec3,
pub t: f64,
pub front_face: bool,
pub material: &'material Material
}
pub trait Hittable {
fn hit(&self, ray: &Ray, t_min: f64, t_max: f64) -> Option<HitRecord>;
}
pub struct Sphere {
pub center: Point3,
pub radius: f64,
pub material: Material
}
impl Sphere {
pub fn new(center: Point3, radius: f64, material: Material) -> Sphere {
Sphere { center, radius, material }
}
}
impl Default for Sphere {
fn default() -> Self {
Sphere {
center: Point3::default(),
radius: 0.0,
material: Material::default()
}
}
}
impl Hittable for Sphere {
fn hit(&self, ray: &Ray, t_min: f64, t_max: f64) -> Option<HitRecord> {
let oc = &ray.origin() - &self.center;
let a = ray.direction().length_squared();
let half_b = oc.dot(&ray.direction());
let c = oc.length_squared() - &self.radius * &self.radius;
let discriminant = half_b * half_b - a * c;
if discriminant < 0.0 { return None; }
let sqrtd = f64::sqrt(discriminant);
let root = (-half_b - sqrtd) / a;
if root < t_min || t_max < root {
let root = (-half_b + sqrtd) / a;
if root < t_min || t_max < root { return None; }
}
let point = ray.at(root);
let normal = (point - self.center) / self.radius;
let front_face = ray.direction().dot(&normal) < 0.0;
let normal = if front_face { normal } else { -normal };
Some(HitRecord {
point,
normal,
t: root,
front_face,
material: &self.material
})
}
}