Hit objects in the inner region
This commit is contained in:
parent
9ec5f17754
commit
4b511af742
|
|
@ -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();
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user