diff --git a/src/bin/flat/main.rs b/src/bin/flat/main.rs index dd87c4d..30c066c 100644 --- a/src/bin/flat/main.rs +++ b/src/bin/flat/main.rs @@ -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 { + 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 { 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, 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();