use crate::core::light::lookup_spectrum; use crate::core::spectrum::spectrum_to_photometric; use crate::core::texture::FloatTexture; use crate::utils::{Arena, FileLoc, ParameterDictionary}; use anyhow::Result; use shared::core::geometry::Point3f; use shared::core::light::{Light, LightBase, LightType}; use shared::core::medium::{Medium, MediumInterface}; use shared::core::shape::Shape; use shared::core::spectrum::Spectrum; use shared::core::texture::SpectrumType; use shared::lights::PointLight; use shared::spectra::RGBColorSpace; use shared::{Float, PI, Transform}; pub trait CreatePointLight { fn new( render_from_light: Transform, medium_interface: MediumInterface, le: Spectrum, scale: Float, arena: &Arena, ) -> Self; } impl CreatePointLight for PointLight { fn new( render_from_light: Transform, medium_interface: MediumInterface, le: Spectrum, scale: Float, arena: &Arena, ) -> Self { let base = LightBase::new( LightType::DeltaPosition, render_from_light, medium_interface, ); let iemit = lookup_spectrum(&le); let i = arena.alloc((*iemit).clone()); Self { base, scale, i } } } pub fn create( render_from_light: Transform, medium: Option, parameters: &ParameterDictionary, _loc: &FileLoc, _shape: &Shape, _alpha: &FloatTexture, colorspace: Option<&RGBColorSpace>, arena: &Arena, ) -> Result { let default_cs = crate::spectra::default_colorspace(); let cs = colorspace.unwrap_or(&default_cs); let l = parameters .get_one_spectrum( "L", Some(Spectrum::Dense(cs.illuminant)), SpectrumType::Illuminant, ) .unwrap(); let mut scale = parameters.get_one_float("scale", 1.)?; scale /= spectrum_to_photometric(l); let phi_v = parameters.get_one_float("power", 1.)?; if phi_v > 0. { let k_e = 4. * PI; scale *= phi_v / k_e; } let from = parameters.get_one_point3f("from", Point3f::zero())?; let tf = Transform::translate(from.into()); let final_render = render_from_light * tf; let mi = match medium { Some(m) => { let ptr = arena.alloc(m); MediumInterface { inside: ptr, outside: ptr, } } None => MediumInterface::default(), }; let specific = PointLight::new(final_render, mi, l, scale, arena); Ok(Light::Point(specific)) }