118 lines
2.1 KiB
Rust
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
|
|
}
|
|
}
|