Silenced/fixed the last of the clippy warnings.

This commit is contained in:
Nathan Vegdahl 2018-12-16 11:48:01 -08:00
parent c73db2edbe
commit e3a9cbef84
7 changed files with 155 additions and 150 deletions

View File

@ -6,7 +6,6 @@ use std::fs::File;
use std::io; use std::io;
use std::io::Write; use std::io::Write;
use std::marker::PhantomData; use std::marker::PhantomData;
use std::mem;
use std::path::Path; use std::path::Path;
use std::sync::Mutex; use std::sync::Mutex;
@ -17,6 +16,7 @@ use png_encode_mini;
use color::{xyz_to_rec709_e, XYZ}; use color::{xyz_to_rec709_e, XYZ};
#[derive(Debug)] #[derive(Debug)]
#[allow(clippy::type_complexity)]
pub struct Image { pub struct Image {
data: UnsafeCell<Vec<XYZ>>, data: UnsafeCell<Vec<XYZ>>,
res: (usize, usize), res: (usize, usize),
@ -87,7 +87,10 @@ impl Image {
Bucket { Bucket {
min: min, min: min,
max: max, 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, _phantom: PhantomData,
} }
} }

View File

@ -10,6 +10,7 @@
#![allow(clippy::cast_lossless)] #![allow(clippy::cast_lossless)]
#![allow(clippy::needless_range_loop)] #![allow(clippy::needless_range_loop)]
#![allow(clippy::excessive_precision)] #![allow(clippy::excessive_precision)]
extern crate bvh_order; extern crate bvh_order;
extern crate color as color_util; extern crate color as color_util;
extern crate float4; extern crate float4;
@ -81,6 +82,7 @@ use timer::Timer;
const VERSION: &str = env!("CARGO_PKG_VERSION"); const VERSION: &str = env!("CARGO_PKG_VERSION");
#[allow(clippy::cyclomatic_complexity)]
fn main() { fn main() {
let mut t = Timer::new(); let mut t = Timer::new();

View File

@ -377,6 +377,7 @@ pub struct LightPath {
color: Float4, color: Float4,
} }
#[allow(clippy::new_ret_no_self)]
impl LightPath { impl LightPath {
fn new( fn new(
scene: &Scene, scene: &Scene,

View File

@ -37,6 +37,8 @@ pub struct Assembly<'a> {
pub light_accel: LightTree<'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> { impl<'a> Assembly<'a> {
// Returns (light_color, (sample_point, normal, point_err), pdf, selection_pdf) // Returns (light_color, (sample_point, normal, point_err), pdf, selection_pdf)
pub fn sample_lights( pub fn sample_lights(
@ -247,7 +249,7 @@ impl<'a> AssemblyBuilder<'a> {
*self *self
.surface_shader_map .surface_shader_map
.get(name) .get(name)
.expect(&format!("Unknown surface shader '{}'.", name)) .unwrap_or_else(|| panic!("Unknown surface shader '{}'.", name))
}), }),
id: self.instances.len(), id: self.instances.len(),
transform_indices: xforms transform_indices: xforms
@ -261,7 +263,7 @@ impl<'a> AssemblyBuilder<'a> {
*self *self
.surface_shader_map .surface_shader_map
.get(name) .get(name)
.expect(&format!("Unknown surface shader '{}'.", name)) .unwrap_or_else(|| panic!("Unknown surface shader '{}'.", name))
}), }),
id: self.instances.len(), id: self.instances.len(),
transform_indices: xforms transform_indices: xforms

View File

@ -1,7 +1,147 @@
mod assembly; mod assembly;
mod scene;
mod world; 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::assembly::{Assembly, AssemblyBuilder, InstanceType, Object};
pub use self::scene::{Scene, SceneLightSample};
pub use self::world::World; pub use self::world::World;
#[derive(Debug)]
pub struct Scene<'a> {
pub name: Option<String>,
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,
}
}
}

View File

@ -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<String>,
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,
}
}
}

View File

@ -23,6 +23,7 @@ pub trait Surface: Boundable + Debug + Sync {
} }
#[derive(Debug, Copy, Clone)] #[derive(Debug, Copy, Clone)]
#[allow(clippy::large_enum_variant)]
pub enum SurfaceIntersection { pub enum SurfaceIntersection {
Miss, Miss,
Occlude, Occlude,