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 { struct Hit {
distance: f32, distance: f32,
id: i32, id: i32,
pos: Vec2,
} }
struct FlatTraceResult { struct FlatTraceResult {
@ -180,13 +181,19 @@ impl Space {
std::iter::successors(Some(ray), |&ray| Some(self.trace_step(ray))) 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); assert_eq!(self.which_subspace(ray.pos), Inner);
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::trace_to_objects(self.list_objects_inner().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!");
let ray = ray.forward(dist); 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 { fn trace_outer(&self, ray: Ray) -> FlatTraceResult {
@ -234,6 +241,26 @@ impl Space {
}).collect() }).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> { fn trace_to_objects(objs: &[Object], ray: Ray) -> Vec<Hit> {
objs.iter() objs.iter()
.filter_map(|obj| { .filter_map(|obj| {
@ -242,7 +269,7 @@ 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 {
return Some(Hit { id: obj.id, distance: t }); return Some(Hit { id: obj.id, distance: t, pos: ray.forward(t).pos });
} }
} }
None 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.dash_length(6.0);
gc.new_path(); gc.new_path();
gc.move_to(ray.pos.x, ray.pos.y); gc.move_to(ray.pos.x, ray.pos.y);
match sub { let ret = match sub {
Inner => { Inner => space.trace_inner(ray),
ray = space.trace_inner(ray); Outer => space.trace_outer(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;
}
};
}
Boundary => panic!(), 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.line_to(ray.pos.x, ray.pos.y);
gc.stroke(); gc.stroke();
gc.new_dash_pattern(); gc.new_dash_pattern();