ft: tri support
This commit is contained in:
79
src/objects/triangle.rs
Normal file
79
src/objects/triangle.rs
Normal 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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user