feat: triangle
This commit is contained in:
parent
ff7cde8758
commit
27905c888f
|
@ -0,0 +1,100 @@
|
|||
use crate::{hittable::Hittable, material::MaterialKind, math_utils::is_front_face, types_defined::{HitRecord, Point, Ray, Vec3}};
|
||||
|
||||
pub struct Triangle {
|
||||
pub points: Vec<Vec3>,
|
||||
pub material: Option<MaterialKind>,
|
||||
}
|
||||
|
||||
impl Triangle {
|
||||
pub fn new(p1: Point, p2: Point, p3: Point, material: Option<MaterialKind>,) -> Self {
|
||||
Triangle {
|
||||
points: vec![
|
||||
p1, p2, p3
|
||||
],
|
||||
material: material
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Hittable for Triangle {
|
||||
|
||||
fn hit(&self, r: &Ray, t_min: f32, t_max: f32, hit_record: &mut HitRecord) -> bool {
|
||||
let p0 = self.points[0];
|
||||
let p1 = self.points[1];
|
||||
let p2 = self.points[2];
|
||||
let u = Vec3 {
|
||||
x: p1.x - p0.x,
|
||||
y: p1.y - p0.y,
|
||||
z: p1.z - p0.z,
|
||||
};
|
||||
let v = Vec3 {
|
||||
x: p2.x - p0.x,
|
||||
y: p2.y - p0.y,
|
||||
z: p2.z - p0.z,
|
||||
};
|
||||
let normal = Vec3 {
|
||||
x: u.y * v.z - u.z * v.y,
|
||||
y: u.z * v.x - u.x * v.z,
|
||||
z: u.x * v.y - u.y * v.x,
|
||||
};
|
||||
let denominator = r.direction.x * normal.x + r.direction.y * normal.y + r.direction.z * normal.z;
|
||||
if denominator.abs() < std::f32::EPSILON {
|
||||
return false;
|
||||
}
|
||||
let w0 = Vec3 {
|
||||
x: r.point.x - p0.x,
|
||||
y: r.point.y - p0.y,
|
||||
z: r.point.z - p0.z,
|
||||
};
|
||||
let t = -(w0.x * normal.x + w0.y * normal.y + w0.z * normal.z) / denominator;
|
||||
if t < t_min || t > t_max {
|
||||
return false;
|
||||
}
|
||||
let P = Vec3 {
|
||||
x: r.point.x + t * r.direction.x,
|
||||
y: r.point.y + t * r.direction.y,
|
||||
z: r.point.z + t * r.direction.z,
|
||||
};
|
||||
let w = Vec3 {
|
||||
x: P.x - p0.x,
|
||||
y: P.y - p0.y,
|
||||
z: P.z - p0.z,
|
||||
};
|
||||
let uv_cross = Vec3 {
|
||||
x: u.y * v.z - u.z * v.y,
|
||||
y: u.z * v.x - u.x * v.z,
|
||||
z: u.x * v.y - u.y * v.x,
|
||||
};
|
||||
let wv_cross = Vec3 {
|
||||
x: w.y * v.z - w.z * v.y,
|
||||
y: w.z * v.x - w.x * v.z,
|
||||
z: w.x * v.y - w.y * v.x,
|
||||
};
|
||||
let uw_cross = Vec3 {
|
||||
x: u.y * w.z - u.z * w.y,
|
||||
y: u.z * w.x - u.x * w.z,
|
||||
z: u.x * w.y - u.y * w.x,
|
||||
};
|
||||
let alpha = (wv_cross.x * normal.x + wv_cross.y * normal.y + wv_cross.z * normal.z) / (uv_cross.x * normal.x + uv_cross.y * normal.y + uv_cross.z * normal.z);
|
||||
let beta = (uw_cross.x * normal.x + uw_cross.y * normal.y + uw_cross.z * normal.z) / (uv_cross.x * normal.x + uv_cross.y * normal.y + uv_cross.z * normal.z);
|
||||
if alpha >= 0.0 && beta >= 0.0 && alpha + beta <= 1.0 {
|
||||
|
||||
hit_record.p = P;
|
||||
hit_record.t = t;
|
||||
hit_record.normal = normal;
|
||||
hit_record.front_face = is_front_face(r, normal);
|
||||
hit_record.material = if let Some(ref m) = self.material {
|
||||
match m {
|
||||
MaterialKind::Lambertian(l) => Some(MaterialKind::Lambertian(l.clone())),
|
||||
MaterialKind::Metal(m) => Some(MaterialKind::Metal(m.clone())),
|
||||
MaterialKind::Dielectric(d) => Some(MaterialKind::Dielectric(d.clone())),
|
||||
}
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
return true;
|
||||
}
|
||||
false
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue