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