use crate::globals::get_options; use shared::bxdfs::DiffuseBxDF; use shared::core::bsdf::BSDF; use shared::core::bssrdf::BSSRDF; use shared::core::bxdf::BxDF; use shared::core::camera::Camera; use shared::core::geometry::Ray; use shared::core::interaction::{MediumInteraction, SimpleInteraction, SurfaceInteraction}; use shared::core::material::{Material, MaterialEvalContext, MaterialTrait}; use shared::core::sampler::{Sampler, SamplerTrait}; use shared::core::texture::UniversalTextureEvaluator; use shared::spectra::SampledWavelengths; use shared::Ptr; pub trait InteractionGetter { fn get_bsdf( &mut self, r: &Ray, lambda: &SampledWavelengths, camera: &Camera, sampler: &mut Sampler, ) -> Option; fn get_bssrdf( &self, _ray: &Ray, lambda: &SampledWavelengths, _camera: &Camera, ) -> Option; } impl InteractionGetter for SurfaceInteraction { fn get_bsdf( &mut self, r: &Ray, lambda: &SampledWavelengths, camera: &Camera, sampler: &mut Sampler, ) -> Option { self.compute_differentials(r, camera, sampler.samples_per_pixel()); let material = { let Some(mut active_mat) = self.material.get() else { return None; }; let tex_eval = UniversalTextureEvaluator; while let Material::Mix(mix) = active_mat { let ctx = MaterialEvalContext::from(&*self); active_mat = mix.choose_material(&tex_eval, &ctx)?; } *active_mat }; let ctx = MaterialEvalContext::from(&*self); let tex_eval = UniversalTextureEvaluator; let displacement = material.get_displacement(); let normal_map = material .get_normal_map() .map(Ptr::from) .unwrap_or(Ptr::null()); if !displacement.is_null() || !normal_map.is_null() { self.compute_bump_geom(&tex_eval, displacement, normal_map); } let mut bsdf = material.get_bsdf(&tex_eval, &ctx, lambda); if get_options().force_diffuse { let rho = bsdf.rho_wo(self.common.wo, &[sampler.get1d()], &[sampler.get2d()]); let diff_bxdf = BxDF::Diffuse(DiffuseBxDF::new(rho)); bsdf = BSDF::new(self.shading.n, self.shading.dpdu, diff_bxdf); } Some(bsdf) } fn get_bssrdf( &self, _ray: &Ray, lambda: &SampledWavelengths, _camera: &Camera, ) -> Option { let Some(mut active_mat) = self.material.get() else { return None; }; let tex_eval = UniversalTextureEvaluator; while let Material::Mix(mix) = active_mat { let ctx = MaterialEvalContext::from(self); active_mat = mix.choose_material(&tex_eval, &ctx)?; } let material = *active_mat; let ctx = MaterialEvalContext::from(self); material.get_bssrdf(&tex_eval, &ctx, lambda) } } impl InteractionGetter for MediumInteraction { fn get_bsdf( &mut self, _r: &Ray, _lambda: &SampledWavelengths, _camera: &Camera, _sampler: &mut Sampler, ) -> Option { None } fn get_bssrdf( &self, _ray: &Ray, _lambda: &SampledWavelengths, _camera: &Camera, ) -> Option { None } } impl InteractionGetter for SimpleInteraction { fn get_bsdf( &mut self, _r: &Ray, _lambda: &SampledWavelengths, _camera: &Camera, _sampler: &mut Sampler, ) -> Option { None } fn get_bssrdf( &self, _ray: &Ray, _lambda: &SampledWavelengths, _camera: &Camera, ) -> Option { None } }