use crate::hittable::HitRecord; use crate::ray::Ray; use crate::vec3::{Color, random_unit_vector, reflect}; pub struct Material { } pub trait Scatter: { fn scatter(&self, r_in: &Ray, rec: HitRecord, attenuation: &mut Color, scattered: &mut Ray) -> bool; } pub struct Lambertian { albedo: Color, } impl Lambertian { pub fn new(a: &Color) -> Self { Lambertian { albedo: *a } } } impl Scatter for Lambertian { fn scatter(&self, r_in: &Ray, rec: HitRecord, attenuation: &mut Color, scattered: &mut Ray) -> bool { let scatter_direction = rec.normal + random_unit_vector(); if scatter_direction.near_zero() { scatter_direction = rec.normal; } scattered = &mut Ray::new(rec.p, scatter_direction); attenuation = &mut self.albedo; return true; } } pub struct Metal { pub albedo: Color } impl Metal { pub fn new(a: &Color) -> Self { Metal { albedo: *a } } } impl Scatter for Metal { fn scatter(&self, r_in: &Ray, rec: HitRecord, attenuation: &mut Color, scattered: &mut Ray) -> bool { let reflected = reflect(&r_in.direction(), &rec.normal); scattered = &mut Ray::new(rec.p, rec.normal); attenuation = &mut self.albedo; scattered.direction().dot(&rec.normal) > 0.0 } }