Files
raytracing/src/objects/hit.rs

118 lines
2.1 KiB
Rust

use std::sync::Arc;
use crate::{
objects::{materials::traits::Material, traits::Hittable},
ray::Ray,
vec3::Vec3,
};
pub struct Hit {
t: f32,
p: Vec3,
n: Vec3,
mat: Arc<dyn Material>,
front_face: bool,
u: f32,
v: f32,
}
impl Hit {
pub fn new(
t: f32,
p: Vec3,
n: Vec3,
mat: Arc<dyn Material>,
front_face: bool,
u: f32,
v: f32,
) -> Self {
Self {
t,
p,
n: if front_face { n } else { -n },
mat,
front_face,
u,
v,
}
}
pub fn from_minimal(
mh: MinimalHit,
n: Vec3,
mat: Arc<dyn Material>,
front_face: bool,
u: f32,
v: f32,
) -> Self {
Self {
t: mh.t,
p: mh.p,
n,
mat,
front_face,
u,
v,
}
}
pub fn t(&self) -> &f32 {
&self.t
}
pub fn p(&self) -> &Vec3 {
&self.p
}
pub fn n(&self) -> &Vec3 {
&self.n
}
pub fn mat(&self) -> Arc<dyn Material> {
self.mat.clone()
}
pub fn front_face(&self) -> bool {
self.front_face
}
pub fn uv(&self) -> (f32, f32) {
(self.u, self.v)
}
// TODO: use front_face to discard back-hits for culling
pub fn hit_list(hittables: &Vec<Arc<dyn Hittable>>, r: &Ray) -> Option<Hit> {
let mut closest: Option<Hit> = None;
for hittable in hittables {
if let Some(hit) = hittable.hit(r) {
// hit happens in front of camera and is closer than closest
if *hit.t() > 0.001
&& (closest.is_none() || closest.as_ref().unwrap().t() > hit.t())
{
closest = Some(hit);
}
}
}
closest
}
}
pub struct MinimalHit {
t: f32,
p: Vec3,
}
impl MinimalHit {
pub fn new(t: f32, p: Vec3) -> Self {
Self { t, p }
}
pub fn t(&self) -> f32 {
self.t
}
pub fn p(&self) -> &Vec3 {
&self.p
}
}