diff --git a/src/random_distributions/mod.rs b/src/random_distributions/mod.rs index d74beca..3e49b86 100644 --- a/src/random_distributions/mod.rs +++ b/src/random_distributions/mod.rs @@ -4,6 +4,9 @@ pub use uniform_square::UniformSquare; mod unit_disc; pub use unit_disc::UnitDisc; +mod uniform_hemisphere; +pub use uniform_hemisphere::UniformHemisphere; + pub trait RandomDistribution { fn value(&self) -> T; } diff --git a/src/random_distributions/uniform_hemisphere.rs b/src/random_distributions/uniform_hemisphere.rs new file mode 100644 index 0000000..506f4f5 --- /dev/null +++ b/src/random_distributions/uniform_hemisphere.rs @@ -0,0 +1,48 @@ +use rand::distributions::{Open01, OpenClosed01}; +use rand::{thread_rng, Rng}; + +use crate::math::Vec3; + +use super::RandomDistribution; + +pub struct UniformHemisphere {} + +impl UniformHemisphere { + pub fn new() -> UniformHemisphere { + UniformHemisphere {} + } +} + +impl RandomDistribution for UniformHemisphere { + fn value(&self) -> Vec3 { + let mut rng = thread_rng(); + let mut result = Vec3::new( + 2.0 * rng.sample::(Open01) - 1.0, + 2.0 * rng.sample::(Open01) - 1.0, + rng.sample::(OpenClosed01), + ); + while result.norm_squared() > 1.0 { + result = Vec3::new( + 2.0 * rng.sample::(Open01) - 1.0, + 2.0 * rng.sample::(Open01) - 1.0, + rng.sample::(OpenClosed01), + ); + } + result.normalize() + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + #[ignore] + fn print_values() { + let target = UniformHemisphere::new(); + for _ in 0..1000 { + let value = target.value(); + println!("{}, {}, {}", value.x(), value.y(), value.z()); + } + } +}