Trace to objects
This commit is contained in:
parent
3362df4109
commit
e840b3f47b
|
|
@ -1,3 +1,4 @@
|
|||
use std::cmp::Ordering;
|
||||
use std::f32::consts::PI;
|
||||
use flo_draw::*;
|
||||
use flo_canvas::*;
|
||||
|
|
@ -114,6 +115,12 @@ enum Subspace {
|
|||
Inner,
|
||||
}
|
||||
|
||||
enum FlatTraceResult {
|
||||
Infinity(Vec2),
|
||||
Edge(Ray),
|
||||
Object(Ray, i32),
|
||||
}
|
||||
|
||||
impl Space {
|
||||
fn which_subspace(&self, pt: Vec2) -> Subspace {
|
||||
if pt.y.abs() > self.rect.external_halflength {
|
||||
|
|
@ -165,13 +172,21 @@ impl Space {
|
|||
cell.ray_to_global(ray)
|
||||
}
|
||||
|
||||
fn trace_outer(&self, ray: Ray) -> Option<Ray> {
|
||||
fn trace_outer(&self, ray: Ray) -> FlatTraceResult {
|
||||
assert_eq!(self.which_subspace(ray.pos), Outer);
|
||||
let cell = basic_shapes::Rect { size: vec2(self.rect.outer_radius, self.rect.external_halflength) };
|
||||
if let Some(dist) = cell.trace_into(ray) {
|
||||
Some(Ray { pos: ray.pos + ray.dir * dist, dir: ray.dir })
|
||||
let obj = Self::trace_to_object(self.list_objects_outer(), ray);
|
||||
let sub = cell.trace_into(ray);
|
||||
let rray = |dist: f32| Ray { pos: ray.pos + ray.dir * dist, dir: ray.dir };
|
||||
match (sub, obj) {
|
||||
(None, None) => FlatTraceResult::Infinity(ray.dir),
|
||||
(Some(dist), None) => FlatTraceResult::Edge(rray(dist)),
|
||||
(None, Some((id, dist))) => FlatTraceResult::Object(rray(dist), id),
|
||||
(Some(sdist), Some((id, odist))) => if sdist < odist {
|
||||
FlatTraceResult::Edge(rray(sdist))
|
||||
} else {
|
||||
None
|
||||
FlatTraceResult::Object(rray(odist), id)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -181,6 +196,26 @@ impl Space {
|
|||
.find(|&ray| self.which_subspace(ray.pos) != Boundary)
|
||||
.expect("Can't get outta the wall!")
|
||||
}
|
||||
|
||||
fn list_objects_outer(&self) -> &[Object] {
|
||||
self.objs.as_slice()
|
||||
}
|
||||
|
||||
fn trace_to_object(objs: &[Object], ray: Ray) -> Option<(i32, f32)> {
|
||||
objs.iter()
|
||||
.filter_map(|obj| {
|
||||
let rel = ray.pos - obj.loc.pos;
|
||||
let diff = rel.dot(ray.dir).powi(2) - ray.dir.length_squared() * (rel.length_squared() - obj.r.powi(2));
|
||||
if diff > 0.0 {
|
||||
let t = (-rel.dot(ray.dir) - diff.sqrt()) / ray.dir.length_squared();
|
||||
if t >= 0.0 {
|
||||
return Some((obj.id, t));
|
||||
}
|
||||
}
|
||||
None
|
||||
})
|
||||
.min_by(|(_, d1), (_, d2)| f32::total_cmp(d1, d2))
|
||||
}
|
||||
}
|
||||
|
||||
fn draw_ray_2(gc: &mut Vec<Draw>, space: &Space, base: Vec2, dir: Vec2) {
|
||||
|
|
@ -209,13 +244,22 @@ fn draw_ray_2(gc: &mut Vec<Draw>, space: &Space, base: Vec2, dir: Vec2) {
|
|||
}
|
||||
Outer => {
|
||||
ray = match space.trace_outer(ray) {
|
||||
Some(r) => r,
|
||||
None => {
|
||||
ray.pos += ray.dir * (1000.0 / DT);
|
||||
FlatTraceResult::Edge(r) => r,
|
||||
FlatTraceResult::Infinity(dir) => {
|
||||
ray.pos += dir * (1000.0 / DT);
|
||||
gc.line_to(ray.pos.x, ray.pos.y);
|
||||
gc.stroke();
|
||||
break;
|
||||
}
|
||||
FlatTraceResult::Object(r, id) => {
|
||||
gc.line_to(r.pos.x, r.pos.y);
|
||||
gc.stroke();
|
||||
gc.new_path();
|
||||
gc.new_dash_pattern();
|
||||
gc.circle(r.pos.x, r.pos.y, 1.5);
|
||||
gc.stroke();
|
||||
r
|
||||
}
|
||||
};
|
||||
}
|
||||
Boundary => panic!(),
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user