Allow getting all ray-mesh intersections (useful for translucent objects)

This commit is contained in:
numzero 2024-09-14 15:55:01 +03:00
parent 3b4338b033
commit 97286085ab

View File

@ -8,13 +8,15 @@ pub struct TraceResult {
pub normal: Vec3, pub normal: Vec3,
} }
pub fn trace_to_mesh(mesh: &Mesh, base: Vec3, ray: Vec3) -> Option<TraceResult> { pub fn trace_to_mesh_all(
let mut ret: Option<TraceResult> = None; mesh: &Mesh,
let mut dist = f32::INFINITY; base: Vec3,
for f in mesh { ray: Vec3,
) -> impl Iterator<Item = TraceResult> + '_ {
mesh.iter().filter_map(move |f| {
let fs = (0..3).map(|k| edge_dist(f.vertices[k], f.vertices[(k + 1) % 3], base, ray)); 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) { if fs.into_iter().any(|f| f < 0.0) {
continue; return None;
} }
let m = mat3( let m = mat3(
f.vertices[1] - f.vertices[0], f.vertices[1] - f.vertices[0],
@ -23,16 +25,17 @@ pub fn trace_to_mesh(mesh: &Mesh, base: Vec3, ray: Vec3) -> Option<TraceResult>
); );
let m = m.inverse(); let m = m.inverse();
let rel = m * (base - f.vertices[0]); let rel = m * (base - f.vertices[0]);
if rel.z > dist { Some(TraceResult {
continue;
}
dist = rel.z;
ret = Some(TraceResult {
distance: rel.z, distance: rel.z,
normal: f.normal, normal: f.normal,
}); })
} })
ret }
pub fn trace_to_mesh(mesh: &Mesh, base: Vec3, ray: Vec3) -> Option<TraceResult> {
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 { fn edge_dist(a: Vec3, b: Vec3, base: Vec3, dir: Vec3) -> f32 {