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, VectorLike}; 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::DistantLight; use shared::spectra::RGBColorSpace; use shared::utils::{Ptr, Transform}; use shared::Float; trait CreateDistantLight { fn new(render_from_light: Transform, le: Spectrum, scale: Float) -> Self; } impl CreateDistantLight for DistantLight { fn new(render_from_light: Transform, le: Spectrum, scale: Float) -> Self { let base = LightBase::new( LightType::DeltaDirection, render_from_light, MediumInterface::empty(), ); let lemit = lookup_spectrum(&le); Self { base, lemit: Ptr::from(&*lemit), scale, scene_center: Point3f::default(), scene_radius: 0., } } } pub fn create( render_from_light: Transform, _medium: Option, parameters: &ParameterDictionary, _loc: &FileLoc, _shape: &Shape, _alpha_text: &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.)?; let from = parameters.get_one_point3f("from", Point3f::new(0., 0., 0.))?; let to = parameters.get_one_point3f("to", Point3f::new(0., 0., 1.))?; let w = (from - to).normalize(); let (v1, v2) = w.coordinate_system(); let m: [Float; 16] = [ v1.x(), v2.x(), w.x(), 0., v1.y(), v2.y(), w.y(), 0., v1.z(), v2.z(), w.z(), 0., 0., 0., 0., 1., ]; let t = Transform::from_flat(&m).expect("Could not create transform for DistantLight"); let final_render = render_from_light * t; scale /= spectrum_to_photometric(l); // Adjust scale to meet target illuminance value let e_v = parameters.get_one_float("illuminance", -1.)?; if e_v > 0. { scale *= e_v; } let specific = DistantLight::new(final_render, l, scale); Ok(Light::Distant(specific)) }