use crate::objects::hit::Hit; use crate::objects::sphere::Sphere; use crate::objects::traits::Hittable; use crate::objects::triangle::Triangle; use crate::ray::Ray; use crate::{objects::materials::traits::Material, vec3::Vec3}; use log::{info, warn}; use std::fmt::Debug; use std::sync::Arc; pub struct Quad { p1: Vec3, p2: Vec3, p3: Vec3, p4: Vec3, material: Arc, normal: Vec3, } impl Quad { pub fn new(p1: Vec3, p2: Vec3, p3: Vec3, p4: Vec3, material: Arc) -> Self { warn!("quad normal {}", (p2 - p1).cross(&(p4 - p1)).get_unit()); Self { p1, p2, p3, p4, material, normal: (p2 - p1).cross(&(p4 - p1)).get_unit(), } } pub fn corner_spheres(&self) -> Vec { let mut out: Vec = vec![]; out.push(Sphere::new(self.p1, 1., self.material.clone())); out.push(Sphere::new(self.p2, 1., self.material.clone())); out.push(Sphere::new(self.p3, 1., self.material.clone())); out.push(Sphere::new(self.p4, 1., self.material.clone())); return out; } pub fn hit( p1: Vec3, p2: Vec3, p3: Vec3, p4: Vec3, material: Arc, normal: Vec3, r: &Ray, ) -> Option { let isct1 = Triangle::hit(p1, p2, p4, material.clone(), normal, r); let isct2 = Triangle::hit(p2, p3, p4, material.clone(), normal, r); if isct1.is_some() { return isct1; } return isct2; } } impl Debug for Quad { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.debug_struct("Triangle") .field("p1", &self.p1) .field("p2", &self.p2) .field("p3", &self.p3) .field("p4", &self.p4) .field("material", &self.material) .finish() } } impl Hittable for Quad { fn hit(&self, r: &Ray) -> Option { Quad::hit( self.p1, self.p2, self.p3, self.p4, self.material.clone(), self.normal, r, ) } fn normal_at(&self, _p: &Vec3) -> Vec3 { // FIXME: might cause ownership issues return self.normal; } }