use std::ops::Range;
use std::rc::Rc;
use crate::utils::RangeExtensions;
use super::dot;
use super::HitRecord;
use super::Hittable;
use super::Material;
use super::Vec3;
#[derive(Clone, Debug)]
pub struct Plane {
pub origin: Vec3,
pub normal: Vec3,
pub mat: Rc<dyn Material>,
}
impl Plane {
pub fn new(origin: Vec3, normal: Vec3, mat: Rc<dyn Material>) -> Self {
Plane {
origin,
normal: normal.normalized(),
mat,
}
}
}
impl Hittable for Plane {
fn hit(&self, r: &crate::ray::Ray, ray_t: Range<f64>, rec: &mut HitRecord) -> bool {
let denom = dot(&self.normal, &r.direction);
if denom.abs() > 1e-4 {
let t = dot(&(self.origin - r.origin), &self.normal) / denom;
if ray_t.surrounds(t) {
rec.t = t;
rec.p = r.at(t);
rec.set_face_normal(r, &self.normal);
rec.set_material(Rc::clone(&self.mat));
return true;
}
}
false
}
fn as_string(&self) -> String {
format!(
"[ Plane ] Normal: ({}, {}, {}), Position: ({}x, {}z, {}z), material: {:?}",
self.normal.x,
self.normal.y,
self.normal.z,
self.origin.x,
self.origin.y,
self.origin.z,
self.mat
)
}
fn as_info_vec(&self) -> Vec<String> {
vec![
"Plane".to_string(),
"∞".to_string(),
self.origin.x.to_string(),
self.origin.y.to_string(),
self.origin.z.to_string(),
format!("{:?}", self.mat),
]
}
}