Trace all objects hit
This commit is contained in:
parent
ab5446385b
commit
69cc1904a8
|
|
@ -1,4 +1,3 @@
|
||||||
use std::cmp::Ordering;
|
|
||||||
use std::f32::consts::PI;
|
use std::f32::consts::PI;
|
||||||
use flo_draw::*;
|
use flo_draw::*;
|
||||||
use flo_canvas::*;
|
use flo_canvas::*;
|
||||||
|
|
@ -125,10 +124,14 @@ enum Subspace {
|
||||||
Inner,
|
Inner,
|
||||||
}
|
}
|
||||||
|
|
||||||
enum FlatTraceResult {
|
struct Hit {
|
||||||
Infinity(Vec2),
|
distance: f32,
|
||||||
Edge(Ray),
|
id: i32,
|
||||||
Object(Ray, i32),
|
}
|
||||||
|
|
||||||
|
struct FlatTraceResult {
|
||||||
|
end: Option<Ray>,
|
||||||
|
objects: Vec<Hit>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Space {
|
impl Space {
|
||||||
|
|
@ -178,24 +181,23 @@ impl Space {
|
||||||
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 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 { pos: ray.pos + ray.dir * dist, dir: ray.dir };
|
let ray = ray.forward(dist);
|
||||||
cell.ray_to_global(ray)
|
cell.ray_to_global(ray)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn trace_outer(&self, ray: Ray) -> FlatTraceResult {
|
fn trace_outer(&self, ray: Ray) -> FlatTraceResult {
|
||||||
assert_eq!(self.which_subspace(ray.pos), Outer);
|
assert_eq!(self.which_subspace(ray.pos), Outer);
|
||||||
let cell = basic_shapes::Rect { size: vec2(self.rect.outer_radius, self.rect.external_halflength) };
|
let cell = basic_shapes::Rect { size: vec2(self.rect.outer_radius, self.rect.external_halflength) };
|
||||||
let obj = Self::trace_to_object(self.list_objects_outer(), ray);
|
let objs = Self::trace_to_objects(self.list_objects_outer(), ray);
|
||||||
let sub = cell.trace_into(ray);
|
if let Some(dist) = cell.trace_into(ray) {
|
||||||
let rray = |dist: f32| Ray { pos: ray.pos + ray.dir * dist, dir: ray.dir };
|
FlatTraceResult {
|
||||||
match (sub, obj) {
|
end: Some(ray.forward(dist)),
|
||||||
(None, None) => FlatTraceResult::Infinity(ray.dir),
|
objects: objs.into_iter().filter(|hit| hit.distance < dist).collect(),
|
||||||
(Some(dist), None) => FlatTraceResult::Edge(rray(dist)),
|
}
|
||||||
(None, Some((id, dist))) => FlatTraceResult::Object(rray(dist), id),
|
} else {
|
||||||
(Some(sdist), Some((id, odist))) => if sdist < odist {
|
FlatTraceResult {
|
||||||
FlatTraceResult::Edge(rray(sdist))
|
end: None,
|
||||||
} else {
|
objects: objs,
|
||||||
FlatTraceResult::Object(rray(odist), id)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -211,7 +213,7 @@ impl Space {
|
||||||
self.objs.as_slice()
|
self.objs.as_slice()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn trace_to_object(objs: &[Object], ray: Ray) -> Option<(i32, f32)> {
|
fn trace_to_objects(objs: &[Object], ray: Ray) -> Vec<Hit> {
|
||||||
objs.iter()
|
objs.iter()
|
||||||
.filter_map(|obj| {
|
.filter_map(|obj| {
|
||||||
let rel = ray.pos - obj.loc.pos;
|
let rel = ray.pos - obj.loc.pos;
|
||||||
|
|
@ -219,16 +221,16 @@ 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((obj.id, t));
|
return Some(Hit { id: obj.id, distance: t });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None
|
None
|
||||||
})
|
}).collect()
|
||||||
.min_by(|(_, d1), (_, d2)| f32::total_cmp(d1, d2))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn draw_ray_2(gc: &mut Vec<Draw>, space: &Space, base: Vec2, dir: Vec2) {
|
fn draw_ray_2(gc: &mut Vec<Draw>, space: &Space, base: Vec2, dir: Vec2) {
|
||||||
|
let mut hits = Vec::<Draw>::new();
|
||||||
let dir = space.rect.globalize(base, dir);
|
let dir = space.rect.globalize(base, dir);
|
||||||
gc.new_path();
|
gc.new_path();
|
||||||
gc.move_to(base.x, base.y);
|
gc.move_to(base.x, base.y);
|
||||||
|
|
@ -253,23 +255,18 @@ fn draw_ray_2(gc: &mut Vec<Draw>, space: &Space, base: Vec2, dir: Vec2) {
|
||||||
ray = space.trace_inner(ray);
|
ray = space.trace_inner(ray);
|
||||||
}
|
}
|
||||||
Outer => {
|
Outer => {
|
||||||
ray = match space.trace_outer(ray) {
|
let ret = space.trace_outer(ray);
|
||||||
FlatTraceResult::Edge(r) => r,
|
for hit in ret.objects {
|
||||||
FlatTraceResult::Infinity(dir) => {
|
let r = ray.forward(hit.distance);
|
||||||
ray.pos += dir * (1000.0 / DT);
|
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);
|
gc.line_to(ray.pos.x, ray.pos.y);
|
||||||
gc.stroke();
|
|
||||||
break;
|
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!(),
|
Boundary => panic!(),
|
||||||
|
|
@ -281,7 +278,10 @@ fn draw_ray_2(gc: &mut Vec<Draw>, space: &Space, base: Vec2, dir: Vec2) {
|
||||||
gc.move_to(ray.pos.x, ray.pos.y);
|
gc.move_to(ray.pos.x, ray.pos.y);
|
||||||
}
|
}
|
||||||
gc.stroke();
|
gc.stroke();
|
||||||
|
gc.new_path();
|
||||||
gc.new_dash_pattern();
|
gc.new_dash_pattern();
|
||||||
|
gc.append(&mut hits);
|
||||||
|
gc.stroke();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn draw_fan_2(gc: &mut Vec<Draw>, space: &Space, base: Vec2, dir: Vec2, spread: f32) {
|
fn draw_fan_2(gc: &mut Vec<Draw>, space: &Space, base: Vec2, dir: Vec2, spread: f32) {
|
||||||
|
|
@ -367,6 +367,12 @@ struct Ray {
|
||||||
dir: Vec2,
|
dir: Vec2,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Ray {
|
||||||
|
fn forward(&self, dist: f32) -> Ray {
|
||||||
|
Ray { pos: self.pos + self.dir * dist, dir: self.dir }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
mod basic_shapes {
|
mod basic_shapes {
|
||||||
use glam::{Vec2, vec2};
|
use glam::{Vec2, vec2};
|
||||||
use crate::Ray;
|
use crate::Ray;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user