diff options
Diffstat (limited to 'src/core')
-rw-r--r-- | src/core/bound.rs | 114 | ||||
-rw-r--r-- | src/core/mod.rs | 11 | ||||
-rw-r--r-- | src/core/ray.rs | 6 | ||||
-rw-r--r-- | src/core/spectrum.rs | 35 | ||||
-rw-r--r-- | src/core/vector2.rs | 110 | ||||
-rw-r--r-- | src/core/vector3.rs | 47 |
6 files changed, 323 insertions, 0 deletions
diff --git a/src/core/bound.rs b/src/core/bound.rs new file mode 100644 index 0000000..ea9d990 --- /dev/null +++ b/src/core/bound.rs @@ -0,0 +1,114 @@ +use crate::{Number, Float}; +use super::vector2::Vector2; +use crate::core; + +#[derive(Clone)] +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> { + pub fn new(p0: &Vector2<T>, p1: &Vector2<T>) -> Self { + let min = Vector2::new_xy(min(p0.x, p1.x), min(p0.y, p1.y)); + let max = Vector2::new_xy(max(p0.x, p1.x), max(p0.y, p1.y)); + + Self { min, max } + } + + pub fn new_xyxy(x1: T, y1: T, x2: T, y2: T) -> Self { + Self::new( + &Vector2::new_xy(x1, y1), + &Vector2::new_xy(x2, y2), + ) + } + + pub fn diagonal(&self) -> Vector2<T> { + self.max - self.min + } + + pub fn area(&self) -> T { + let diag = self.diagonal(); + return diag.x * diag.y; + } + + pub fn width(&self) -> T { + self.diagonal().x + } +} + +impl From<&Bound2i> for Bound2f { + fn from(b: &Bound2i) -> Self { + Self { + min: core::Vector2f::from(b.min), + max: core::Vector2f::from(b.max), + } + } +} + +impl From<&Bound2f> for Bound2i { + fn from(b: &Bound2f) -> Self { + Self { + min: core::Vector2i::from(b.min), + max: core::Vector2i::from(b.max), + } + } +} + +pub fn intersect<T: Number>(a: &Bound2<T>, b: &Bound2<T>) -> Bound2<T> { + Bound2::new( + &Vector2::new_xy(max(a.min.x, b.min.x), max(a.min.y, b.min.y)), + &Vector2::new_xy(min(a.max.x, b.max.x), min(a.max.y, b.max.y)), + ) +} + +#[cfg(test)] +mod tests { + use super::*; + + fn create_test() -> Bound2<i32> { + Bound2::new( + &Vector2::new_xy(1, 2), + &Vector2::new_xy(10, 3) + ) + } + + #[test] + fn area() { + let b = create_test(); + + assert!(b.area() == 9); + } + + #[test] + fn intersect_test() { + let b1 = Bound2i::new_xyxy(10, 10, 20, 20); + let b2 = Bound2i::new_xyxy(2, 11, 22, 17); + + let b = intersect(&b1, &b2); + + assert!( + b.min.x == 10 && + b.min.y == 11 && + b.max.x == 20 && + b.max.y == 17 + ) + } +} diff --git a/src/core/mod.rs b/src/core/mod.rs new file mode 100644 index 0000000..938a16e --- /dev/null +++ b/src/core/mod.rs @@ -0,0 +1,11 @@ +pub mod vector2; +pub mod vector3; +pub mod bound; +pub mod spectrum; +mod ray; + +pub use vector2::{Vector2i, Vector2f}; +pub use vector3::Vector3f; +pub use bound::{Bound2i, Bound2f}; +pub use spectrum::Spectrum; +pub use ray::Ray; diff --git a/src/core/ray.rs b/src/core/ray.rs new file mode 100644 index 0000000..7d73b93 --- /dev/null +++ b/src/core/ray.rs @@ -0,0 +1,6 @@ +use crate::core::Vector3f; + +pub struct Ray { + origin: Vector3f, + direction: Vector3f, +} diff --git a/src/core/spectrum.rs b/src/core/spectrum.rs new file mode 100644 index 0000000..604c8c0 --- /dev/null +++ b/src/core/spectrum.rs @@ -0,0 +1,35 @@ +use crate::Float; +use std::ops; + +// TODO implement SampledSpectrum instead for nicer images + +#[derive(Clone, Default)] +pub struct Spectrum { + c: [Float; 3], +} + +impl Spectrum { + fn new_rgb(r: Float, g: Float, b: Float) -> Spectrum { + Spectrum { c: [r, g, b] } + } +} + +impl std::ops::Mul<Float> for &Spectrum { + type Output = Spectrum; + + fn mul(self, op: Float) -> Self::Output { + Self::Output::new_rgb( + self.c[0] * op, + self.c[1] * op, + self.c[2] * op, + ) + } +} + +impl std::ops::AddAssign<&Self> for Spectrum { + fn add_assign(&mut self, op: &Self) { + self.c[0] += op.c[0]; + self.c[1] += op.c[1]; + self.c[2] += op.c[2]; + } +} diff --git a/src/core/vector2.rs b/src/core/vector2.rs new file mode 100644 index 0000000..ac70947 --- /dev/null +++ b/src/core/vector2.rs @@ -0,0 +1,110 @@ +use crate::{Float, Number}; +use std::ops::{Sub, Add}; + +#[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 new_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 { + Self::new_xy( + self.x - op.x, + self.y - op.y, + ) + } +} + +impl<T: Number> Add for Vector2<T> { + type Output = Self; + fn add(self, op: Self) -> Self::Output { + Self::new_xy( + self.x + op.x, + self.y + op.y, + ) + } +} + +impl Vector2f { + pub fn ceil(&self) -> Self { + Self::new_xy( + self.x.ceil(), + self.y.ceil() + ) + } + + pub fn floor(&self) -> Self { + Self::new_xy( + self.x.ceil(), + self.y.ceil() + ) + } +} + +impl From<Vector2i> for Vector2f { + fn from(v: Vector2i) -> Self { + Self { + x: v.x as Float, + y: v.y as Float, + } + } +} + +impl From<Vector2f> for Vector2i { + fn from(v: Vector2f) -> Self { + Self { + x: v.x as i32, + y: v.y as i32, + } + } +} + + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn new_vec2() { + let v = Vector2::new_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::new_xy(10, 11); + let v2 = Vector2::new_xy(2, 3); + + let v3 = v1-v2; + assert!(v3.x == 8 && v3.y == 8); + } + + #[test] + fn add_vec2() { + let v1 = Vector2::new_xy(10, 11); + let v2 = Vector2::new_xy(2, 3); + + let v3 = v1+v2; + assert!(v3.x == 12 && v3.y == 14); + } +} diff --git a/src/core/vector3.rs b/src/core/vector3.rs new file mode 100644 index 0000000..da09ceb --- /dev/null +++ b/src/core/vector3.rs @@ -0,0 +1,47 @@ +use crate::{Float, Number}; +use std::ops::{Sub, Add}; + +#[derive(Clone, Copy)] +pub struct Vector3<T: Number> { + pub x: T, + pub y: T, + pub z: T, +} + +pub type Vector3f = Vector3<Float>; + +impl<T: Number> Vector3<T> { + pub fn new(initial: T) -> Vector3<T> { + Vector3 { + x: initial, + y: initial, + z: initial, + } + } + + pub fn new_xy(x: T, y: T, z: T) -> Vector3<T> { + Vector3 { x, y, z} + } +} + +impl<T: Number> Sub for Vector3<T> { + type Output = Self; + fn sub(self, op: Self) -> Self::Output { + Self::new_xy( + self.x - op.x, + self.y - op.y, + self.z - op.z, + ) + } +} + +impl<T: Number> Add for Vector3<T> { + type Output = Self; + fn add(self, op: Self) -> Self::Output { + Self::new_xy( + self.x + op.x, + self.y + op.y, + self.z + op.z, + ) + } +} |