ft: tri support

This commit is contained in:
2026-04-30 16:28:16 +02:00
parent 388fbcbb8a
commit 27bdce5882
7 changed files with 204 additions and 12 deletions

79
src/objects/triangle.rs Normal file
View File

@@ -0,0 +1,79 @@
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;
pub struct Triangle {
p1: Vec3,
p2: Vec3,
p3: Vec3,
material: Arc<dyn Material>,
normal: Vec3,
}
impl Triangle {
pub fn new(p1: Vec3, p2: Vec3, p3: Vec3, material: Arc<dyn Material>) -> Self {
Self {
p1,
p2,
p3,
material,
normal: (p2 - p1).cross(&(p3 - p1)),
}
}
}
impl Debug for Triangle {
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("material", &self.material)
.finish()
}
}
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 normal_at(&self, _p: &Vec3) -> Vec3 {
// FIXME: might cause ownership issues
return self.normal;
}
}