Hit objects in the inner region

This commit is contained in:
numzero 2024-06-10 20:04:53 +03:00
parent 9ec5f17754
commit 4b511af742

View File

@ -131,6 +131,7 @@ enum Subspace {
struct Hit {
distance: f32,
id: i32,
pos: Vec2,
}
struct FlatTraceResult {
@ -180,13 +181,19 @@ impl Space {
std::iter::successors(Some(ray), |&ray| Some(self.trace_step(ray)))
}
fn trace_inner(&self, ray: Ray) -> Ray {
fn trace_inner(&self, ray: Ray) -> FlatTraceResult {
assert_eq!(self.which_subspace(ray.pos), Inner);
let cell = RectInside { rect: self.rect };
let ray = cell.ray_to_local(ray);
let objs = Self::trace_to_objects(self.list_objects_inner().as_slice(), ray);
let dist = cell.to_boundary(ray).expect("Can't get outta here!");
let ray = ray.forward(dist);
cell.ray_to_global(ray)
FlatTraceResult {
end: Some(cell.ray_to_global(ray)),
objects: objs.into_iter().filter_map(|Hit { id, distance, pos }|
if distance < dist { Some(Hit { id, distance, pos: cell.pos_to_global(pos) }) } else { None }
).collect(),
}
}
fn trace_outer(&self, ray: Ray) -> FlatTraceResult {
@ -234,6 +241,26 @@ impl Space {
}).collect()
}
fn list_objects_inner(&self) -> Vec<Object> {
let cell = RectInside { rect: self.rect };
self.objs.iter().map(|&obj| {
match self.which_subspace(obj.loc.pos) {
Inner | Outer => {
// NB: не работает для частей Outer с |y| < external_halflength. Но они и не нужны.
Object {
id: obj.id,
loc: Location {
pos: cell.pos_to_local(obj.loc.pos), // в плоской СК для Inner или её продолжении на Outer
rot: obj.loc.rot,
},
r: obj.r,
}
}
Boundary => panic!("Object {} was destroyed by the space curvature", obj.id),
}
}).collect()
}
fn trace_to_objects(objs: &[Object], ray: Ray) -> Vec<Hit> {
objs.iter()
.filter_map(|obj| {
@ -242,7 +269,7 @@ impl Space {
if diff > 0.0 {
let t = (-rel.dot(ray.dir) - diff.sqrt()) / ray.dir.length_squared();
if t >= 0.0 {
return Some(Hit { id: obj.id, distance: t });
return Some(Hit { id: obj.id, distance: t, pos: ray.forward(t).pos });
}
}
None
@ -271,27 +298,22 @@ fn draw_ray_2(gc: &mut Vec<Draw>, space: &Space, base: Vec2, dir: Vec2) {
// gc.dash_length(6.0);
gc.new_path();
gc.move_to(ray.pos.x, ray.pos.y);
match sub {
Inner => {
ray = space.trace_inner(ray);
}
Outer => {
let ret = space.trace_outer(ray);
for hit in ret.objects {
let r = ray.forward(hit.distance);
hits.circle(r.pos.x, r.pos.y, 1.5);
}
ray = match ret.end {
Some(r) => r,
None => {
ray = ray.forward(1000.0 / DT);
gc.line_to(ray.pos.x, ray.pos.y);
break;
}
};
}
let ret = match sub {
Inner => space.trace_inner(ray),
Outer => space.trace_outer(ray),
Boundary => panic!(),
};
for hit in ret.objects {
hits.circle(hit.pos.x, hit.pos.y, 1.5);
}
ray = match ret.end {
Some(r) => r,
None => {
ray = ray.forward(1000.0 / DT);
gc.line_to(ray.pos.x, ray.pos.y);
break;
}
};
gc.line_to(ray.pos.x, ray.pos.y);
gc.stroke();
gc.new_dash_pattern();