From e3a9cbef841ab468690ab83ad96bce37a3d566c5 Mon Sep 17 00:00:00 2001 From: Nathan Vegdahl Date: Sun, 16 Dec 2018 11:48:01 -0800 Subject: [PATCH] Silenced/fixed the last of the clippy warnings. --- src/image.rs | 7 +- src/main.rs | 2 + src/renderer.rs | 1 + src/scene/assembly.rs | 6 +- src/scene/mod.rs | 144 +++++++++++++++++++++++++++++++++++++++++- src/scene/scene.rs | 144 ------------------------------------------ src/surface/mod.rs | 1 + 7 files changed, 155 insertions(+), 150 deletions(-) delete mode 100644 src/scene/scene.rs diff --git a/src/image.rs b/src/image.rs index f6d9009..fbfd96f 100644 --- a/src/image.rs +++ b/src/image.rs @@ -6,7 +6,6 @@ use std::fs::File; use std::io; use std::io::Write; use std::marker::PhantomData; -use std::mem; use std::path::Path; use std::sync::Mutex; @@ -17,6 +16,7 @@ use png_encode_mini; use color::{xyz_to_rec709_e, XYZ}; #[derive(Debug)] +#[allow(clippy::type_complexity)] pub struct Image { data: UnsafeCell>, res: (usize, usize), @@ -87,7 +87,10 @@ impl Image { Bucket { min: min, max: max, - img: unsafe { mem::transmute(self as *const Image) }, + // This cast to `*mut` is okay, because we have already dynamically + // ensured earlier in this function that the same memory locations + // aren't aliased. + img: self as *const Image as *mut Image, _phantom: PhantomData, } } diff --git a/src/main.rs b/src/main.rs index a24521a..601a2c9 100644 --- a/src/main.rs +++ b/src/main.rs @@ -10,6 +10,7 @@ #![allow(clippy::cast_lossless)] #![allow(clippy::needless_range_loop)] #![allow(clippy::excessive_precision)] + extern crate bvh_order; extern crate color as color_util; extern crate float4; @@ -81,6 +82,7 @@ use timer::Timer; const VERSION: &str = env!("CARGO_PKG_VERSION"); +#[allow(clippy::cyclomatic_complexity)] fn main() { let mut t = Timer::new(); diff --git a/src/renderer.rs b/src/renderer.rs index 24a4c40..3c0bf36 100644 --- a/src/renderer.rs +++ b/src/renderer.rs @@ -377,6 +377,7 @@ pub struct LightPath { color: Float4, } +#[allow(clippy::new_ret_no_self)] impl LightPath { fn new( scene: &Scene, diff --git a/src/scene/assembly.rs b/src/scene/assembly.rs index 4217238..45b252b 100644 --- a/src/scene/assembly.rs +++ b/src/scene/assembly.rs @@ -37,6 +37,8 @@ pub struct Assembly<'a> { pub light_accel: LightTree<'a>, } +// TODO: actually fix this clippy warning, rather than `allow`ing it. +#[allow(clippy::type_complexity)] impl<'a> Assembly<'a> { // Returns (light_color, (sample_point, normal, point_err), pdf, selection_pdf) pub fn sample_lights( @@ -247,7 +249,7 @@ impl<'a> AssemblyBuilder<'a> { *self .surface_shader_map .get(name) - .expect(&format!("Unknown surface shader '{}'.", name)) + .unwrap_or_else(|| panic!("Unknown surface shader '{}'.", name)) }), id: self.instances.len(), transform_indices: xforms @@ -261,7 +263,7 @@ impl<'a> AssemblyBuilder<'a> { *self .surface_shader_map .get(name) - .expect(&format!("Unknown surface shader '{}'.", name)) + .unwrap_or_else(|| panic!("Unknown surface shader '{}'.", name)) }), id: self.instances.len(), transform_indices: xforms diff --git a/src/scene/mod.rs b/src/scene/mod.rs index 4ca8ed8..1c5c49e 100644 --- a/src/scene/mod.rs +++ b/src/scene/mod.rs @@ -1,7 +1,147 @@ mod assembly; -mod scene; mod world; +use accel::LightAccel; +use algorithm::weighted_choice; +use camera::Camera; +use color::SpectralSample; +use math::{Normal, Point, Vector}; +use surface::SurfaceIntersection; +use transform_stack::TransformStack; + pub use self::assembly::{Assembly, AssemblyBuilder, InstanceType, Object}; -pub use self::scene::{Scene, SceneLightSample}; pub use self::world::World; + +#[derive(Debug)] +pub struct Scene<'a> { + pub name: Option, + pub camera: Camera<'a>, + pub world: World<'a>, + pub root: Assembly<'a>, +} + +impl<'a> Scene<'a> { + pub fn sample_lights( + &self, + xform_stack: &mut TransformStack, + n: f32, + uvw: (f32, f32, f32), + wavelength: f32, + time: f32, + intr: &SurfaceIntersection, + ) -> SceneLightSample { + // TODO: this just selects between world lights and local lights + // with a 50/50 chance. We should do something more sophisticated + // than this, accounting for the estimated impact of the lights + // on the point being lit. + + // Calculate relative probabilities of traversing into world lights + // or local lights. + let wl_energy = if self + .world + .lights + .iter() + .fold(0.0, |energy, light| energy + light.approximate_energy()) + <= 0.0 + { + 0.0 + } else { + 1.0 + }; + let ll_energy = if self.root.light_accel.approximate_energy() <= 0.0 { + 0.0 + } else { + 1.0 + }; + let tot_energy = wl_energy + ll_energy; + + // Decide either world or local lights, and select and sample a light. + if tot_energy <= 0.0 { + return SceneLightSample::None; + } else { + let wl_prob = wl_energy / tot_energy; + + if n < wl_prob { + // World lights + let n = n / wl_prob; + let (i, p) = weighted_choice(self.world.lights, n, |l| l.approximate_energy()); + let (ss, sv, pdf) = + self.world.lights[i].sample_from_point(uvw.0, uvw.1, wavelength, time); + return SceneLightSample::Distant { + color: ss, + direction: sv, + pdf: pdf, + selection_pdf: p * wl_prob, + }; + } else { + // Local lights + let n = (n - wl_prob) / (1.0 - wl_prob); + + if let Some((ss, sgeo, pdf, spdf)) = + self.root + .sample_lights(xform_stack, n, uvw, wavelength, time, intr) + { + return SceneLightSample::Surface { + color: ss, + sample_geo: sgeo, + pdf: pdf, + selection_pdf: spdf * (1.0 - wl_prob), + }; + } else { + return SceneLightSample::None; + } + } + } + } +} + +#[derive(Debug, Copy, Clone)] +pub enum SceneLightSample { + None, + Distant { + color: SpectralSample, + direction: Vector, + pdf: f32, + selection_pdf: f32, + }, + Surface { + color: SpectralSample, + sample_geo: (Point, Normal, f32), + pdf: f32, + selection_pdf: f32, + }, +} + +impl SceneLightSample { + pub fn is_none(&self) -> bool { + if let SceneLightSample::None = *self { + true + } else { + false + } + } + + pub fn color(&self) -> SpectralSample { + match *self { + SceneLightSample::None => panic!(), + SceneLightSample::Distant { color, .. } => color, + SceneLightSample::Surface { color, .. } => color, + } + } + + pub fn pdf(&self) -> f32 { + match *self { + SceneLightSample::None => panic!(), + SceneLightSample::Distant { pdf, .. } => pdf, + SceneLightSample::Surface { pdf, .. } => pdf, + } + } + + pub fn selection_pdf(&self) -> f32 { + match *self { + SceneLightSample::None => panic!(), + SceneLightSample::Distant { selection_pdf, .. } => selection_pdf, + SceneLightSample::Surface { selection_pdf, .. } => selection_pdf, + } + } +} diff --git a/src/scene/scene.rs b/src/scene/scene.rs deleted file mode 100644 index 1ba3481..0000000 --- a/src/scene/scene.rs +++ /dev/null @@ -1,144 +0,0 @@ -use accel::LightAccel; -use algorithm::weighted_choice; -use camera::Camera; -use color::SpectralSample; -use math::{Normal, Point, Vector}; -use surface::SurfaceIntersection; -use transform_stack::TransformStack; - -use super::Assembly; -use super::World; - -#[derive(Debug)] -pub struct Scene<'a> { - pub name: Option, - pub camera: Camera<'a>, - pub world: World<'a>, - pub root: Assembly<'a>, -} - -impl<'a> Scene<'a> { - pub fn sample_lights( - &self, - xform_stack: &mut TransformStack, - n: f32, - uvw: (f32, f32, f32), - wavelength: f32, - time: f32, - intr: &SurfaceIntersection, - ) -> SceneLightSample { - // TODO: this just selects between world lights and local lights - // with a 50/50 chance. We should do something more sophisticated - // than this, accounting for the estimated impact of the lights - // on the point being lit. - - // Calculate relative probabilities of traversing into world lights - // or local lights. - let wl_energy = if self - .world - .lights - .iter() - .fold(0.0, |energy, light| energy + light.approximate_energy()) - <= 0.0 - { - 0.0 - } else { - 1.0 - }; - let ll_energy = if self.root.light_accel.approximate_energy() <= 0.0 { - 0.0 - } else { - 1.0 - }; - let tot_energy = wl_energy + ll_energy; - - // Decide either world or local lights, and select and sample a light. - if tot_energy <= 0.0 { - return SceneLightSample::None; - } else { - let wl_prob = wl_energy / tot_energy; - - if n < wl_prob { - // World lights - let n = n / wl_prob; - let (i, p) = weighted_choice(self.world.lights, n, |l| l.approximate_energy()); - let (ss, sv, pdf) = - self.world.lights[i].sample_from_point(uvw.0, uvw.1, wavelength, time); - return SceneLightSample::Distant { - color: ss, - direction: sv, - pdf: pdf, - selection_pdf: p * wl_prob, - }; - } else { - // Local lights - let n = (n - wl_prob) / (1.0 - wl_prob); - - if let Some((ss, sgeo, pdf, spdf)) = - self.root - .sample_lights(xform_stack, n, uvw, wavelength, time, intr) - { - return SceneLightSample::Surface { - color: ss, - sample_geo: sgeo, - pdf: pdf, - selection_pdf: spdf * (1.0 - wl_prob), - }; - } else { - return SceneLightSample::None; - } - } - } - } -} - -#[derive(Debug, Copy, Clone)] -pub enum SceneLightSample { - None, - Distant { - color: SpectralSample, - direction: Vector, - pdf: f32, - selection_pdf: f32, - }, - Surface { - color: SpectralSample, - sample_geo: (Point, Normal, f32), - pdf: f32, - selection_pdf: f32, - }, -} - -impl SceneLightSample { - pub fn is_none(&self) -> bool { - if let SceneLightSample::None = *self { - true - } else { - false - } - } - - pub fn color(&self) -> SpectralSample { - match *self { - SceneLightSample::None => panic!(), - SceneLightSample::Distant { color, .. } => color, - SceneLightSample::Surface { color, .. } => color, - } - } - - pub fn pdf(&self) -> f32 { - match *self { - SceneLightSample::None => panic!(), - SceneLightSample::Distant { pdf, .. } => pdf, - SceneLightSample::Surface { pdf, .. } => pdf, - } - } - - pub fn selection_pdf(&self) -> f32 { - match *self { - SceneLightSample::None => panic!(), - SceneLightSample::Distant { selection_pdf, .. } => selection_pdf, - SceneLightSample::Surface { selection_pdf, .. } => selection_pdf, - } - } -} diff --git a/src/surface/mod.rs b/src/surface/mod.rs index 453a1eb..8af0c56 100644 --- a/src/surface/mod.rs +++ b/src/surface/mod.rs @@ -23,6 +23,7 @@ pub trait Surface: Boundable + Debug + Sync { } #[derive(Debug, Copy, Clone)] +#[allow(clippy::large_enum_variant)] pub enum SurfaceIntersection { Miss, Occlude,