Unify object hitting code

This commit is contained in:
numzero 2024-06-11 00:12:16 +03:00
parent 39a4ee5824
commit 8e31359a69

View File

@ -193,18 +193,10 @@ impl Space {
let cell = RectInside { rect: self.rect }; let cell = RectInside { rect: self.rect };
let ray = cell.ray_to_local(ray); let ray = cell.ray_to_local(ray);
let objs = self.list_objects_inner(); let objs = self.list_objects_inner();
let hits = Self::trace_to_objects(objs.as_slice(), ray);
let dist = cell.to_boundary(ray).expect("Can't get outta here!"); let dist = cell.to_boundary(ray).expect("Can't get outta here!");
FlatTraceResult { FlatTraceResult {
end: Some(cell.ray_to_global(ray.forward(dist))), end: Some(cell.ray_to_global(ray.forward(dist))),
objects: hits.into_iter().filter_map(|HitInternal { object, distance }| objects: Self::hit_objects(objs.as_slice(), ray, dist, |pos| cell.pos_to_global(pos)),
if distance < dist {
let pos = ray.forward(distance).pos;
let rel = object.loc.rot.inverse() * (pos - object.loc.pos);
let dir = object.loc.rot.inverse() * ray.dir;
Some(Hit { id: object.id, distance, pos: cell.pos_to_global(pos), rel: Ray { pos: rel, dir } })
} else { None }
).collect(),
} }
} }
@ -212,19 +204,11 @@ impl Space {
assert_eq!(self.which_subspace(ray.pos), Outer); assert_eq!(self.which_subspace(ray.pos), Outer);
let cell = basic_shapes::Rect { size: vec2(self.rect.outer_radius, self.rect.external_halflength) }; let cell = basic_shapes::Rect { size: vec2(self.rect.outer_radius, self.rect.external_halflength) };
let objs = self.list_objects_outer(); let objs = self.list_objects_outer();
let hits = Self::trace_to_objects(objs.as_slice(), ray);
let lim = cell.trace_into(ray); let lim = cell.trace_into(ray);
let dist = lim.unwrap_or(f32::INFINITY); let dist = lim.unwrap_or(f32::INFINITY);
FlatTraceResult { FlatTraceResult {
end: lim.map(|dist| ray.forward(dist)), end: lim.map(|dist| ray.forward(dist)),
objects: hits.into_iter().filter_map(|HitInternal { object, distance }| objects: Self::hit_objects(objs.as_slice(), ray, dist, |pos| pos),
if distance < dist {
let pos = ray.forward(distance).pos;
let rel = object.loc.rot.inverse() * (pos - object.loc.pos);
let dir = object.loc.rot.inverse() * ray.dir;
Some(Hit { id: object.id, distance, pos, rel: Ray { pos: rel, dir } })
} else { None }
).collect(),
} }
} }
@ -287,7 +271,6 @@ impl Space {
if diff > 0.0 { if diff > 0.0 {
let t = (-rel.dot(ray.dir) - diff.sqrt()) / ray.dir.length_squared(); let t = (-rel.dot(ray.dir) - diff.sqrt()) / ray.dir.length_squared();
if t >= 0.0 { if t >= 0.0 {
let pos = ray.forward(t).pos;
return Some(HitInternal { object: &obj, distance: t }); return Some(HitInternal { object: &obj, distance: t });
} }
} }
@ -295,6 +278,18 @@ impl Space {
}).collect() }).collect()
} }
fn hit_objects(objs: &[Object], ray: Ray, dist: f32, globalize: impl Fn(Vec2) -> Vec2) -> Vec<Hit> {
let hits = Self::trace_to_objects(objs, ray);
hits.into_iter().filter_map(|HitInternal { object, distance }|
if distance < dist {
let pos = ray.forward(distance).pos;
let rel = object.loc.rot.inverse() * (pos - object.loc.pos);
let dir = object.loc.rot.inverse() * ray.dir;
Some(Hit { id: object.id, distance, pos: globalize(pos), rel: Ray { pos: rel, dir } })
} else { None }
).collect()
}
fn line(&self, a: Vec2, b: Vec2, step: f32) -> Vec<Vec2> { fn line(&self, a: Vec2, b: Vec2, step: f32) -> Vec<Vec2> {
match self.which_subspace(a) { match self.which_subspace(a) {
Outer => vec![b], Outer => vec![b],