Add BVH bounding boxes

This commit is contained in:
2022-07-05 11:21:37 +02:00
parent 3de572d4a9
commit dbb0ab2b91
6 changed files with 90 additions and 323 deletions

View File

@ -1,5 +1,8 @@
use crate::{Point3, Ray, Vec3};
use crate::material::{Material};
use crate::aabb::Aabb;
pub type HittableList = Vec<Box<dyn Hittable + Sync>>;
#[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<HitRecord>;
fn bounding_box(&self, time0: f64, time1: f64) -> Option<Aabb>;
}
#[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<HitRecord> {
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<Aabb> {
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
})
}
}
fn bounding_box(&self, time0: f64, time1: f64) -> Option<Aabb> {
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
}))
}
}

View File

@ -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<Box<dyn Hittable + Sync>> {
let mut world:Vec<Box<dyn Hittable + Sync>> = 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<Box<dyn Hittable + Sync>> {
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<Aabb> {
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)
}

View File

@ -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<Box<dyn Hittable + Sync>>, 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<Box<dyn Hittable + Sync>>,
world: &'material HittableList,
t_min: f64,
t_max: f64,
) -> Option<HitRecord<'material>> {

View File

@ -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<i32> 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<usize> 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")
}
}
}