79 lines
2.4 KiB
Rust
79 lines
2.4 KiB
Rust
use std::sync::Arc;
|
|
use crate::hittable::{HitRecord, Hittable};
|
|
use crate::{Aabb, Material, Point3, Ray, Vec3};
|
|
//https://github.com/perliedman/raytracing-in-one-weekend/blob/master/src/geometry/triangle.rs
|
|
|
|
pub struct Triangle {
|
|
a: Point3,
|
|
b: Point3,
|
|
c: Point3,
|
|
normal: Vec3,
|
|
material: Arc<Material>,
|
|
}
|
|
|
|
impl Triangle {
|
|
pub fn new(a: Point3, b: Point3, c: Point3, normal: Vec3, material: Arc<Material>, ) -> Self {
|
|
Self { a, b, c, normal, material }
|
|
}
|
|
pub fn without_normal(a: Point3, b: Point3, c: Point3, material: Arc<Material>, ) -> Self {
|
|
let normal = (b - a).cross(&(c - a));
|
|
Self { a, b, c, normal, material }
|
|
}
|
|
}
|
|
|
|
impl Hittable for Triangle {
|
|
fn hit(&self, ray: &Ray, t_min: f64, t_max: f64) -> Option<HitRecord> {
|
|
let ab = self.b - self.a;
|
|
let ac = self.c - self.a;
|
|
let pvec = ray.direction().cross(&ac);
|
|
let det = ab.dot(&pvec);
|
|
if det.abs() < 1e-4 {
|
|
return None;
|
|
}
|
|
let inv_det = 1.0 / det;
|
|
let tvec = ray.origin() - self.a;
|
|
let u = tvec.dot(&pvec) * inv_det;
|
|
if u < 0.0 || u > 1.0 {
|
|
return None;
|
|
}
|
|
|
|
let qvec = tvec.cross(&ab);
|
|
let v = ray.direction().dot(&qvec) * inv_det;
|
|
if v < 0.0 || u + v > 1.0 {
|
|
return None;
|
|
}
|
|
|
|
match ac.dot(&qvec) * inv_det {
|
|
t if t < t_min || t > t_max => None,
|
|
t => {
|
|
let mut rec = HitRecord {
|
|
point: ray.at(t),
|
|
normal: self.normal,
|
|
t,
|
|
u,
|
|
v,
|
|
front_face: true,
|
|
material: &self.material
|
|
};
|
|
rec.normalized(ray);
|
|
Some(rec)
|
|
}
|
|
}
|
|
}
|
|
|
|
fn bounding_box(&self, _time0: f64, _time1: f64) -> Option<Aabb> {
|
|
Some(Aabb {
|
|
minimum: Point3::new(
|
|
self.a.x().min(self.b.x()).min(self.c.x()),
|
|
self.a.y().min(self.b.y()).min(self.c.y()),
|
|
self.a.z().min(self.b.z()).min(self.c.z()),
|
|
),
|
|
maximum: Point3::new(
|
|
self.a.x().max(self.b.x()).max(self.c.x()),
|
|
self.a.y().max(self.b.y()).max(self.c.y()),
|
|
self.a.z().max(self.b.z()).max(self.c.z()),
|
|
),
|
|
})
|
|
}
|
|
}
|