raytracers/rtiow/renderer/src/constant_medium.rs
Bill Thiede 4066bf4b85 rtiow: add blox with gloxy edges.
Fixed bug in kdtree that this uncovered.
Marked Hit and it's dependencies as needing to implement the Debug
trait.
2022-09-17 16:45:29 -07:00

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)
}
}