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;
|
||||||
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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
|
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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
|
||||||
|
|
144
src/scene/mod.rs
144
src/scene/mod.rs
|
@ -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,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -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)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
|
#[allow(clippy::large_enum_variant)]
|
||||||
pub enum SurfaceIntersection {
|
pub enum SurfaceIntersection {
|
||||||
Miss,
|
Miss,
|
||||||
Occlude,
|
Occlude,
|
||||||
|
|
Loading…
Reference in New Issue
Block a user