15120
|
1 |
use crate::{
|
|
2 |
collision::{fppoint_round, CircleBounds, DetectedCollisions},
|
|
3 |
common::GearId,
|
|
4 |
};
|
|
5 |
|
|
6 |
use fpnum::FPPoint;
|
|
7 |
use integral_geometry::{GridIndex, Point, Size};
|
|
8 |
|
|
9 |
struct GridBin {
|
|
10 |
refs: Vec<GearId>,
|
|
11 |
static_entries: Vec<CircleBounds>,
|
|
12 |
dynamic_entries: Vec<CircleBounds>,
|
|
13 |
}
|
|
14 |
|
|
15 |
impl GridBin {
|
|
16 |
fn new() -> Self {
|
|
17 |
Self {
|
|
18 |
refs: vec![],
|
|
19 |
static_entries: vec![],
|
|
20 |
dynamic_entries: vec![],
|
|
21 |
}
|
|
22 |
}
|
|
23 |
}
|
|
24 |
|
|
25 |
const GRID_BIN_SIZE: usize = 128;
|
|
26 |
|
|
27 |
pub struct Grid {
|
|
28 |
bins: Vec<GridBin>,
|
|
29 |
space_size: Size,
|
|
30 |
bins_count: Size,
|
|
31 |
index: GridIndex,
|
|
32 |
}
|
|
33 |
|
|
34 |
impl Grid {
|
|
35 |
pub fn new(size: Size) -> Self {
|
|
36 |
assert!(size.is_power_of_two());
|
|
37 |
let bins_count = Size::new(size.width / GRID_BIN_SIZE, size.height / GRID_BIN_SIZE);
|
|
38 |
|
|
39 |
Self {
|
|
40 |
bins: (0..bins_count.area()).map(|_| GridBin::new()).collect(),
|
|
41 |
space_size: size,
|
|
42 |
bins_count,
|
|
43 |
index: Size::square(GRID_BIN_SIZE).to_grid_index(),
|
|
44 |
}
|
|
45 |
}
|
|
46 |
|
|
47 |
fn bin_index(&self, position: &FPPoint) -> Point {
|
|
48 |
self.index.map(fppoint_round(position))
|
|
49 |
}
|
|
50 |
|
|
51 |
fn lookup_bin(&mut self, position: &FPPoint) -> &mut GridBin {
|
|
52 |
let index = self.bin_index(position);
|
|
53 |
&mut self.bins[index.x as usize * self.bins_count.width + index.y as usize]
|
|
54 |
}
|
|
55 |
|
|
56 |
pub fn insert_static(&mut self, gear_id: GearId, bounds: &CircleBounds) {
|
|
57 |
self.lookup_bin(&bounds.center).static_entries.push(*bounds)
|
|
58 |
}
|
|
59 |
|
|
60 |
pub fn insert_dynamic(&mut self, gear_id: GearId, bounds: &CircleBounds) {
|
|
61 |
self.lookup_bin(&bounds.center)
|
|
62 |
.dynamic_entries
|
|
63 |
.push(*bounds)
|
|
64 |
}
|
|
65 |
|
|
66 |
pub fn check_collisions(&self, collisions: &mut DetectedCollisions) {
|
|
67 |
for bin in &self.bins {
|
|
68 |
for bounds in &bin.dynamic_entries {
|
|
69 |
for other in &bin.dynamic_entries {
|
|
70 |
if bounds.intersects(other) && bounds != other {
|
|
71 |
collisions.push(0, 0, &bounds.center)
|
|
72 |
}
|
|
73 |
}
|
|
74 |
|
|
75 |
for other in &bin.static_entries {
|
|
76 |
if bounds.intersects(other) {
|
|
77 |
collisions.push(0, 0, &bounds.center)
|
|
78 |
}
|
|
79 |
}
|
|
80 |
}
|
|
81 |
}
|
|
82 |
}
|
|
83 |
}
|