From 33a35c50c20e863123642c8c9ea31dfc006945f6 Mon Sep 17 00:00:00 2001 From: Julian T Date: Mon, 25 Jan 2021 14:43:46 +0100 Subject: Started work on implementing vectors bounding and film --- Cargo.lock | 5 ++++ src/bounding.rs | 62 ++++++++++++++++++++++++++++++++++++++++++++++++ src/camera/film.rs | 51 +++++++++++++++++++++++++++++++++++++++ src/camera/filter/mod.rs | 22 +++++++++++++++++ src/camera/mod.rs | 2 ++ src/lib.rs | 21 ++++++++++++++++ src/spectrum.rs | 13 ++++++++++ src/vector.rs | 56 +++++++++++++++++++++++++++++++++++++++++++ 8 files changed, 232 insertions(+) create mode 100644 Cargo.lock create mode 100644 src/bounding.rs create mode 100644 src/camera/film.rs create mode 100644 src/camera/filter/mod.rs create mode 100644 src/camera/mod.rs create mode 100644 src/lib.rs create mode 100644 src/spectrum.rs create mode 100644 src/vector.rs diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..169dc89 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,5 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +[[package]] +name = "pathtrace" +version = "0.1.0" diff --git a/src/bounding.rs b/src/bounding.rs new file mode 100644 index 0000000..d5a3ed0 --- /dev/null +++ b/src/bounding.rs @@ -0,0 +1,62 @@ +use crate::{Number, Float}; +use crate::vector::Vector2; +use std::cmp; + +pub struct Bound2 { + pub min: Vector2, + pub max: Vector2 +} + +pub type Bound2i = Bound2; +pub type Bound2f = Bound2; + +fn min (a: T, b: T) -> T { + if b < a { + return b; + } + a +} + +fn max (a: T, b: T) -> T { + if b > a { + return b; + } + a +} + +impl Bound2 { + fn new(p0: &Vector2, p1: &Vector2) -> Bound2 { + let min = Vector2::from_xy(min(p0.x, p1.x), min(p0.y, p1.y)); + let max = Vector2::from_xy(max(p0.x, p1.x), max(p0.y, p1.y)); + + Bound2 { min, max } + } + + fn diagonal(&self) -> Vector2 { + self.max - self.min + } + + fn area(&self) -> T { + let diag = self.diagonal(); + return diag.x * diag.y; + } +} + +#[cfg(test)] +mod tests { + use super::*; + + fn create_test() -> Bound2 { + Bound2::new( + &Vector2::from_xy(1, 2), + &Vector2::from_xy(10, 3) + ) + } + + #[test] + fn area() { + let b = create_test(); + + assert!(b.area() == 9); + } +} diff --git a/src/camera/film.rs b/src/camera/film.rs new file mode 100644 index 0000000..c4a65ce --- /dev/null +++ b/src/camera/film.rs @@ -0,0 +1,51 @@ +use crate::vector::{Vector2, Vector2f}; +use crate::Float; +use crate::bounding::Bound2i; +use super::filter::Filter; + +#[derive(Clone)] +pub struct Pixel { + pub rgb: [Float; 3], +} + +pub struct Film<'a> { + pub resolution: Vector2, + + pixels: Vec, + filter: &'a dyn Filter, + filter_radius: Vector2f, +} + +pub struct FilmTile { + +} + +impl Pixel { + fn new() -> Pixel { + Pixel { rgb: [0.0, 0.0, 0.0] } + } +} + +impl Film<'_> { + fn new(resolution: Vector2, filter: & dyn Filter) -> Film { + let area = resolution.x * resolution.y; + Film { + resolution, + pixels: vec![Pixel::new(); area], + filter, + filter_radius: filter.radius() + } + } + + fn get_tile(bound: &Bound2i) { + // Used to calculate descrete coordinates into continues + let halfpixel = Vector2f::from_xy(0.5, 0.5); + } + + fn splat(&mut self, point: &Vector2, pixel: &Pixel) { + let index = point.x + point.y * self.resolution.x; + + self.pixels[index] = pixel.clone(); + } +} + diff --git a/src/camera/filter/mod.rs b/src/camera/filter/mod.rs new file mode 100644 index 0000000..93c6fc5 --- /dev/null +++ b/src/camera/filter/mod.rs @@ -0,0 +1,22 @@ +use crate::vector::Vector2f; +use crate::Float; + +pub trait Filter { + fn eval(&self, point: &Vector2f) -> Float; + fn radius(&self) -> Vector2f; +} + +pub struct BoxFilter { + radius: Vector2f, +} + +// The same a no filter, and can give aliasing in final image +impl Filter for BoxFilter { + fn eval(&self, _: &Vector2f) -> Float { + 1.0 + } + + fn radius(&self) -> Vector2f { + self.radius + } +} diff --git a/src/camera/mod.rs b/src/camera/mod.rs new file mode 100644 index 0000000..bba95f7 --- /dev/null +++ b/src/camera/mod.rs @@ -0,0 +1,2 @@ +mod film; +mod filter; diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..1d43855 --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,21 @@ +mod vector; +mod bounding; +mod camera; +mod spectrum; + +use std::ops::{Sub, Mul}; +use std::cmp; + +pub trait Number: + Copy + + cmp::PartialOrd + + Sub + + Mul +{} + +impl Number for usize {} +impl Number for i32 {} +impl Number for f32 {} + +// Used throughout the program +type Float = f32; diff --git a/src/spectrum.rs b/src/spectrum.rs new file mode 100644 index 0000000..aa37056 --- /dev/null +++ b/src/spectrum.rs @@ -0,0 +1,13 @@ +use crate::Float; + +// TODO implement SampledSpectrum instead for nicer images + +pub struct Spectrum { + c: [Float; 3], +} + +impl Spectrum { + fn from_rgb(r: Float, g: Float, b: Float) -> Spectrum { + Spectrum { c: [r, g, b] } + } +} diff --git a/src/vector.rs b/src/vector.rs new file mode 100644 index 0000000..9b89168 --- /dev/null +++ b/src/vector.rs @@ -0,0 +1,56 @@ +use crate::{Float, Number}; +use std::ops::{Sub}; + +#[derive(Clone, Copy)] +pub struct Vector2 { + pub x: T, + pub y: T, +} + +pub type Vector2f = Vector2; +pub type Vector2i = Vector2; + +impl Vector2 { + pub fn new(initial: T) -> Vector2 { + Vector2 { x: initial, y: initial } + } + + pub fn from_xy(x: T, y: T) -> Vector2 { + Vector2 { x, y } + } +} + +impl Sub for Vector2 { + type Output = Self; + fn sub(self, op: Self) -> Self::Output { + Vector2 { + x: self.x - op.x, + y: self.y - op.y, + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn new_vec2() { + let v = Vector2::from_xy(2.0, 10.0); + + assert!(v.x == 2.0 && v.y == 10.0); + + let v = Vector2::new(3); + + assert!(v.x == 3 && v.y == 3); + } + + #[test] + fn sub_vec2() { + let v1 = Vector2::from_xy(10, 11); + let v2 = Vector2::from_xy(2, 3); + + let v3 = v1-v2; + assert!(v3.x == 8 && v3.y == 8); + } +} -- cgit v1.2.3