Fixed bug in kdtree that this uncovered. Marked Hit and it's dependencies as needing to implement the Debug trait.
85 lines
2.2 KiB
Rust
85 lines
2.2 KiB
Rust
use std;
|
|
|
|
use rand::{self, Rng};
|
|
|
|
use crate::{
|
|
aabb::AABB,
|
|
hitable::{Hit, HitRecord},
|
|
material::Isotropic,
|
|
ray::Ray,
|
|
texture::Texture,
|
|
vec3::Vec3,
|
|
};
|
|
|
|
#[derive(Debug)]
|
|
pub struct ConstantMedium<H, T>
|
|
where
|
|
H: Hit,
|
|
T: Texture,
|
|
{
|
|
density: f32,
|
|
material: Isotropic<T>,
|
|
hitable: H,
|
|
}
|
|
|
|
impl<H, T> ConstantMedium<H, T>
|
|
where
|
|
H: Hit,
|
|
T: Texture,
|
|
{
|
|
pub fn new(hitable: H, density: f32, texture: T) -> ConstantMedium<H, T>
|
|
where
|
|
T: Texture,
|
|
{
|
|
ConstantMedium {
|
|
density,
|
|
material: Isotropic::new(texture),
|
|
hitable,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl<H, T> Hit for ConstantMedium<H, T>
|
|
where
|
|
H: Hit,
|
|
T: Texture,
|
|
{
|
|
fn hit(&self, r: Ray, t_min: f32, t_max: f32) -> Option<HitRecord> {
|
|
let mut rng = rand::thread_rng();
|
|
if let Some(mut rec1) = self.hitable.hit(r, std::f32::MIN, std::f32::MAX) {
|
|
if let Some(mut rec2) = self.hitable.hit(r, rec1.t + 0.001, std::f32::MAX) {
|
|
if rec1.t < t_min {
|
|
rec1.t = t_min;
|
|
}
|
|
if rec2.t > t_max {
|
|
rec2.t = t_max;
|
|
}
|
|
if rec1.t >= rec2.t {
|
|
return None;
|
|
}
|
|
if rec1.t < 0. {
|
|
rec1.t = 0.;
|
|
}
|
|
let distance_inside_boundary = (rec2.t - rec1.t) * r.direction.length();
|
|
let hit_distance: f32 = -(1. / self.density) * rng.gen::<f32>().ln();
|
|
if hit_distance < distance_inside_boundary {
|
|
let t = rec1.t + hit_distance / r.direction.length();
|
|
let normal = Vec3::new(rng.gen(), rng.gen(), rng.gen()).unit_vector();
|
|
return Some(HitRecord {
|
|
t,
|
|
p: r.point_at_parameter(t),
|
|
normal,
|
|
material: &self.material,
|
|
uv: (0., 0.),
|
|
});
|
|
}
|
|
}
|
|
}
|
|
None
|
|
}
|
|
|
|
fn bounding_box(&self, t_min: f32, t_max: f32) -> Option<AABB> {
|
|
self.hitable.bounding_box(t_min, t_max)
|
|
}
|
|
}
|