From c2d36e0d14d6b6db7d9af8c86fe76c00b5e216ff Mon Sep 17 00:00:00 2001 From: Nathan Vegdahl Date: Thu, 23 Jun 2016 20:46:57 -0700 Subject: [PATCH] Beginnings of parsing sphere lights. --- src/assembly.rs | 3 +++ src/light/mod.rs | 9 ++++--- src/light/sphere_light.rs | 15 ++++++++--- src/parse/mod.rs | 1 + src/parse/psy_light.rs | 56 +++++++++++++++++++++++++++++++++++++++ src/tracer.rs | 2 ++ 6 files changed, 79 insertions(+), 7 deletions(-) create mode 100644 src/parse/psy_light.rs diff --git a/src/assembly.rs b/src/assembly.rs index aae90f0..5beff75 100644 --- a/src/assembly.rs +++ b/src/assembly.rs @@ -4,6 +4,7 @@ use math::Matrix4x4; use bvh::BVH; use boundable::Boundable; use surface::Surface; +use light::LightSource; use bbox::{BBox, transform_bbox_slice_from}; @@ -160,6 +161,7 @@ impl AssemblyBuilder { let obj = &self.objects[inst.data_index]; match obj { &Object::Surface(ref s) => bbs.extend(s.bounds()), + &Object::Light(_) => unimplemented!(), } } @@ -193,6 +195,7 @@ impl AssemblyBuilder { #[derive(Debug)] pub enum Object { Surface(Box), + Light(Box), } diff --git a/src/light/mod.rs b/src/light/mod.rs index c88c38c..43baaa3 100644 --- a/src/light/mod.rs +++ b/src/light/mod.rs @@ -1,11 +1,14 @@ mod sphere_light; -// pub use sphere_light::{SphereLight}; +use std::fmt::Debug; + +pub use self::sphere_light::SphereLight; use math::{Vector, Point}; use color::SpectralSample; +use boundable::Boundable; -pub trait LightSource { +pub trait LightSource: Boundable + Debug + Sync { /// Samples the light source for a given point to be illuminated. /// /// - arr: The point to be illuminated. @@ -49,7 +52,7 @@ pub trait LightSource { /// - dir: The direction of the outgoing light. /// - u: Random parameter U. /// - v: Random parameter V. - /// - wavelength: The wavelength of light to sample at. + /// - wavelength: The hero wavelength of light to sample at. /// - time: The time to sample at. fn outgoing(&self, dir: Vector, u: f32, v: f32, wavelength: f32, time: f32) -> SpectralSample; diff --git a/src/light/sphere_light.rs b/src/light/sphere_light.rs index 7ea6343..d2a5018 100644 --- a/src/light/sphere_light.rs +++ b/src/light/sphere_light.rs @@ -1,5 +1,6 @@ use math::{Vector, Point, coordinate_system_from_vector}; use bbox::BBox; +use boundable::Boundable; use color::{XYZ, SpectralSample, Color}; use super::LightSource; use lerp::lerp_slice; @@ -7,15 +8,15 @@ use sampling::{uniform_sample_cone, uniform_sample_cone_pdf, uniform_sample_sphe use std::f64::consts::PI as PI_64; use std::f32::consts::PI as PI_32; +#[derive(Debug)] pub struct SphereLight { - positions: Vec, radii: Vec, colors: Vec, bounds_: Vec, } impl SphereLight { - fn new() -> SphereLight { + pub fn new(radii: Vec, colors: Vec) -> SphereLight { unimplemented!() } } @@ -29,7 +30,7 @@ impl LightSource for SphereLight { time: f32) -> (SpectralSample, Vector, f32) { // Calculate time interpolated values - let pos = lerp_slice(&self.positions, time); + let pos = Point::new(0.0, 0.0, 0.0); // Light position is always at origin let radius: f64 = lerp_slice(&self.radii, time) as f64; let col = lerp_slice(&self.colors, time); let surface_area_inv: f64 = 1.0 / (4.0 * PI_64 * radius * radius); @@ -98,7 +99,7 @@ impl LightSource for SphereLight { wavelength: f32, time: f32) -> f32 { - let pos = lerp_slice(&self.positions, time); + let pos = Point::new(0.0, 0.0, 0.0); // Light position is always at origin let radius: f64 = lerp_slice(&self.radii, time) as f64; let d2: f64 = (pos - arr).length2() as f64; // Distance from center of sphere squared @@ -127,3 +128,9 @@ impl LightSource for SphereLight { false } } + +impl Boundable for SphereLight { + fn bounds<'a>(&'a self) -> &'a [BBox] { + &self.bounds_ + } +} diff --git a/src/parse/mod.rs b/src/parse/mod.rs index a676d72..54ba968 100644 --- a/src/parse/mod.rs +++ b/src/parse/mod.rs @@ -2,6 +2,7 @@ mod data_tree; mod psy; mod psy_assembly; mod psy_mesh_surface; +mod psy_light; pub mod basics; pub use self::data_tree::DataTree; diff --git a/src/parse/psy_light.rs b/src/parse/psy_light.rs new file mode 100644 index 0000000..bb685f9 --- /dev/null +++ b/src/parse/psy_light.rs @@ -0,0 +1,56 @@ +#![allow(dead_code)] + +use std::result::Result; + +use nom::IResult; + +use super::DataTree; +use super::basics::{ws_usize, ws_f32}; +use super::psy::PsyParseError; + +use light::SphereLight; +use math::Point; +use color::XYZ; + +pub fn parse_sphere_light(tree: &DataTree) -> Result { + if let &DataTree::Internal { ref children, .. } = tree { + let mut radii = Vec::new(); + let mut colors = Vec::new(); + + // Parse + for child in children.iter() { + match child { + // Radius + &DataTree::Leaf { type_name, contents } if type_name == "Radius" => { + if let IResult::Done(_, radius) = ws_f32(contents.as_bytes()) { + radii.push(radius); + } else { + // Found radius, but its contents is not in the right format + return Err(PsyParseError::UnknownError); + } + } + + // Color + &DataTree::Leaf { type_name, contents } if type_name == "Color" => { + if let IResult::Done(_, color) = closure!(tuple!(ws_f32, + ws_f32, + ws_f32))(contents.as_bytes()) { + // TODO: handle color space conversions properly. + // Probably will need a special color type with its + // own parser...? + colors.push(XYZ::new(color.0, color.1, color.2)); + } else { + // Found color, but its contents is not in the right format + return Err(PsyParseError::UnknownError); + } + } + + _ => {} + } + } + + return Ok(SphereLight::new(radii, colors)); + } else { + return Err(PsyParseError::UnknownError); + } +} diff --git a/src/tracer.rs b/src/tracer.rs index b62edb5..a647e5e 100644 --- a/src/tracer.rs +++ b/src/tracer.rs @@ -115,6 +115,8 @@ impl<'a> Tracer<'a> { &Object::Surface(ref surface) => { surface.intersect_rays(rays, wrays, &mut self.isects, self.xform_stack.top()); } + + &Object::Light(_) => unimplemented!(), } } }