use crate::mesh_loader::Face; use glam::{mat3, Vec3}; pub type Mesh = [Face]; pub struct TraceResult { pub distance: f32, pub normal: Vec3, } pub fn trace_to_mesh_all( mesh: &Mesh, base: Vec3, ray: Vec3, ) -> impl Iterator + '_ { mesh.iter().filter_map(move |f| { let fs = (0..3).map(|k| edge_dist(f.vertices[k], f.vertices[(k + 1) % 3], base, ray)); if fs.into_iter().any(|f| f < 0.0) { return None; } let m = mat3( f.vertices[1] - f.vertices[0], f.vertices[2] - f.vertices[0], -ray, ); let m = m.inverse(); let rel = m * (base - f.vertices[0]); Some(TraceResult { distance: rel.z, normal: f.normal, }) }) } pub fn trace_to_mesh(mesh: &Mesh, base: Vec3, ray: Vec3) -> Option { trace_to_mesh_all(mesh, base, ray) .filter(|tr| tr.distance >= 0.0) .min_by(|a, b| a.distance.total_cmp(&b.distance)) } fn edge_dist(a: Vec3, b: Vec3, base: Vec3, dir: Vec3) -> f32 { // Note: given that the input is not arbitrary but comes from a cartesian product of certain (a, b) pairs and certain (base, dir) pairs, this can be optimized from Cnm to an+bm+cnm with c