From ed224b18cb8b329cbfffce91a35c815fa6ff019b Mon Sep 17 00:00:00 2001 From: Matthew Gordon Date: Thu, 7 Oct 2021 11:23:46 -0400 Subject: [PATCH] Add random_distributions::LinearWeighted --- src/integrators/simple_random_integrator.rs | 2 +- src/integrators/whitted_integrator.rs | 2 +- src/random_distributions/linear_weighted.rs | 67 +++++++++++++++++++++ src/random_distributions/mod.rs | 3 + 4 files changed, 72 insertions(+), 2 deletions(-) create mode 100644 src/random_distributions/linear_weighted.rs diff --git a/src/integrators/simple_random_integrator.rs b/src/integrators/simple_random_integrator.rs index 89db98d..b24863c 100644 --- a/src/integrators/simple_random_integrator.rs +++ b/src/integrators/simple_random_integrator.rs @@ -1,6 +1,6 @@ -use crate::math::Vec3; use crate::colour::{ColourRgbF, Photon, Spectrum}; use crate::materials::MaterialSampleResult; +use crate::math::Vec3; use crate::raycasting::{IntersectionInfo, Ray}; use crate::sampler::Sampler; use crate::util::algebra_utils::try_change_of_basis_matrix; diff --git a/src/integrators/whitted_integrator.rs b/src/integrators/whitted_integrator.rs index c6e0198..3875c26 100644 --- a/src/integrators/whitted_integrator.rs +++ b/src/integrators/whitted_integrator.rs @@ -1,6 +1,6 @@ -use crate::math::Vec3; use crate::colour::{Photon, Spectrum}; use crate::materials::MaterialSampleResult; +use crate::math::Vec3; use crate::raycasting::{IntersectionInfo, Ray}; use crate::sampler::Sampler; use crate::util::algebra_utils::try_change_of_basis_matrix; diff --git a/src/random_distributions/linear_weighted.rs b/src/random_distributions/linear_weighted.rs new file mode 100644 index 0000000..705d990 --- /dev/null +++ b/src/random_distributions/linear_weighted.rs @@ -0,0 +1,67 @@ +use rand::distributions::Open01; +use rand::{thread_rng, Rng}; + +use super::RandomDistribution; + +pub struct LinearWeighted { + max_value: f64, +} + +impl LinearWeighted { + pub fn new(max_value: f64) -> LinearWeighted { + LinearWeighted { max_value } + } +} + +impl RandomDistribution for LinearWeighted { + fn value(&self) -> f64 { + let mut rng = thread_rng(); + rng.sample::(Open01).sqrt() * self.max_value + } + + fn pdf(&self, value: f64) -> f64 { + 2.0 * value / (self.max_value * self.max_value) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + #[ignore] + fn print_values() { + let target = LinearWeighted::new(2.0); + for _ in 0..1000 { + let value = target.value(); + println!("{}", value); + } + } + + #[test] + #[ignore] + fn print_buckets() { + let mut buckets = [0; 20]; + let target = LinearWeighted::new(20.0); + for _ in 0..10000 { + let value = target.value(); + let i = value as usize; + buckets[i] += 1; + } + for count in buckets { + println!("{}", count); + } + } + + #[test] + #[ignore] + fn integral_is_near_area() { + let target = LinearWeighted::new(2.0); + let integral = (0..100000) + .map(|_| target.value()) + .map(|value| 1.0 / target.pdf(value)) + .sum::() + / 100000.0; + println!("Area: {}\nIntegral: {}", 2.0, integral); + } +} diff --git a/src/random_distributions/mod.rs b/src/random_distributions/mod.rs index b63ccd8..b259ca3 100644 --- a/src/random_distributions/mod.rs +++ b/src/random_distributions/mod.rs @@ -10,6 +10,9 @@ pub use uniform_hemisphere::UniformHemisphere; mod cosine_weighted_hemisphere; pub use cosine_weighted_hemisphere::CosineWeightedHemisphere; +mod linear_weighted; +pub use linear_weighted::LinearWeighted; + pub trait RandomDistribution { fn value(&self) -> T; fn pdf(&self, value: T) -> f64;