Implement AABB and BVH.
This commit is contained in:
parent
a4556212ed
commit
11a7cc6f08
45
rtiow/src/aabb.rs
Normal file
45
rtiow/src/aabb.rs
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
use ray::Ray;
|
||||||
|
use vec3::Vec3;
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct AABB {
|
||||||
|
pub min: Vec3,
|
||||||
|
pub max: Vec3,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AABB {
|
||||||
|
pub fn new(min: Vec3, max: Vec3) -> AABB {
|
||||||
|
AABB { min, max }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn hit(&self, r: Ray, t_min: f32, t_max: f32) -> bool {
|
||||||
|
let mut t_min = t_min;
|
||||||
|
let mut t_max = t_max;
|
||||||
|
for axis in 0..3 {
|
||||||
|
let t0 = ((self.min[axis] - r.origin[axis]) / r.direction[axis])
|
||||||
|
.min((self.max[axis] - r.origin[axis]) / r.direction[axis]);
|
||||||
|
let t1 = ((self.min[axis] - r.origin[axis]) / r.direction[axis])
|
||||||
|
.max((self.max[axis] - r.origin[axis]) / r.direction[axis]);
|
||||||
|
t_min = t0.max(t_min);
|
||||||
|
t_max = t1.min(t_max);
|
||||||
|
if t_max <= t_min {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn surrounding_box(box0: &AABB, box1: &AABB) -> AABB {
|
||||||
|
let min = Vec3::new(
|
||||||
|
box0.min.x.min(box1.min.x),
|
||||||
|
box0.min.y.min(box1.min.y),
|
||||||
|
box0.min.z.min(box1.min.z),
|
||||||
|
);
|
||||||
|
let max = Vec3::new(
|
||||||
|
box0.max.x.max(box1.max.x),
|
||||||
|
box0.max.y.max(box1.max.y),
|
||||||
|
box0.max.z.max(box1.max.z),
|
||||||
|
);
|
||||||
|
AABB::new(min, max)
|
||||||
|
}
|
||||||
@ -11,6 +11,7 @@ use std::time::Instant;
|
|||||||
use rand::Rng;
|
use rand::Rng;
|
||||||
use structopt::StructOpt;
|
use structopt::StructOpt;
|
||||||
|
|
||||||
|
use rtiow::bvh::BVH;
|
||||||
use rtiow::camera::Camera;
|
use rtiow::camera::Camera;
|
||||||
use rtiow::cube::Cube;
|
use rtiow::cube::Cube;
|
||||||
use rtiow::hitable::Hit;
|
use rtiow::hitable::Hit;
|
||||||
@ -111,7 +112,63 @@ fn build_scene_book(opt: &Opt) -> Scene {
|
|||||||
time_min,
|
time_min,
|
||||||
time_max,
|
time_max,
|
||||||
);
|
);
|
||||||
let world = HitableList::new(random_scene());
|
let world: Box<Hit> = Box::new(HitableList::new(random_scene()));
|
||||||
|
Scene {
|
||||||
|
camera,
|
||||||
|
world,
|
||||||
|
subsamples: opt.subsamples,
|
||||||
|
width: opt.width,
|
||||||
|
height: opt.height,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn build_scene_bvh(opt: &Opt) -> Scene {
|
||||||
|
let lookfrom = Vec3::new(3., 3., 2.);
|
||||||
|
let lookat = Vec3::new(0., 0., -1.);
|
||||||
|
let dist_to_focus = (lookfrom - lookat).length();
|
||||||
|
let aperture = 0.1;
|
||||||
|
let time_min = 0.;
|
||||||
|
let time_max = 1.;
|
||||||
|
let camera = Camera::new(
|
||||||
|
lookfrom,
|
||||||
|
lookat,
|
||||||
|
Vec3::new(0., 1., 0.),
|
||||||
|
45.,
|
||||||
|
opt.width as f32 / opt.height as f32,
|
||||||
|
aperture,
|
||||||
|
dist_to_focus,
|
||||||
|
time_min,
|
||||||
|
time_max,
|
||||||
|
);
|
||||||
|
let world: Box<Hit> = Box::new(BVH::new(
|
||||||
|
vec![
|
||||||
|
Box::new(Sphere::new(
|
||||||
|
Vec3::new(0., 0., -1.),
|
||||||
|
0.5,
|
||||||
|
Box::new(Lambertian::new(Vec3::new(0.1, 0.2, 0.5))),
|
||||||
|
)),
|
||||||
|
Box::new(Sphere::new(
|
||||||
|
Vec3::new(0., -100.5, -1.),
|
||||||
|
100.,
|
||||||
|
Box::new(Lambertian::new(Vec3::new(0.8, 0.8, 0.8))),
|
||||||
|
)),
|
||||||
|
Box::new(Sphere::new(
|
||||||
|
Vec3::new(1., 0., -1.),
|
||||||
|
0.5,
|
||||||
|
Box::new(Metal::new(Vec3::new(0.6, 0.6, 0.6), 0.2)),
|
||||||
|
)),
|
||||||
|
Box::new(MovingSphere::new(
|
||||||
|
Vec3::new(-1., 0., -1.25),
|
||||||
|
Vec3::new(-1., 0., -0.75),
|
||||||
|
0.5,
|
||||||
|
time_min,
|
||||||
|
time_max,
|
||||||
|
Box::new(Lambertian::new(Vec3::new(0.2, 0.8, 0.2))),
|
||||||
|
)),
|
||||||
|
],
|
||||||
|
time_min,
|
||||||
|
time_max,
|
||||||
|
));
|
||||||
Scene {
|
Scene {
|
||||||
camera,
|
camera,
|
||||||
world,
|
world,
|
||||||
@ -139,7 +196,7 @@ fn build_scene_tutorial(opt: &Opt) -> Scene {
|
|||||||
time_min,
|
time_min,
|
||||||
time_max,
|
time_max,
|
||||||
);
|
);
|
||||||
let world = HitableList::new(vec![
|
let world: Box<Hit> = Box::new(HitableList::new(vec![
|
||||||
Box::new(Sphere::new(
|
Box::new(Sphere::new(
|
||||||
Vec3::new(0., 0., -1.),
|
Vec3::new(0., 0., -1.),
|
||||||
0.5,
|
0.5,
|
||||||
@ -163,7 +220,7 @@ fn build_scene_tutorial(opt: &Opt) -> Scene {
|
|||||||
1.,
|
1.,
|
||||||
Box::new(Lambertian::new(Vec3::new(0.2, 0.8, 0.2))),
|
Box::new(Lambertian::new(Vec3::new(0.2, 0.8, 0.2))),
|
||||||
)),
|
)),
|
||||||
]);
|
]));
|
||||||
Scene {
|
Scene {
|
||||||
camera,
|
camera,
|
||||||
world,
|
world,
|
||||||
@ -191,7 +248,7 @@ fn build_scene_cube(opt: &Opt) -> Scene {
|
|||||||
time_min,
|
time_min,
|
||||||
time_max,
|
time_max,
|
||||||
);
|
);
|
||||||
let world = HitableList::new(vec![
|
let world: Box<Hit> = Box::new(HitableList::new(vec![
|
||||||
Box::new(Sphere::new(
|
Box::new(Sphere::new(
|
||||||
Vec3::new(0., 0., -1.),
|
Vec3::new(0., 0., -1.),
|
||||||
0.5,
|
0.5,
|
||||||
@ -207,7 +264,7 @@ fn build_scene_cube(opt: &Opt) -> Scene {
|
|||||||
100.,
|
100.,
|
||||||
Box::new(Lambertian::new(Vec3::new(0.8, 0.8, 0.8))),
|
Box::new(Lambertian::new(Vec3::new(0.8, 0.8, 0.8))),
|
||||||
)),
|
)),
|
||||||
]);
|
]));
|
||||||
Scene {
|
Scene {
|
||||||
camera,
|
camera,
|
||||||
world,
|
world,
|
||||||
@ -222,6 +279,7 @@ pub enum Model {
|
|||||||
Book,
|
Book,
|
||||||
Tutorial,
|
Tutorial,
|
||||||
Cube,
|
Cube,
|
||||||
|
BVH,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@ -240,6 +298,7 @@ impl str::FromStr for Model {
|
|||||||
"book" => Ok(Model::Book),
|
"book" => Ok(Model::Book),
|
||||||
"tutorial" => Ok(Model::Tutorial),
|
"tutorial" => Ok(Model::Tutorial),
|
||||||
"cube" => Ok(Model::Cube),
|
"cube" => Ok(Model::Cube),
|
||||||
|
"bvh" => Ok(Model::BVH),
|
||||||
_ => Err(ModelParseError(s.to_owned())),
|
_ => Err(ModelParseError(s.to_owned())),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -272,6 +331,7 @@ fn main() -> Result<(), std::io::Error> {
|
|||||||
Model::Book => build_scene_book(&opt),
|
Model::Book => build_scene_book(&opt),
|
||||||
Model::Cube => build_scene_cube(&opt),
|
Model::Cube => build_scene_cube(&opt),
|
||||||
Model::Tutorial => build_scene_tutorial(&opt),
|
Model::Tutorial => build_scene_tutorial(&opt),
|
||||||
|
Model::BVH => build_scene_bvh(&opt),
|
||||||
};
|
};
|
||||||
let res = render(scene, &opt.output);
|
let res = render(scene, &opt.output);
|
||||||
let runtime = start.elapsed();
|
let runtime = start.elapsed();
|
||||||
|
|||||||
149
rtiow/src/bvh.rs
Normal file
149
rtiow/src/bvh.rs
Normal file
@ -0,0 +1,149 @@
|
|||||||
|
use std;
|
||||||
|
|
||||||
|
use rand;
|
||||||
|
use rand::Rng;
|
||||||
|
|
||||||
|
use aabb::surrounding_box;
|
||||||
|
use aabb::AABB;
|
||||||
|
use hitable::Hit;
|
||||||
|
use hitable::HitRecord;
|
||||||
|
use ray::Ray;
|
||||||
|
|
||||||
|
enum BVHNode {
|
||||||
|
Leaf(Box<Hit>),
|
||||||
|
Branch {
|
||||||
|
left: Box<BVHNode>,
|
||||||
|
right: Box<BVHNode>,
|
||||||
|
bbox: Option<AABB>,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
fn box_x_compare(ah: &Box<Hit>, bh: &Box<Hit>) -> std::cmp::Ordering {
|
||||||
|
match (ah.bounding_box(0., 0.), bh.bounding_box(0., 0.)) {
|
||||||
|
(Some(box_left), Some(box_right)) => {
|
||||||
|
eprintln!("box_x_compare {} < {}", box_left.min, box_right.min);
|
||||||
|
return box_left.min.x.partial_cmp(&box_right.min.x).unwrap();
|
||||||
|
}
|
||||||
|
_ => panic!("hit missing bounding box"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn box_y_compare(ah: &Box<Hit>, bh: &Box<Hit>) -> std::cmp::Ordering {
|
||||||
|
match (ah.bounding_box(0., 0.), bh.bounding_box(0., 0.)) {
|
||||||
|
(Some(box_left), Some(box_right)) => {
|
||||||
|
eprintln!("box_y_compare {} < {}", box_left.min, box_right.min);
|
||||||
|
return box_left.min.y.partial_cmp(&box_right.min.y).unwrap();
|
||||||
|
}
|
||||||
|
_ => panic!("hit missing bounding box"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn box_z_compare(ah: &Box<Hit>, bh: &Box<Hit>) -> std::cmp::Ordering {
|
||||||
|
match (ah.bounding_box(0., 0.), bh.bounding_box(0., 0.)) {
|
||||||
|
(Some(box_left), Some(box_right)) => {
|
||||||
|
eprintln!("box_z_compare {} < {}", box_left.min, box_right.min);
|
||||||
|
return box_left.min.z.partial_cmp(&box_right.min.z).unwrap();
|
||||||
|
}
|
||||||
|
_ => panic!("hit missing bounding box"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BVHNode {
|
||||||
|
fn new(l: Vec<Box<Hit>>, t_min: f32, t_max: f32) -> BVHNode {
|
||||||
|
if l.len() == 1 {
|
||||||
|
// Return the first element from the vector, which should be the only element.
|
||||||
|
// TODO(wathiede): we really want a .first_into() (.first() doesn't work because it
|
||||||
|
// returns a reference.)
|
||||||
|
for h in l.into_iter() {
|
||||||
|
return BVHNode::Leaf(h);
|
||||||
|
}
|
||||||
|
panic!("Unreachable");
|
||||||
|
} else {
|
||||||
|
let mut l: Vec<Box<Hit>> = l.into_iter().collect();
|
||||||
|
let mut rng = rand::thread_rng();
|
||||||
|
match rng.gen_range::<u16>(0, 3) {
|
||||||
|
0 => l.sort_by(box_x_compare),
|
||||||
|
1 => l.sort_by(box_y_compare),
|
||||||
|
2 => l.sort_by(box_z_compare),
|
||||||
|
val @ _ => panic!("unknown axis {}", val),
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut left_half = Vec::new();
|
||||||
|
let mut right_half = Vec::new();
|
||||||
|
let half_idx = l.len() / 2;
|
||||||
|
l.into_iter().enumerate().for_each(|(i, h)| {
|
||||||
|
if i < half_idx {
|
||||||
|
left_half.push(h);
|
||||||
|
} else {
|
||||||
|
right_half.push(h);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
let left = Box::new(BVHNode::new(left_half, t_min, t_max));
|
||||||
|
let right = Box::new(BVHNode::new(right_half, t_min, t_max));
|
||||||
|
let bbox = BVHNode::surrounding_box(left.as_ref(), right.as_ref(), t_min, t_max);
|
||||||
|
return BVHNode::Branch { left, right, bbox };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn surrounding_box(left: &Hit, right: &Hit, t_min: f32, t_max: f32) -> Option<AABB> {
|
||||||
|
match (
|
||||||
|
left.bounding_box(t_min, t_max),
|
||||||
|
right.bounding_box(t_min, t_max),
|
||||||
|
) {
|
||||||
|
(Some(left_bbox), Some(right_bbox)) => Some(surrounding_box(&left_bbox, &right_bbox)),
|
||||||
|
(None, Some(right_bbox)) => Some(right_bbox),
|
||||||
|
(Some(left_bbox), None) => Some(left_bbox),
|
||||||
|
(None, None) => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Hit for BVHNode {
|
||||||
|
fn hit(&self, r: Ray, t_min: f32, t_max: f32) -> Option<HitRecord> {
|
||||||
|
match self {
|
||||||
|
BVHNode::Leaf(ref hit) => hit.hit(r, t_min, t_max),
|
||||||
|
BVHNode::Branch {
|
||||||
|
ref left,
|
||||||
|
ref right,
|
||||||
|
..
|
||||||
|
} => match (left.hit(r, t_min, t_max), right.hit(r, t_min, t_max)) {
|
||||||
|
(Some(hit_left), Some(hit_right)) => if hit_left.t < hit_right.t {
|
||||||
|
return Some(hit_left);
|
||||||
|
} else {
|
||||||
|
return Some(hit_right);
|
||||||
|
},
|
||||||
|
(Some(hit_left), None) => Some(hit_left),
|
||||||
|
(None, Some(hit_right)) => Some(hit_right),
|
||||||
|
(None, None) => None,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn bounding_box(&self, t_min: f32, t_max: f32) -> Option<AABB> {
|
||||||
|
match self {
|
||||||
|
BVHNode::Leaf(ref hit) => hit.bounding_box(t_min, t_max),
|
||||||
|
BVHNode::Branch { ref bbox, .. } => bbox.clone(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct BVH {
|
||||||
|
root: BVHNode,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BVH {
|
||||||
|
pub fn new(l: Vec<Box<Hit>>, t_min: f32, t_max: f32) -> BVH {
|
||||||
|
BVH {
|
||||||
|
root: BVHNode::new(l, t_min, t_max),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Hit for BVH {
|
||||||
|
fn hit(&self, r: Ray, t_min: f32, t_max: f32) -> Option<HitRecord> {
|
||||||
|
self.root.hit(r, t_min, t_max)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn bounding_box(&self, t_min: f32, t_max: f32) -> Option<AABB> {
|
||||||
|
self.root.bounding_box(t_min, t_max)
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,3 +1,4 @@
|
|||||||
|
use aabb::AABB;
|
||||||
use hitable::Hit;
|
use hitable::Hit;
|
||||||
use hitable::HitRecord;
|
use hitable::HitRecord;
|
||||||
use material::Material;
|
use material::Material;
|
||||||
@ -5,6 +6,7 @@ use ray::Ray;
|
|||||||
use vec3::dot;
|
use vec3::dot;
|
||||||
use vec3::Vec3;
|
use vec3::Vec3;
|
||||||
|
|
||||||
|
// Cube is an axis-aligned cube with dimensions length x length x length with center in the middle.
|
||||||
pub struct Cube {
|
pub struct Cube {
|
||||||
center: Vec3,
|
center: Vec3,
|
||||||
length: f32,
|
length: f32,
|
||||||
@ -23,6 +25,7 @@ impl Cube {
|
|||||||
|
|
||||||
impl Hit for Cube {
|
impl Hit for Cube {
|
||||||
fn hit(&self, r: Ray, t_min: f32, t_max: f32) -> Option<HitRecord> {
|
fn hit(&self, r: Ray, t_min: f32, t_max: f32) -> Option<HitRecord> {
|
||||||
|
// See if it hit the positive X wall first.
|
||||||
let oc = r.origin - self.center;
|
let oc = r.origin - self.center;
|
||||||
let a = dot(r.direction, r.direction);
|
let a = dot(r.direction, r.direction);
|
||||||
let b = dot(oc, r.direction);
|
let b = dot(oc, r.direction);
|
||||||
@ -52,4 +55,11 @@ impl Hit for Cube {
|
|||||||
}
|
}
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn bounding_box(&self, _t_min: f32, _t_max: f32) -> Option<AABB> {
|
||||||
|
Some(AABB::new(
|
||||||
|
self.center - Vec3::new(self.length / 2., self.length / 2., self.length / 2.),
|
||||||
|
self.center + Vec3::new(self.length / 2., self.length / 2., self.length / 2.),
|
||||||
|
))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
use aabb::AABB;
|
||||||
use material::Material;
|
use material::Material;
|
||||||
use ray::Ray;
|
use ray::Ray;
|
||||||
use vec3::Vec3;
|
use vec3::Vec3;
|
||||||
@ -11,4 +12,5 @@ pub struct HitRecord<'m> {
|
|||||||
|
|
||||||
pub trait Hit: Send + Sync {
|
pub trait Hit: Send + Sync {
|
||||||
fn hit(&self, r: Ray, t_min: f32, t_max: f32) -> Option<HitRecord>;
|
fn hit(&self, r: Ray, t_min: f32, t_max: f32) -> Option<HitRecord>;
|
||||||
|
fn bounding_box(&self, t_min: f32, t_max: f32) -> Option<AABB>;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,11 @@
|
|||||||
|
use std;
|
||||||
|
|
||||||
|
use aabb::surrounding_box;
|
||||||
|
use aabb::AABB;
|
||||||
use hitable::Hit;
|
use hitable::Hit;
|
||||||
use hitable::HitRecord;
|
use hitable::HitRecord;
|
||||||
use ray::Ray;
|
use ray::Ray;
|
||||||
|
use vec3::Vec3;
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct HitableList {
|
pub struct HitableList {
|
||||||
@ -25,4 +30,19 @@ impl Hit for HitableList {
|
|||||||
}
|
}
|
||||||
min_hit
|
min_hit
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn bounding_box(&self, t_min: f32, t_max: f32) -> Option<AABB> {
|
||||||
|
// TODO(wathiede): I don't understand the version from the book, this implementation
|
||||||
|
// returns a superset of all bounding boxes.
|
||||||
|
let super_box = AABB::new(
|
||||||
|
Vec3::new(std::f32::MAX, std::f32::MAX, std::f32::MAX),
|
||||||
|
Vec3::new(std::f32::MIN, std::f32::MIN, std::f32::MIN),
|
||||||
|
);
|
||||||
|
Some(self.list.iter().fold(super_box, |acc, hitable| {
|
||||||
|
match hitable.bounding_box(t_min, t_max) {
|
||||||
|
Some(bbox) => surrounding_box(&acc, &bbox),
|
||||||
|
None => acc,
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,3 +1,5 @@
|
|||||||
|
pub mod aabb;
|
||||||
|
pub mod bvh;
|
||||||
pub mod camera;
|
pub mod camera;
|
||||||
pub mod cube;
|
pub mod cube;
|
||||||
pub mod hitable;
|
pub mod hitable;
|
||||||
|
|||||||
@ -1,3 +1,5 @@
|
|||||||
|
use aabb::surrounding_box;
|
||||||
|
use aabb::AABB;
|
||||||
use hitable::Hit;
|
use hitable::Hit;
|
||||||
use hitable::HitRecord;
|
use hitable::HitRecord;
|
||||||
use material::Material;
|
use material::Material;
|
||||||
@ -69,4 +71,17 @@ impl Hit for MovingSphere {
|
|||||||
}
|
}
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn bounding_box(&self, _t_min: f32, _t_max: f32) -> Option<AABB> {
|
||||||
|
let t_min_bb = AABB::new(
|
||||||
|
self.center0 - Vec3::new(self.radius, self.radius, self.radius),
|
||||||
|
self.center0 + Vec3::new(self.radius, self.radius, self.radius),
|
||||||
|
);
|
||||||
|
|
||||||
|
let t_max_bb = AABB::new(
|
||||||
|
self.center1 - Vec3::new(self.radius, self.radius, self.radius),
|
||||||
|
self.center1 + Vec3::new(self.radius, self.radius, self.radius),
|
||||||
|
);
|
||||||
|
Some(surrounding_box(&t_min_bb, &t_max_bb))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -12,12 +12,11 @@ use rand::Rng;
|
|||||||
|
|
||||||
use camera::Camera;
|
use camera::Camera;
|
||||||
use hitable::Hit;
|
use hitable::Hit;
|
||||||
use hitable_list::HitableList;
|
|
||||||
use ray::Ray;
|
use ray::Ray;
|
||||||
use vec3::Vec3;
|
use vec3::Vec3;
|
||||||
|
|
||||||
pub struct Scene {
|
pub struct Scene {
|
||||||
pub world: HitableList,
|
pub world: Box<Hit>,
|
||||||
pub camera: Camera,
|
pub camera: Camera,
|
||||||
pub subsamples: usize,
|
pub subsamples: usize,
|
||||||
pub width: usize,
|
pub width: usize,
|
||||||
@ -44,7 +43,7 @@ fn trace_pixel(x: usize, y: usize, scene: &Scene) -> Vec3 {
|
|||||||
let u = (rng.gen_range::<f32>(0., 1.) + x as f32) / scene.width as f32;
|
let u = (rng.gen_range::<f32>(0., 1.) + x as f32) / scene.width as f32;
|
||||||
let v = (rng.gen_range::<f32>(0., 1.) + y as f32) / scene.height as f32;
|
let v = (rng.gen_range::<f32>(0., 1.) + y as f32) / scene.height as f32;
|
||||||
let ray = scene.camera.get_ray(u, v);
|
let ray = scene.camera.get_ray(u, v);
|
||||||
color(ray, &scene.world, 0)
|
color(ray, scene.world.as_ref(), 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render_worker(
|
fn render_worker(
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
use aabb::AABB;
|
||||||
use hitable::Hit;
|
use hitable::Hit;
|
||||||
use hitable::HitRecord;
|
use hitable::HitRecord;
|
||||||
use material::Material;
|
use material::Material;
|
||||||
@ -52,4 +53,11 @@ impl Hit for Sphere {
|
|||||||
}
|
}
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn bounding_box(&self, _t_min: f32, _t_max: f32) -> Option<AABB> {
|
||||||
|
Some(AABB::new(
|
||||||
|
self.center - Vec3::new(self.radius, self.radius, self.radius),
|
||||||
|
self.center + Vec3::new(self.radius, self.radius, self.radius),
|
||||||
|
))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user