use crate::core::geometry::{ Bounds3f, Normal3f, Point2f, Point3f, Point3fi, Ray, Vector3f, VectorLike, }; use crate::core::interaction::{Interaction, InteractionBase, SimpleInteraction}; use crate::core::light::{ Light, LightBase, LightBounds, LightLiSample, LightSampleContext, LightTrait, LightType, }; use crate::core::spectrum::SpectrumTrait; use crate::spectra::{DenselySampledSpectrum, SampledSpectrum, SampledWavelengths}; use crate::{Float, PI, Ptr, Transform}; use num_traits::Float as NumFloat; #[repr(C)] #[derive(Clone, Copy, Debug)] pub struct PointLight { pub base: LightBase, pub scale: Float, pub i: Ptr, } impl LightTrait for PointLight { fn base(&self) -> &LightBase { &self.base } fn sample_li( &self, ctx: &LightSampleContext, _u: Point2f, lambda: &SampledWavelengths, _allow_incomplete_pdf: bool, ) -> Option { let pi = self .base .render_from_light .apply_to_interval(&Point3fi::default()); let p: Point3f = pi.into(); let wi = (p - ctx.p()).normalize(); let li = self.scale * self.i.sample(lambda) / p.distance_squared(ctx.p()); let base = InteractionBase::new_boundary(p, 0., self.base.medium_interface); let intr = SimpleInteraction::new(base); Some(LightLiSample::new(li, wi, 1., Interaction::Simple(intr))) } fn pdf_li( &self, _ctx: &LightSampleContext, _wi: Vector3f, _allow_incomplete_pdf: bool, ) -> Float { 0. } fn l( &self, _p: Point3f, _n: Normal3f, _uv: Point2f, _w: Vector3f, _lambda: &SampledWavelengths, ) -> SampledSpectrum { todo!() } fn le(&self, _ray: &Ray, _lambda: &SampledWavelengths) -> SampledSpectrum { todo!() } #[cfg(not(target_os = "cuda"))] fn phi(&self, lambda: SampledWavelengths) -> SampledSpectrum { 4. * PI * self.scale * self.i.sample(&lambda) } #[cfg(not(target_os = "cuda"))] fn preprocess(&mut self, _scene_bounds: &Bounds3f) { todo!() } #[cfg(not(target_os = "cuda"))] fn bounds(&self) -> Option { let p = self .base .render_from_light .apply_to_point(Point3f::new(0., 0., 0.)); let phi = 4. * PI * self.scale * self.i.max_value(); Some(LightBounds::new( &Bounds3f::from_points(p, p), Vector3f::new(0., 0., 1.), phi, PI.cos(), (PI / 2.).cos(), false, )) } }