Beginnings of parsing sphere lights.

This commit is contained in:
Nathan Vegdahl 2016-06-23 20:46:57 -07:00
parent 1cbf20e67f
commit c2d36e0d14
6 changed files with 79 additions and 7 deletions

View File

@ -4,6 +4,7 @@ use math::Matrix4x4;
use bvh::BVH; use bvh::BVH;
use boundable::Boundable; use boundable::Boundable;
use surface::Surface; use surface::Surface;
use light::LightSource;
use bbox::{BBox, transform_bbox_slice_from}; use bbox::{BBox, transform_bbox_slice_from};
@ -160,6 +161,7 @@ impl AssemblyBuilder {
let obj = &self.objects[inst.data_index]; let obj = &self.objects[inst.data_index];
match obj { match obj {
&Object::Surface(ref s) => bbs.extend(s.bounds()), &Object::Surface(ref s) => bbs.extend(s.bounds()),
&Object::Light(_) => unimplemented!(),
} }
} }
@ -193,6 +195,7 @@ impl AssemblyBuilder {
#[derive(Debug)] #[derive(Debug)]
pub enum Object { pub enum Object {
Surface(Box<Surface>), Surface(Box<Surface>),
Light(Box<LightSource>),
} }

View File

@ -1,11 +1,14 @@
mod sphere_light; mod sphere_light;
// pub use sphere_light::{SphereLight}; use std::fmt::Debug;
pub use self::sphere_light::SphereLight;
use math::{Vector, Point}; use math::{Vector, Point};
use color::SpectralSample; 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. /// Samples the light source for a given point to be illuminated.
/// ///
/// - arr: The point to be illuminated. /// - arr: The point to be illuminated.
@ -49,7 +52,7 @@ pub trait LightSource {
/// - dir: The direction of the outgoing light. /// - dir: The direction of the outgoing light.
/// - u: Random parameter U. /// - u: Random parameter U.
/// - v: Random parameter V. /// - 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. /// - time: The time to sample at.
fn outgoing(&self, dir: Vector, u: f32, v: f32, wavelength: f32, time: f32) -> SpectralSample; fn outgoing(&self, dir: Vector, u: f32, v: f32, wavelength: f32, time: f32) -> SpectralSample;

View File

@ -1,5 +1,6 @@
use math::{Vector, Point, coordinate_system_from_vector}; use math::{Vector, Point, coordinate_system_from_vector};
use bbox::BBox; use bbox::BBox;
use boundable::Boundable;
use color::{XYZ, SpectralSample, Color}; use color::{XYZ, SpectralSample, Color};
use super::LightSource; use super::LightSource;
use lerp::lerp_slice; 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::f64::consts::PI as PI_64;
use std::f32::consts::PI as PI_32; use std::f32::consts::PI as PI_32;
#[derive(Debug)]
pub struct SphereLight { pub struct SphereLight {
positions: Vec<Point>,
radii: Vec<f32>, radii: Vec<f32>,
colors: Vec<XYZ>, colors: Vec<XYZ>,
bounds_: Vec<BBox>, bounds_: Vec<BBox>,
} }
impl SphereLight { impl SphereLight {
fn new() -> SphereLight { pub fn new(radii: Vec<f32>, colors: Vec<XYZ>) -> SphereLight {
unimplemented!() unimplemented!()
} }
} }
@ -29,7 +30,7 @@ impl LightSource for SphereLight {
time: f32) time: f32)
-> (SpectralSample, Vector, f32) { -> (SpectralSample, Vector, f32) {
// Calculate time interpolated values // 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 radius: f64 = lerp_slice(&self.radii, time) as f64;
let col = lerp_slice(&self.colors, time); let col = lerp_slice(&self.colors, time);
let surface_area_inv: f64 = 1.0 / (4.0 * PI_64 * radius * radius); let surface_area_inv: f64 = 1.0 / (4.0 * PI_64 * radius * radius);
@ -98,7 +99,7 @@ impl LightSource for SphereLight {
wavelength: f32, wavelength: f32,
time: f32) time: f32)
-> 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 radius: f64 = lerp_slice(&self.radii, time) as f64;
let d2: f64 = (pos - arr).length2() as f64; // Distance from center of sphere squared let d2: f64 = (pos - arr).length2() as f64; // Distance from center of sphere squared
@ -127,3 +128,9 @@ impl LightSource for SphereLight {
false false
} }
} }
impl Boundable for SphereLight {
fn bounds<'a>(&'a self) -> &'a [BBox] {
&self.bounds_
}
}

View File

@ -2,6 +2,7 @@ mod data_tree;
mod psy; mod psy;
mod psy_assembly; mod psy_assembly;
mod psy_mesh_surface; mod psy_mesh_surface;
mod psy_light;
pub mod basics; pub mod basics;
pub use self::data_tree::DataTree; pub use self::data_tree::DataTree;

56
src/parse/psy_light.rs Normal file
View File

@ -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<SphereLight, PsyParseError> {
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);
}
}

View File

@ -115,6 +115,8 @@ impl<'a> Tracer<'a> {
&Object::Surface(ref surface) => { &Object::Surface(ref surface) => {
surface.intersect_rays(rays, wrays, &mut self.isects, self.xform_stack.top()); surface.intersect_rays(rays, wrays, &mut self.isects, self.xform_stack.top());
} }
&Object::Light(_) => unimplemented!(),
} }
} }
} }