ft: quad support

This commit is contained in:
2026-05-02 04:46:15 +02:00
parent 27bdce5882
commit f1ac226dbb
7 changed files with 193 additions and 42 deletions

View File

@@ -1,8 +1,9 @@
use log::{info, warn};
use crate::objects::hit::Hit;
use crate::objects::traits::Hittable;
use crate::ray::Ray;
use crate::{objects::materials::traits::Material, vec3::Vec3};
use is_close::default;
use std::fmt::Debug;
use std::sync::Arc;
@@ -21,7 +22,43 @@ impl Triangle {
p2,
p3,
material,
normal: (p2 - p1).cross(&(p3 - p1)),
normal: (p2 - p1).cross(&(p3 - p1)).get_unit(),
}
}
pub fn hit(
p1: Vec3,
p2: Vec3,
p3: Vec3,
material: Arc<dyn Material>,
normal: Vec3,
r: &Ray,
) -> Option<Hit> {
// check if ray parallel to plane
let dot = normal.dot(r.dir());
if dot == 0.0 {
return None;
}
let d = (-normal).dot(&p1);
// hitpoint on plane
let t = -(normal.dot(&(r.origin() + d))) / dot;
// hits behind camera
if t < 0. {
return None;
};
let p = r.at(t);
let a4 = (p3 - p1).cross(&(p2 - p1)).length();
let a3 = (p3 - p).cross(&(p2 - p)).length();
let a2 = (p3 - p).cross(&(p1 - p)).length();
let a1 = (p2 - p).cross(&(p1 - p)).length();
let diff = (a4 - a1 - a2 - a3).abs();
if diff < 0.001 {
return Some(Hit::new(t, p, normal, material, normal.dot(&-r.dir()) < 0.));
} else {
return None;
}
}
}
@@ -38,38 +75,15 @@ impl Debug for Triangle {
}
impl Hittable for Triangle {
fn hit(&self, r: &Ray) -> Option<super::hit::Hit> {
// check if ray parallel to plane
let dot = self.normal.dot(r.dir());
if default().is_close(dot, 0.) {
return None;
}
let d = (-self.normal).dot(&self.p1);
// hitpoint on plane
let t = -(self.normal.dot(&(r.origin() + d))) / dot;
// hits behind camera
if t < 0. {
return None;
};
let p = *r.origin() + t * r.dir();
let a4 = (self.p3 - self.p1).cross(&(self.p2 - self.p1)).length();
let a3 = (self.p3 - p).cross(&(self.p2 - p)).length();
let a2 = (self.p3 - p).cross(&(self.p1 - p)).length();
let a1 = (self.p2 - p).cross(&(self.p1 - p)).length();
let mut normal_copy = self.normal.clone();
let diff = (a4 - a1 - a2 - a3).abs();
if diff < 0.01 {
if self.normal.dot(&-r.dir()) < 0. {
normal_copy *= -1.; // TODO: vec3 * integer function
}
return Some(Hit::new(t, p, self.normal, self.material.clone(), true)); // TODO:
// front_face calculation; have to change with if check up there iggg
} else {
return None;
}
fn hit(&self, r: &Ray) -> Option<Hit> {
Triangle::hit(
self.p1,
self.p2,
self.p3,
self.material.clone(),
self.normal,
r,
)
}
fn normal_at(&self, _p: &Vec3) -> Vec3 {