192 lines
4.3 KiB
Rust
192 lines
4.3 KiB
Rust
// There are many math functions in this file, so we allow single letter variable names.
|
|
#![allow(clippy::many_single_char_names)]
|
|
use crate::aabb::AABB;
|
|
use crate::hitable::Hit;
|
|
use crate::hitable::HitRecord;
|
|
use crate::material::Material;
|
|
use crate::ray::Ray;
|
|
use crate::vec3::Vec3;
|
|
|
|
pub struct XYRect<M>
|
|
where
|
|
M: Material,
|
|
{
|
|
x0: f32,
|
|
x1: f32,
|
|
y0: f32,
|
|
y1: f32,
|
|
k: f32,
|
|
material: M,
|
|
}
|
|
|
|
impl<M> XYRect<M>
|
|
where
|
|
M: Material,
|
|
{
|
|
pub fn new(x0: f32, x1: f32, y0: f32, y1: f32, k: f32, material: M) -> XYRect<M> {
|
|
XYRect {
|
|
x0,
|
|
x1,
|
|
y0,
|
|
y1,
|
|
k,
|
|
material,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl<M> Hit for XYRect<M>
|
|
where
|
|
M: Material,
|
|
{
|
|
fn hit(&self, r: Ray, t_min: f32, t_max: f32) -> Option<HitRecord> {
|
|
let t = (self.k - r.origin.z) / r.direction.z;
|
|
if t < t_min || t > t_max {
|
|
return None;
|
|
}
|
|
let x = r.origin.x + t * r.direction.x;
|
|
let y = r.origin.y + t * r.direction.y;
|
|
if x < self.x0 || x > self.x1 || y < self.y0 || y > self.y1 {
|
|
return None;
|
|
}
|
|
let u = (x - self.x0) / (self.x1 - self.x0);
|
|
let v = (y - self.y0) / (self.y1 - self.y0);
|
|
Some(HitRecord {
|
|
t,
|
|
uv: (u, v),
|
|
p: r.point_at_parameter(t),
|
|
normal: Vec3::new(0., 0., 1.),
|
|
material: &self.material,
|
|
})
|
|
}
|
|
|
|
fn bounding_box(&self, _t_min: f32, _t_max: f32) -> Option<AABB> {
|
|
Some(AABB::new(
|
|
Vec3::new(self.x0, self.y0, self.k - 0.0001),
|
|
Vec3::new(self.x1, self.y1, self.k + 0.0001),
|
|
))
|
|
}
|
|
}
|
|
|
|
pub struct XZRect<M>
|
|
where
|
|
M: Material,
|
|
{
|
|
x0: f32,
|
|
x1: f32,
|
|
z0: f32,
|
|
z1: f32,
|
|
k: f32,
|
|
material: M,
|
|
}
|
|
|
|
impl<M> XZRect<M>
|
|
where
|
|
M: Material,
|
|
{
|
|
pub fn new(x0: f32, x1: f32, z0: f32, z1: f32, k: f32, material: M) -> XZRect<M> {
|
|
XZRect {
|
|
x0,
|
|
x1,
|
|
z0,
|
|
z1,
|
|
k,
|
|
material,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl<M> Hit for XZRect<M>
|
|
where
|
|
M: Material,
|
|
{
|
|
fn hit(&self, r: Ray, t_min: f32, t_max: f32) -> Option<HitRecord> {
|
|
let t = (self.k - r.origin.y) / r.direction.y;
|
|
if t < t_min || t > t_max {
|
|
return None;
|
|
}
|
|
let x = r.origin.x + t * r.direction.x;
|
|
let z = r.origin.z + t * r.direction.z;
|
|
if x < self.x0 || x > self.x1 || z < self.z0 || z > self.z1 {
|
|
return None;
|
|
}
|
|
let u = (x - self.x0) / (self.x1 - self.x0);
|
|
let v = (z - self.z0) / (self.z1 - self.z0);
|
|
Some(HitRecord {
|
|
t,
|
|
uv: (u, v),
|
|
p: r.point_at_parameter(t),
|
|
normal: Vec3::new(0., 1., 0.),
|
|
material: &self.material,
|
|
})
|
|
}
|
|
|
|
fn bounding_box(&self, _t_min: f32, _t_max: f32) -> Option<AABB> {
|
|
Some(AABB::new(
|
|
Vec3::new(self.x0, self.k - 0.0001, self.z0),
|
|
Vec3::new(self.x1, self.k + 0.0001, self.z1),
|
|
))
|
|
}
|
|
}
|
|
|
|
pub struct YZRect<M>
|
|
where
|
|
M: Material,
|
|
{
|
|
y0: f32,
|
|
y1: f32,
|
|
k: f32,
|
|
z0: f32,
|
|
z1: f32,
|
|
material: M,
|
|
}
|
|
|
|
impl<M> YZRect<M>
|
|
where
|
|
M: Material,
|
|
{
|
|
pub fn new(y0: f32, y1: f32, z0: f32, z1: f32, k: f32, material: M) -> YZRect<M> {
|
|
YZRect {
|
|
y0,
|
|
y1,
|
|
z0,
|
|
z1,
|
|
k,
|
|
material,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl<M> Hit for YZRect<M>
|
|
where
|
|
M: Material,
|
|
{
|
|
fn hit(&self, r: Ray, t_min: f32, t_max: f32) -> Option<HitRecord> {
|
|
let t = (self.k - r.origin.x) / r.direction.x;
|
|
if t < t_min || t > t_max {
|
|
return None;
|
|
}
|
|
let y = r.origin.y + t * r.direction.y;
|
|
let z = r.origin.z + t * r.direction.z;
|
|
if y < self.y0 || y > self.y1 || z < self.z0 || z > self.z1 {
|
|
return None;
|
|
}
|
|
let u = (y - self.y0) / (self.y1 - self.y0);
|
|
let v = (z - self.z0) / (self.z1 - self.z0);
|
|
Some(HitRecord {
|
|
t,
|
|
uv: (u, v),
|
|
p: r.point_at_parameter(t),
|
|
normal: Vec3::new(1., 0., 0.),
|
|
material: &self.material,
|
|
})
|
|
}
|
|
|
|
fn bounding_box(&self, _t_min: f32, _t_max: f32) -> Option<AABB> {
|
|
Some(AABB::new(
|
|
Vec3::new(self.k - 0.0001, self.y0, self.z0),
|
|
Vec3::new(self.k + 0.0001, self.y1, self.z1),
|
|
))
|
|
}
|
|
}
|