From f3f56ed5f183f8461cc91cb6430d97c725ba159c Mon Sep 17 00:00:00 2001 From: Julian T Date: Sun, 7 Feb 2021 00:37:58 +0100 Subject: Move to double to avoid rounding error This rounding errors seems to happen when adding floats very close to 1 to a relatively large number. 325.0 + 0.99999034 = 326.0 This is a problem as this sample should be counted at the 325 pixel. However this will be a lesser problem when filtering is implemented. --- src/camera/film.rs | 9 ++++++--- src/core/vector2.rs | 10 ++++++++++ src/lib.rs | 6 +++++- src/main.rs | 2 +- src/sample/mod.rs | 5 ++--- src/sample/uniform.rs | 5 +++-- 6 files changed, 27 insertions(+), 10 deletions(-) diff --git a/src/camera/film.rs b/src/camera/film.rs index 2ff7239..7a7f2dc 100644 --- a/src/camera/film.rs +++ b/src/camera/film.rs @@ -132,11 +132,14 @@ impl FilmTile { pub fn add_sample(&mut self, inp: &Vector2f, c: Spectrum) { let point = Vector2i::from(inp.floor()); // Subtract the offset - let point = point - self.bounds.min; + let point = (point - self.bounds.min).cap(self.size.x-1, self.size.y-1); let index = point.x + point.y * self.size.x; - let pixel = self.pixels.get_mut(index as usize).unwrap(); - pixel.add(&c, 1.0); + if let Some(pixel) = self.pixels.get_mut(index as usize) { + pixel.add(&c, 1.0); + } else { + println!("Could not get pixel {} inp: {}, index: {}", point, inp, index); + } } } diff --git a/src/core/vector2.rs b/src/core/vector2.rs index 858068e..b3fa443 100644 --- a/src/core/vector2.rs +++ b/src/core/vector2.rs @@ -4,6 +4,7 @@ use crate::{Float, Number}; use std::ops::{Sub, Add}; use std::fmt; +use std::cmp::min; #[derive(Clone, Copy)] pub struct Vector2 { @@ -84,6 +85,15 @@ impl From for Vector2i { } } +impl Vector2i { + pub fn cap(&self, x: i32, y: i32) -> Self { + Self::new_xy( + min(self.x, x), + min(self.y, y), + ) + } +} + #[cfg(test)] mod tests { diff --git a/src/lib.rs b/src/lib.rs index 0ec6700..7da6627 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -8,6 +8,7 @@ pub mod sample; use std::ops::{Add, Sub, Mul, DivAssign, Neg}; use std::cmp; use std::fmt; +use std::f64::consts::PI; /// Trait used to implement generics /// @@ -25,8 +26,11 @@ pub trait Number: impl Number for i32 {} impl Number for f32 {} +impl Number for f64 {} /// Used for representing floating point values throughout the program /// /// A higher precision type will require more ram -pub type Float = f32; +pub type Float = f64; + +pub const M_PI: Float = PI; diff --git a/src/main.rs b/src/main.rs index c6bc14e..1604ae3 100644 --- a/src/main.rs +++ b/src/main.rs @@ -32,7 +32,7 @@ fn main() { let mut film = Film::new(res); let tile = film.get_tile(&film.frame); - let mut task = RenderTask::new(Box::new(tile), 10); + let mut task = RenderTask::new(Box::new(tile), 100); task.render(&ctx, &mut sampler); film.commit_tile(&task.tile); diff --git a/src/sample/mod.rs b/src/sample/mod.rs index 84ac755..5095501 100644 --- a/src/sample/mod.rs +++ b/src/sample/mod.rs @@ -1,6 +1,5 @@ -use crate::Float; +use crate::{M_PI, Float}; use crate::core::{Vector3f, Vector2f}; -use std::f32::consts::PI; mod uniform; @@ -20,7 +19,7 @@ pub trait Sampler { fn get_unit_vector(&mut self) -> Vector3f { let s2d = self.get_sample_2d(); - let lambda = distribute_between(s2d.x, -PI, PI); + let lambda = distribute_between(s2d.x, -M_PI, M_PI); let costheta = 2.0 * s2d.y - 1.0; let sintheta = costheta.acos().sin(); diff --git a/src/sample/uniform.rs b/src/sample/uniform.rs index cc6825a..e2f0b7c 100644 --- a/src/sample/uniform.rs +++ b/src/sample/uniform.rs @@ -15,13 +15,14 @@ impl UniformSampler { pub fn new() -> Self { Self { r: Pcg32::seed_from_u64(1), - d: Uniform::from(0.0..1.0), + d: Uniform::new(0.0, 1.0), } } } impl Sampler for UniformSampler { fn get_sample(&mut self) -> Float { - self.d.sample(&mut self.r) + let sample = self.d.sample(&mut self.r); + sample } } -- cgit v1.2.3