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