smallpt 1.0.1

A small ray/pathtracer in Rust, inspired by Kevin Beason's educational 99-lines ray/pathtracer (http://www.kevinbeason.com/smallpt/)
Documentation
use crate::hit::Hit;
use crate::material::Material;
use crate::ray::Ray;
use crate::{PrimitiveType, Traceable, Vec3};
use bvh::aabb::{Aabb, Bounded};
use bvh::bounding_hierarchy::BHShape;
use nalgebra::Point3;

#[derive(Copy, Clone)]
pub struct Triangle {
	pub p0: Vec3,
	pub p1: Vec3,
	pub p2: Vec3,
	pub normal: Vec3,
	pub n0: Vec3,
	pub n1: Vec3,
	pub n2: Vec3,
	pub material: Material,
	node_index: usize,
}

impl Triangle {
	pub fn new(p0: Vec3, p1: Vec3, p2: Vec3, material: Material) -> Triangle {
		let normal = (p2 - p0).normalize().cross(&(p1 - p0).normalize());
		Triangle {
			p0,
			p1,
			p2,
			normal,
			n0: normal,
			n1: normal,
			n2: normal,
			material,
			node_index: 0,
		}
	}

	pub fn new_ext(
		p0: Vec3,
		p1: Vec3,
		p2: Vec3,
		n0: Vec3,
		n1: Vec3,
		n2: Vec3,
		material: Material,
	) -> Triangle {
		Triangle {
			p0,
			p1,
			p2,
			n0,
			n1,
			n2,
			normal: (p2 - p0).normalize().cross(&(p1 - p0).normalize()),
			material,
			node_index: 0,
		}
	}
}

impl Traceable for Triangle {
	fn intersect(&self, r: &Ray, result: &mut Hit) -> bool {
		let p0p1 = self.p1 - self.p0;
		let p0p2 = self.p2 - self.p0;
		let pvec = r.direction.cross(&p0p2);

		let det = p0p1.dot(&pvec).abs();

		let tvec = r.origin - self.p0;
		let u = tvec.dot(&pvec) / det;
		if !(0.0..=1.0).contains(&u) {
			return false;
		}

		let qvec = tvec.cross(&p0p1);
		let v = r.direction.dot(&qvec) / det;
		if v < 0.0 || u + v > 1.0 {
			return false;
		}

		result.t = p0p2.dot(&qvec) / det;
		result.p = r.origin + r.direction * result.t;
		result.material = self.material;
		result.b = Vec3::new(1.0 - u - v, u, v);

		result.n = result.b.x * self.n0 + result.b.y * self.n1 + result.b.z * self.n2;

		true
	}

	fn get_primitive_type(&self) -> PrimitiveType {
		PrimitiveType::Triangle
	}
}

impl Bounded<f32, 3> for Triangle {
	fn aabb(&self) -> Aabb<f32, 3> {
		let min_x = self.p0.x.min(self.p1.x).min(self.p2.x);
		let min_y = self.p0.y.min(self.p1.y).min(self.p2.y);
		let min_z = self.p0.z.min(self.p1.z).min(self.p2.z);
		let max_x = self.p0.x.max(self.p1.x).max(self.p2.x);
		let max_y = self.p0.y.max(self.p1.y).max(self.p2.y);
		let max_z = self.p0.z.max(self.p1.z).max(self.p2.z);
		Aabb::with_bounds(
			Point3::new(min_x, min_y, min_z),
			Point3::new(max_x, max_y, max_z),
		)
	}
}

impl BHShape<f32, 3> for Triangle {
	fn set_bh_node_index(&mut self, index: usize) {
		self.node_index = index;
	}

	fn bh_node_index(&self) -> usize {
		self.node_index
	}
}