aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJulian T <julian@jtle.dk>2021-01-25 14:43:46 +0100
committerJulian T <julian@jtle.dk>2021-01-25 14:43:46 +0100
commit33a35c50c20e863123642c8c9ea31dfc006945f6 (patch)
tree6bbdd9f0f5d4deddec50fca1c3dbff3f2878ffac /src
parent41ea2d8f94043d49fc26aaaa8030a73dcfdc2da9 (diff)
Started work on implementing vectors bounding and film
Diffstat (limited to 'src')
-rw-r--r--src/bounding.rs62
-rw-r--r--src/camera/film.rs51
-rw-r--r--src/camera/filter/mod.rs22
-rw-r--r--src/camera/mod.rs2
-rw-r--r--src/lib.rs21
-rw-r--r--src/spectrum.rs13
-rw-r--r--src/vector.rs56
7 files changed, 227 insertions, 0 deletions
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<T: Number> {
+ pub min: Vector2<T>,
+ pub max: Vector2<T>
+}
+
+pub type Bound2i = Bound2<i32>;
+pub type Bound2f = Bound2<Float>;
+
+fn min<T: Number> (a: T, b: T) -> T {
+ if b < a {
+ return b;
+ }
+ a
+}
+
+fn max<T: Number> (a: T, b: T) -> T {
+ if b > a {
+ return b;
+ }
+ a
+}
+
+impl<T: Number> Bound2<T> {
+ fn new(p0: &Vector2<T>, p1: &Vector2<T>) -> Bound2<T> {
+ 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<T> {
+ 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<i32> {
+ 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<usize>,
+
+ pixels: Vec<Pixel>,
+ 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<usize>, 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<usize>, 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<Output = Self> +
+ Mul<Output = Self>
+{}
+
+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<T: Number> {
+ pub x: T,
+ pub y: T,
+}
+
+pub type Vector2f = Vector2<Float>;
+pub type Vector2i = Vector2<i32>;
+
+impl<T: Number> Vector2<T> {
+ pub fn new(initial: T) -> Vector2<T> {
+ Vector2 { x: initial, y: initial }
+ }
+
+ pub fn from_xy(x: T, y: T) -> Vector2<T> {
+ Vector2 { x, y }
+ }
+}
+
+impl<T: Number> Sub for Vector2<T> {
+ 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);
+ }
+}