diff --git a/profile.sh b/profile.sh new file mode 100755 index 0000000..f471e19 --- /dev/null +++ b/profile.sh @@ -0,0 +1,25 @@ +#!/bin/bash +RELEASE_FLAG=$1 + +if [ "$RELEASE_FLAG" == "--release" ]; +then + echo "Profiling in release mode" + IS_RELEASE=1 +else + echo "Profiling in debug mode" + IS_RELEASE=0 +fi + +PROFILE_OUT=profiling/callgrind.$(date +"%m-%d-%Y-%I:%M:%S").out + +if [ RELEASE_FLAG == 1 ]; +then + BIN=target/release/ray_tracer +else + BIN=target/debug/ray_tracer +fi + +mkdir -p profiling + +((IS_RELEASE)) && cargo build --release || cargo build +valgrind --tool=callgrind --dump-instr=yes --collect-jumps=yes --simulate-cache=yes --callgrind-out-file=$PROFILE_OUT $BIN diff --git a/src/hittable.rs b/src/hittable.rs index e573f62..4b0440a 100644 --- a/src/hittable.rs +++ b/src/hittable.rs @@ -7,6 +7,7 @@ use crate::{ vec3::Vec3, }; use std::fmt::Debug; +use std::marker::PhantomData; pub trait Hittable<'a, T: Rng>: Sync { fn hit(&self, ray: &Ray, t_min: f64, t_max: f64) -> Option>; @@ -560,36 +561,112 @@ impl Center for Moving { } } +#[derive(Debug)] +pub struct Translate<'a, T: Rng, H: Hittable<'a, T> + Debug> { + object: H, + offset: Vec3, + _dummy: PhantomData<&'a T>, +} + +impl<'a, T: Rng, H: Hittable<'a, T> + Debug> Translate<'a, T, H> { + fn new(object: H, offset: Vec3) -> Self { + Self { + object, + offset, + _dummy: PhantomData, + } + } +} + +unsafe impl<'a, T: Rng, H: Hittable<'a, T> + Debug> Sync for Translate<'a, T, H> {} + +impl<'a, T: Rng, H: Hittable<'a, T> + Debug> Hittable<'a, T> for Translate<'a, T, H> { + fn hit(&self, ray: &Ray, t_min: f64, t_max: f64) -> Option> { + let offset_ray = Ray::new( + ray.origin() - &self.offset, + ray.direction().clone(), + ray.time(), + ); + + self.object.hit(&offset_ray, t_min, t_max).map(|mut hit| { + hit.p = hit.p + &self.offset; + hit + }) + } + + fn bounding_box(&self, time_start: f64, time_end: f64) -> Option { + self.object + .bounding_box(time_start, time_end) + .map(|mut aabb| { + let min = aabb.min() + &self.offset; + let max = aabb.max() + &self.offset; + AABB::new(min, max) + }) + } +} + +impl<'a, T: Rng, H: Hittable<'a, T> + Center + Debug> Center for Translate<'a, T, H> { + fn center(&self, time: f64) -> Vec3 { + &self.offset + self.object.center(time) + } +} + #[derive(Debug)] pub enum Shape { Sphere(Sphere), - XyRect(XyRect), - XzRect(XzRect), - YzRect(YzRect), + Rect(Rect), Cube(Cube), MovingSphere(Moving), -} - -impl Shape { + MovingRect(Moving), + MovingCube(Moving), + TranslateSphere(Translate<'_, T, Sphere>), + TranslateRect(Translate<'_, T, Sphere>), + TranslateCube(Translate<'_, T, Sphere>), + RotateSphere(), + RotateRect(), + RotateCube(), + MovingTranslateSphere(), + MovingTranslateRect(), + MovingTranslateCube(), + MovingRotateSphere(), + MovingRotateRect(), + MovingRotateCube(), + TranslateRotateSphere(), + TranslateRotateRect(), + TranslateRotateCube(), + MovingTranslateRotateSphere(), + MovingTranslateRotateRect(), + MovingTranslateRotateCube(), +} + +pub struct ShapeBuilder { + shape: Shape, +} + +impl ShapeBuilder { pub fn sphere(x: f64, y: f64, z: f64, radius: f64, material: Material) -> Self { let center = Vec3::new(x, y, z); let sphere: Sphere = Sphere::new(center, radius, material); - Self::Sphere(sphere) + let shape = Shape::Sphere(sphere); + Self { shape } } pub fn xy_rect(x0: f64, x1: f64, y0: f64, y1: f64, k: f64, material: Material) -> Self { let rect = XyRect::new(x0, x1, y0, y1, k, material); - Self::XyRect(rect) + let shape = Shape::Rect(Rect::Xy(rect)); + Self { shape } } pub fn xz_rect(x0: f64, x1: f64, z0: f64, z1: f64, k: f64, material: Material) -> Self { let rect = XzRect::new(x0, x1, z0, z1, k, material); - Self::XzRect(rect) + let shape = Shape::Rect(Rect::Xz(rect)); + Self { shape } } pub fn yz_rect(y0: f64, y1: f64, z0: f64, z1: f64, k: f64, material: Material) -> Self { let rect = YzRect::new(y0, y1, z0, z1, k, material); - Self::YzRect(rect) + let shape = Shape::Rect(Rect::Yz(rect)); + Self { shape } } pub fn cube(x0: f64, y0: f64, z0: f64, x1: f64, y1: f64, z1: f64, material: Material) -> Self { @@ -597,28 +674,36 @@ impl Shape { let p1 = Vec3::new(x1, y1, z1); let cube = Cube::new(p0, p1, material); - Self::Cube(cube) - } - - pub fn moving_sphere( - x0: f64, - y0: f64, - z0: f64, - x1: f64, - y1: f64, - z1: f64, - radius: f64, - material: Material, - time_start: f64, - time_end: f64, - ) -> Self { - let center_initial = Vec3::new(x0, y0, z0); - let center_final = Vec3::new(x1, y1, z1); - let sphere: Sphere = Sphere::new(center_initial, radius, material); - - let sphere = Moving::new(sphere, center_final, time_start, time_end); - - Self::MovingSphere(sphere) + let shape = Shape::Cube(cube); + Self { shape } + } + + pub fn moving(self, x: f64, y: f64, z: f64, time_start: f64, time_end: f64) -> Self { + let center_final = Vec3::new(x, y, z); + let shape = match self.shape { + Shape::Sphere(sphere) => { + Shape::MovingSphere(Moving::new(sphere, center_final, time_start, time_end)) + } + Shape::XyRect(rect) => {} + Shape::XzRect(rect) => {} + Shape::YzRect(rect) => {} + Shape::Cube(cube) => {} + Shape::MovingSphere(Moving { object, .. }) => { + Shape::MovingSphere(Moving::new(object, center_final, time_start, time_end)) + } + }; + + Moving::new(sphere, center_final, time_start, time_end); + + Self { shape } + } + + pub fn translate(self) -> Self { + Self { shape } + } + + pub fn build(self) -> Shape { + self.shape } } diff --git a/src/main.rs b/src/main.rs index 6390875..8a30990 100644 --- a/src/main.rs +++ b/src/main.rs @@ -43,7 +43,7 @@ fn main() { let v_up = Vec3::new(0.0, 1.0, 0.0); - let focus_distance = 10.0; //(&look_from - &look_at).length(); + let focus_distance = (&look_from - &look_at).length(); Camera::new( look_from,