use super::{ Ray, HitRecord, Color, Vec3, utility, }; pub struct Lambertian { albedo: Color, } pub struct Metal { albedo: Color, } pub struct Mirror { albedo: Color, } pub trait Material: Sync + Send { fn scatter(&self,r_in: &Ray, rec: &HitRecord, attenuation: &mut Color, scattered: &mut Ray) -> bool; } impl Lambertian { pub fn new(a: &Color) -> Self { Lambertian { albedo: a.clone(), } } } impl Material for Lambertian { fn scatter(&self, _r_in: &Ray, rec: &HitRecord, attenuation: &mut Color, scattered: &mut Ray) -> bool { let mut scatter_direction = rec.normal + Vec3::random_unit_vector(); if scatter_direction.near_zero() { scatter_direction = rec.normal; } *scattered = Ray::new(rec.p, scatter_direction); *attenuation = self.albedo.clone(); return true; } } impl Metal { pub fn new(a: &Color) -> Self { Metal { albedo: *a, } } } impl Material for Metal { fn scatter(&self, r_in: &Ray, rec: &HitRecord, attenuation: &mut Color, scattered: &mut Ray) -> bool { let reflected = Vec3::reflect(&Vec3::unit_vector(r_in.direction()), &rec.normal); *scattered = Ray::new(rec.p, reflected); *attenuation = self.albedo.clone(); return Vec3::dot(scattered.direction(), rec.normal) > 0.0; } } impl Mirror { pub fn new(a: &Color) -> Self { Mirror { albedo: *a, } } } impl Material for Mirror { fn scatter(&self, r_in: &Ray, rec: &HitRecord, attenuation: &mut Color, scattered: &mut Ray) -> bool { if utility::random_f64() > 0.8 { // Reflektiert let reflected = Vec3::reflect(&Vec3::unit_vector(r_in.direction()), &rec.normal); *scattered = Ray::new(rec.p, reflected); *attenuation = self.albedo.clone(); return Vec3::dot(scattered.direction(), rec.normal) > 0.0; } else { // Geht geradeaus durch let reflected = r_in.direction().clone(); *scattered = Ray::new(rec.p, reflected); *attenuation = self.albedo.clone(); return true; }; } }