From c4369f86c920888bfaa00e46d74e3f5a1872a9ab Mon Sep 17 00:00:00 2001 From: Julian T Date: Sun, 31 Jan 2021 17:21:11 +0100 Subject: Add Scene type and Sphere intersect --- src/core/ray.rs | 5 +++-- src/core/vector3.rs | 45 +++++++++++++++++++++++++++++++++++++++++---- src/lib.rs | 6 ++++-- src/main.rs | 8 -------- src/scene/mod.rs | 5 +++-- src/scene/scene.rs | 38 ++++++++++++++++++++++++++++++++++++++ src/scene/shapes/mod.rs | 6 ++---- src/scene/shapes/sphere.rs | 37 +++++++++++++++++++++++++++++++++++++ 8 files changed, 128 insertions(+), 22 deletions(-) create mode 100644 src/scene/scene.rs diff --git a/src/core/ray.rs b/src/core/ray.rs index 7d73b93..54af639 100644 --- a/src/core/ray.rs +++ b/src/core/ray.rs @@ -1,6 +1,7 @@ use crate::core::Vector3f; pub struct Ray { - origin: Vector3f, - direction: Vector3f, + pub origin: Vector3f, + pub direction: Vector3f, } + diff --git a/src/core/vector3.rs b/src/core/vector3.rs index da09ceb..e3aa9a6 100644 --- a/src/core/vector3.rs +++ b/src/core/vector3.rs @@ -1,5 +1,5 @@ use crate::{Float, Number}; -use std::ops::{Sub, Add}; +use std::ops::{Sub, Add, DivAssign}; #[derive(Clone, Copy)] pub struct Vector3 { @@ -19,7 +19,7 @@ impl Vector3 { } } - pub fn new_xy(x: T, y: T, z: T) -> Vector3 { + pub fn new_xyz(x: T, y: T, z: T) -> Vector3 { Vector3 { x, y, z} } } @@ -27,7 +27,7 @@ impl Vector3 { impl Sub for Vector3 { type Output = Self; fn sub(self, op: Self) -> Self::Output { - Self::new_xy( + Self::new_xyz( self.x - op.x, self.y - op.y, self.z - op.z, @@ -38,10 +38,47 @@ impl Sub for Vector3 { impl Add for Vector3 { type Output = Self; fn add(self, op: Self) -> Self::Output { - Self::new_xy( + Self::new_xyz( self.x + op.x, self.y + op.y, self.z + op.z, ) } } + +impl DivAssign for Vector3 { + fn div_assign(&mut self, op: T) { + self.x /= op; + self.y /= op; + self.z /= op; + } +} + +impl Vector3f { + pub fn len_squared(&self) -> Float { + self.x * self.x + self.y * self.y + self.z * self.z + } + + pub fn len(&self) -> Float { + self.len_squared().sqrt() + } + + pub fn dot(&self, op: &Self) -> Float { + self.x * op.x + self.y * op.y + self.z * op.z + } + + pub fn norm_in(&mut self) { + let len = self.len(); + if len == 0.0 { + *self = Self::new(0.0); + } + + *self /= len; + } + + pub fn norm(&self) -> Self { + let mut new = self.clone(); + new.norm_in(); + new + } +} diff --git a/src/lib.rs b/src/lib.rs index c78c51e..a120f0d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,8 +1,9 @@ pub mod core; pub mod camera; mod scene; +mod render; -use std::ops::{Add, Sub, Mul}; +use std::ops::{Add, Sub, Mul, DivAssign}; use std::cmp; pub trait Number: @@ -10,7 +11,8 @@ pub trait Number: cmp::PartialOrd + Sub + Add + - Mul + Mul + + DivAssign {} impl Number for usize {} diff --git a/src/main.rs b/src/main.rs index c984176..524f613 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,12 +1,4 @@ -use pathtrace::camera::film::Film; -use pathtrace::vector::{Vector2i}; -use pathtrace::bound::Bound2i; fn main() { - - let film = Film::new(Vector2i::new(100)); - let tile = film.get_tile(&Bound2i::new_xyxy(10, 10, 100, 100)); - - //println!("Yo {}", tile.bounds.min.x); } diff --git a/src/scene/mod.rs b/src/scene/mod.rs index 3482bb6..13c5e23 100644 --- a/src/scene/mod.rs +++ b/src/scene/mod.rs @@ -1,3 +1,4 @@ -mod shapes; - +pub mod shapes; +mod scene; +pub use scene::*; diff --git a/src/scene/scene.rs b/src/scene/scene.rs new file mode 100644 index 0000000..a2f5b88 --- /dev/null +++ b/src/scene/scene.rs @@ -0,0 +1,38 @@ +use super::shapes::Shape; +use crate::Float; +use crate::core::Ray; + +pub struct Scene { + shps: Vec>, +} + +pub struct Intersection<'a> { + pub shp: &'a dyn Shape, + pub t: Float, +} + +impl Scene { + pub fn new() -> Self { + Self { + shps: Vec::new(), + } + } + + pub fn add_shape(&mut self, shp: Box) { + self.shps.push(shp); + } + + pub fn intersect(&self, ray: Ray) -> Option { + for shp in self.shps.iter() { + if let Some(t) = shp.intersect(&ray) { + return Some(Intersection { + shp: shp.as_ref(), + t, + }) + } + } + + None + } +} + diff --git a/src/scene/shapes/mod.rs b/src/scene/shapes/mod.rs index 76fb6f2..7fbb8db 100644 --- a/src/scene/shapes/mod.rs +++ b/src/scene/shapes/mod.rs @@ -5,8 +5,6 @@ pub use sphere::Sphere; use crate::core::Ray; use crate::Float; -trait Shape { - // - fn intersect(ray: Ray) -> Float; - fn intersect_ +pub trait Shape { + fn intersect(&self, ray: &Ray) -> Option; } diff --git a/src/scene/shapes/sphere.rs b/src/scene/shapes/sphere.rs index 9598422..f8ae11e 100644 --- a/src/scene/shapes/sphere.rs +++ b/src/scene/shapes/sphere.rs @@ -1,5 +1,6 @@ use crate::Float; use crate::core::{Ray, Vector3f}; +use super::Shape; pub struct Sphere { radius: Float, @@ -14,3 +15,39 @@ impl Sphere { } } } + +impl Shape for Sphere { + // Implementation from ray tracing in a weekend + fn intersect(&self, ray: &Ray) -> Option { + let oc = ray.origin - self.center; + let a = ray.direction.len_squared(); + let half_b = oc.dot(&ray.direction); + let c = oc.len_squared() - self.radius * self.radius; + let disc = half_b*half_b - a*c; + + if disc < 0.0 { + None + } else { + Some( (-half_b - disc.sqrt()) / a) + } + + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn sphere_intersect() { + let sph = Sphere::new(2.0, Vector3f::new_xyz(2.0, 3.0, 4.0)); + + let ray = Ray { + origin: Vector3f::new_xyz(1.0, 0.0, 0.0), + direction: Vector3f::new_xyz(0.0, 1.0, 1.5).norm(), + }; + + let dist = sph.intersect(&ray); + assert!((dist.unwrap() - 3.28).abs() < 0.01); + } +} -- cgit v1.2.3