From dbb0ab2b91f64774fd639d86b0ad00e066760145 Mon Sep 17 00:00:00 2001 From: "max.nuding" Date: Tue, 5 Jul 2022 11:21:37 +0200 Subject: [PATCH] Add BVH bounding boxes --- Cargo.lock | 309 ------------------------------------------------ Cargo.toml | 3 +- src/hittable.rs | 29 ++++- src/main.rs | 39 +++++- src/ray.rs | 8 +- src/vec3.rs | 25 +++- 6 files changed, 90 insertions(+), 323 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 826a40d..abd5c29 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -20,24 +20,12 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" -[[package]] -name = "bit_field" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcb6dd1c2376d2e096796e234a70e17e94cc2d5d54ff8ce42b28cef1d0d359a4" - [[package]] name = "bitflags" version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" -[[package]] -name = "bumpalo" -version = "3.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37ccbd214614c6783386c1af30caf03192f17891059cecc394b4fb119e363de3" - [[package]] name = "bytemuck" version = "1.10.0" @@ -131,57 +119,6 @@ version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f107b87b6afc2a64fd13cac55fe06d6c8859f12d4b14cbcdd2c67d0976781be" -[[package]] -name = "exr" -version = "1.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14cc0e06fb5f67e5d6beadf3a382fec9baca1aa751c6d5368fdeee7e5932c215" -dependencies = [ - "bit_field", - "deflate", - "flume", - "half", - "inflate", - "lebe", - "smallvec", - "threadpool", -] - -[[package]] -name = "flate2" -version = "1.0.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f82b0f4c27ad9f8bfd1f3208d882da2b09c301bc1c828fd3a00d0216d2fbbff6" -dependencies = [ - "crc32fast", - "miniz_oxide", -] - -[[package]] -name = "flume" -version = "0.10.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ceeb589a3157cac0ab8cc585feb749bd2cea5cb55a6ee802ad72d9fd38303da" -dependencies = [ - "futures-core", - "futures-sink", - "nanorand", - "pin-project", - "spin", -] - -[[package]] -name = "futures-core" -version = "0.3.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c09fd04b7e4073ac7156a9539b57a484a8ea920f79c7c675d05d289ab6110d3" - -[[package]] -name = "futures-sink" -version = "0.3.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21163e139fa306126e6eedaf49ecdb4588f939600f0b1e770f4205ee4b7fa868" - [[package]] name = "getrandom" version = "0.2.7" @@ -189,28 +126,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4eb1a864a501629691edf6c15a593b7a51eebaa1e8468e9ddc623de7c9b58ec6" dependencies = [ "cfg-if", - "js-sys", "libc", "wasi", - "wasm-bindgen", ] -[[package]] -name = "gif" -version = "0.11.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3edd93c6756b4dfaf2709eafcc345ba2636565295c198a9cfbf75fa5e3e00b06" -dependencies = [ - "color_quant", - "weezl", -] - -[[package]] -name = "half" -version = "1.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eabb4a44450da02c90444cf74558da904edde8fb4e9035a9a6a4e15445af0bd7" - [[package]] name = "hermit-abi" version = "0.1.19" @@ -229,81 +148,18 @@ dependencies = [ "bytemuck", "byteorder", "color_quant", - "exr", - "gif", - "jpeg-decoder", "num-iter", "num-rational", "num-traits", "png", - "scoped_threadpool", - "tiff", ] -[[package]] -name = "inflate" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cdb29978cc5797bd8dcc8e5bf7de604891df2a8dc576973d71a281e916db2ff" -dependencies = [ - "adler32", -] - -[[package]] -name = "jpeg-decoder" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9478aa10f73e7528198d75109c8be5cd7d15fb530238040148d5f9a22d4c5b3b" -dependencies = [ - "rayon", -] - -[[package]] -name = "js-sys" -version = "0.3.58" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3fac17f7123a73ca62df411b1bf727ccc805daa070338fda671c86dac1bdc27" -dependencies = [ - "wasm-bindgen", -] - -[[package]] -name = "lazy_static" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" - -[[package]] -name = "lebe" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7efd1d698db0759e6ef11a7cd44407407399a910c774dd804c64c032da7826ff" - [[package]] name = "libc" version = "0.2.126" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836" -[[package]] -name = "lock_api" -version = "0.4.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "327fa5b6a6940e4699ec49a9beae1ea4845c6bab9314e4f84ac68742139d8c53" -dependencies = [ - "autocfg", - "scopeguard", -] - -[[package]] -name = "log" -version = "0.4.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" -dependencies = [ - "cfg-if", -] - [[package]] name = "memoffset" version = "0.6.5" @@ -322,15 +178,6 @@ dependencies = [ "adler", ] -[[package]] -name = "nanorand" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a51313c5820b0b02bd422f4b44776fbf47961755c74ce64afc73bfad10226c3" -dependencies = [ - "getrandom", -] - [[package]] name = "num-integer" version = "0.1.45" @@ -388,26 +235,6 @@ version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7709cef83f0c1f58f666e746a08b21e0085f7440fa6a29cc194d68aac97a4225" -[[package]] -name = "pin-project" -version = "1.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78203e83c48cffbe01e4a2d35d566ca4de445d79a85372fc64e378bfc812a260" -dependencies = [ - "pin-project-internal", -] - -[[package]] -name = "pin-project-internal" -version = "1.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "710faf75e1b33345361201d36d04e98ac1ed8909151a017ed384700836104c74" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "png" version = "0.17.5" @@ -426,24 +253,6 @@ version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872" -[[package]] -name = "proc-macro2" -version = "1.0.40" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd96a1e8ed2596c337f8eae5f24924ec83f5ad5ab21ea8e455d3566c69fbcaf7" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "quote" -version = "1.0.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3bcdf212e9776fbcb2d23ab029360416bb1706b1aea2d1a5ba002727cbcab804" -dependencies = [ - "proc-macro2", -] - [[package]] name = "rand" version = "0.8.5" @@ -507,132 +316,14 @@ dependencies = [ "rayon", ] -[[package]] -name = "scoped_threadpool" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d51f5df5af43ab3f1360b429fa5e0152ac5ce8c0bd6485cae490332e96846a8" - [[package]] name = "scopeguard" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" -[[package]] -name = "smallvec" -version = "1.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fd0db749597d91ff862fd1d55ea87f7855a744a8425a64695b6fca237d1dad1" - -[[package]] -name = "spin" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c530c2b0d0bf8b69304b39fe2001993e267461948b890cd037d8ad4293fa1a0d" -dependencies = [ - "lock_api", -] - -[[package]] -name = "syn" -version = "1.0.98" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c50aef8a904de4c23c788f104b7dddc7d6f79c647c7c8ce4cc8f73eb0ca773dd" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "threadpool" -version = "1.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d050e60b33d41c19108b32cea32164033a9013fe3b46cbd4457559bfbf77afaa" -dependencies = [ - "num_cpus", -] - -[[package]] -name = "tiff" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cfada0986f446a770eca461e8c6566cb879682f7d687c8348aa0c857bd52286" -dependencies = [ - "flate2", - "jpeg-decoder", - "weezl", -] - -[[package]] -name = "unicode-ident" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bd2fe26506023ed7b5e1e315add59d6f584c621d037f9368fea9cfb988f368c" - [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" - -[[package]] -name = "wasm-bindgen" -version = "0.2.81" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c53b543413a17a202f4be280a7e5c62a1c69345f5de525ee64f8cfdbc954994" -dependencies = [ - "cfg-if", - "wasm-bindgen-macro", -] - -[[package]] -name = "wasm-bindgen-backend" -version = "0.2.81" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5491a68ab4500fa6b4d726bd67408630c3dbe9c4fe7bda16d5c82a1fd8c7340a" -dependencies = [ - "bumpalo", - "lazy_static", - "log", - "proc-macro2", - "quote", - "syn", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-macro" -version = "0.2.81" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c441e177922bc58f1e12c022624b6216378e5febc2f0533e41ba443d505b80aa" -dependencies = [ - "quote", - "wasm-bindgen-macro-support", -] - -[[package]] -name = "wasm-bindgen-macro-support" -version = "0.2.81" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d94ac45fcf608c1f45ef53e748d35660f168490c10b23704c7779ab8f5c3048" -dependencies = [ - "proc-macro2", - "quote", - "syn", - "wasm-bindgen-backend", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-shared" -version = "0.2.81" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a89911bd99e5f3659ec4acf9c4d93b0a90fe4a2a11f15328472058edc5261be" - -[[package]] -name = "weezl" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c97e489d8f836838d497091de568cf16b117486d529ec5579233521065bd5e4" diff --git a/Cargo.toml b/Cargo.toml index fde7592..6c46686 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,11 +2,12 @@ name = "rustracer" version = "0.1.0" edition = "2021" +include = ["/src"] # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -image = "0.24.2" +image = { version = "0.24.2", default-features = false, features=["png"] } rand = "0.8.5" rayon = "1.5.3" diff --git a/src/hittable.rs b/src/hittable.rs index 5ad460c..270c7f3 100644 --- a/src/hittable.rs +++ b/src/hittable.rs @@ -1,5 +1,8 @@ use crate::{Point3, Ray, Vec3}; use crate::material::{Material}; +use crate::aabb::Aabb; + +pub type HittableList = Vec>; #[derive(Debug, Clone, Copy)] pub struct HitRecord<'material> { @@ -12,7 +15,10 @@ pub struct HitRecord<'material> { pub trait Hittable { fn hit(&self, ray: &Ray, t_min: f64, t_max: f64) -> Option; + fn bounding_box(&self, time0: f64, time1: f64) -> Option; } + +#[derive(Clone)] pub struct Sphere { pub center: Point3, pub radius: f64, @@ -32,7 +38,6 @@ impl Default for Sphere { } } } - impl Hittable for Sphere { fn hit(&self, ray: &Ray, t_min: f64, t_max: f64) -> Option { let oc = &ray.origin() - &self.center; @@ -61,8 +66,16 @@ impl Hittable for Sphere { material: &self.material }) } + fn bounding_box(&self, _time0: f64, _time1: f64) -> Option { + let s = Vec3::new(self.radius, self.radius, self.radius); + Some(Aabb { + minimum: self.center - s, + maximum: self.center + s, + }) + } } +#[derive(Clone)] pub struct MovableSphere { pub center0: Point3, pub center1: Point3, @@ -126,4 +139,16 @@ impl Hittable for MovableSphere { material: &self.material }) } -} \ No newline at end of file + fn bounding_box(&self, time0: f64, time1: f64) -> Option { + let s = Vec3::new(self.radius, self.radius, self.radius); + let center0 = self.center(time0); + let center1 = self.center(time1); + Some(Aabb { + minimum: center0 - s, + maximum: center0 + s, + }.surrounding(&Aabb { + minimum: center1 - s, + maximum: center1 + s + })) + } +} diff --git a/src/main.rs b/src/main.rs index ff88a18..afd3b53 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,8 +2,8 @@ use std::sync::Mutex; use std::time::Instant; use crate::camera::Camera; -use crate::hittable::{Hittable, Sphere}; -use crate::output::{Output, P3, PNG}; +use crate::hittable::{Hittable, Sphere, HittableList}; +use crate::output::{Output, PNG}; use crate::ray::Ray; use crate::vec3::{Color, Point3, Vec3}; use hittable::MovableSphere; @@ -11,6 +11,8 @@ use rand::Rng; use rand::distributions::{Distribution, Uniform}; use rayon::iter::{IntoParallelIterator, ParallelIterator}; use crate::material::{Dielectric, Lambertian, Material, Metal}; +use crate::aabb::Aabb; +use crate::bvh::BVH; mod vec3; mod ray; @@ -18,9 +20,11 @@ mod hittable; mod material; mod camera; mod output; +mod aabb; +mod bvh; -fn random_scene() -> Vec> { - let mut world:Vec> = Vec::new(); +fn random_scene() -> HittableList { + let mut world:HittableList = Vec::new(); let material_ground = Material::Lambertian(Lambertian::new(Color::new(0.5, 0.5, 0.5))); let ground = Sphere { @@ -99,9 +103,9 @@ fn random_scene() -> Vec> { fn main() { // Image const ASPECT_RATIO: f64 = 3.0 / 2.0; - const IMAGE_WIDTH: usize = 1200; + const IMAGE_WIDTH: usize = 400; const IMAGE_HEIGHT: usize = (IMAGE_WIDTH as f64 / ASPECT_RATIO) as usize; - const SAMPLES_PER_PIXEL: i32 = 100; + const SAMPLES_PER_PIXEL: i32 = 50; const MAX_DEPTH: i32 = 50; let look_from = Point3::new(13.0, 2.0, 3.0); @@ -157,3 +161,26 @@ fn main() { PNG::write("imc.png", &pixels, IMAGE_WIDTH, IMAGE_HEIGHT).expect("Error writing image: {}"); eprintln!("\nDone. Time: {}ms", start.elapsed().as_millis()); } + +fn world_bounding_box(time0: f64, time1: f64, world: &HittableList) -> Option { + if world.is_empty() { + return None; + } + let mut is_first = true; + let mut output_box: Aabb = Aabb { + minimum: Point3::default(), + maximum: Point3::default() + }; + for object in world { + if let Some(bb) = object.bounding_box(time0, time1) { + output_box = match is_first { + true => bb, + false => output_box.surrounding(&bb) + }; + is_first = false; + } else { + return None; + } + } + Some(output_box) +} diff --git a/src/ray.rs b/src/ray.rs index 5a06a99..14ef7f0 100644 --- a/src/ray.rs +++ b/src/ray.rs @@ -1,5 +1,5 @@ -use crate::{Color, Hittable, Vec3}; -use crate::hittable::HitRecord; +use crate::{Color, Vec3}; +use crate::hittable::{HitRecord, HittableList}; use crate::material::Scatterable; use crate::vec3::Point3; @@ -25,7 +25,7 @@ impl Ray { pub fn direction(&self) -> Vec3 { self.direction } pub fn origin(&self) -> Point3 { self.origin } pub fn time(&self) -> f64 { self.time } - pub fn pixel_color(&self, world: &Vec>, depth: i32) -> Color { + pub fn pixel_color(&self, world: &HittableList, depth: i32) -> Color { if depth <= 0 { return Color::default(); } @@ -52,7 +52,7 @@ impl Ray { } fn hit_world<'material>( &self, - world: &'material Vec>, + world: &'material HittableList, t_min: f64, t_max: f64, ) -> Option> { diff --git a/src/vec3.rs b/src/vec3.rs index 9e1c96b..5861583 100644 --- a/src/vec3.rs +++ b/src/vec3.rs @@ -1,5 +1,5 @@ use std::fmt::{Display, Formatter}; -use std::ops::{Add, AddAssign, Div, Mul, Neg, Sub}; +use std::ops::{Add, AddAssign, Div, Mul, Neg, Sub, Index}; use rand::distributions::{Distribution, Uniform}; #[derive(Debug, Clone, Copy)] @@ -257,3 +257,26 @@ impl PartialEq for Vec3 { self.x == other.x() && self.y == other.y() && self.z == other.z() } } + +impl Index for Vec3 { + type Output = f64; + fn index(&self, index: i32) -> &Self::Output { + match index { + 0 => &self.x, + 1 => &self.y, + 2 => &self.z, + _ => panic!("Unknown index") + } + } +} +impl Index for Vec3 { + type Output = f64; + fn index(&self, index: usize) -> &Self::Output { + match index { + 0 => &self.x, + 1 => &self.y, + 2 => &self.z, + _ => panic!("Unknown index") + } + } +}