Silenced/fixed the last of the clippy warnings.
This commit is contained in:
parent
c73db2edbe
commit
e3a9cbef84
|
@ -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<Vec<XYZ>>,
|
||||
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,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -377,6 +377,7 @@ pub struct LightPath {
|
|||
color: Float4,
|
||||
}
|
||||
|
||||
#[allow(clippy::new_ret_no_self)]
|
||||
impl LightPath {
|
||||
fn new(
|
||||
scene: &Scene,
|
||||
|
|
|
@ -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
|
||||
|
|
144
src/scene/mod.rs
144
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<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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
}
|
||||
}
|
|
@ -23,6 +23,7 @@ pub trait Surface: Boundable + Debug + Sync {
|
|||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
#[allow(clippy::large_enum_variant)]
|
||||
pub enum SurfaceIntersection {
|
||||
Miss,
|
||||
Occlude,
|
||||
|
|
Loading…
Reference in New Issue
Block a user