2 collision::{fppoint_round, CircleBounds, DetectedCollisions}, |
2 collision::{fppoint_round, CircleBounds, DetectedCollisions}, |
3 common::GearId, |
3 common::GearId, |
4 }; |
4 }; |
5 |
5 |
6 use fpnum::FPPoint; |
6 use fpnum::FPPoint; |
7 use integral_geometry::{GridIndex, Point, Size}; |
7 use integral_geometry::{GridIndex, Point, PotSize}; |
8 |
8 |
9 struct GridBin { |
9 struct GridBin { |
10 refs: Vec<GearId>, |
10 refs: Vec<GearId>, |
11 entries: Vec<CircleBounds>, |
11 entries: Vec<CircleBounds>, |
12 } |
12 } |
37 |
37 |
38 const GRID_BIN_SIZE: usize = 128; |
38 const GRID_BIN_SIZE: usize = 128; |
39 |
39 |
40 pub struct Grid { |
40 pub struct Grid { |
41 bins: Vec<GridBin>, |
41 bins: Vec<GridBin>, |
42 space_size: Size, |
42 space_size: PotSize, |
43 bins_count: Size, |
43 bins_count: PotSize, |
44 index: GridIndex, |
44 index: GridIndex, |
45 } |
45 } |
46 |
46 |
47 impl Grid { |
47 impl Grid { |
48 pub fn new(size: Size) -> Self { |
48 pub fn new(size: PotSize) -> Self { |
49 assert!(size.is_power_of_two()); |
49 let bins_count = |
50 let bins_count = Size::new(size.width / GRID_BIN_SIZE, size.height / GRID_BIN_SIZE); |
50 PotSize::new(size.width() / GRID_BIN_SIZE, size.height() / GRID_BIN_SIZE).unwrap(); |
51 |
51 |
52 Self { |
52 Self { |
53 bins: (0..bins_count.area()).map(|_| GridBin::new()).collect(), |
53 bins: (0..bins_count.area()).map(|_| GridBin::new()).collect(), |
54 space_size: size, |
54 space_size: size, |
55 bins_count, |
55 bins_count, |
56 index: Size::square(GRID_BIN_SIZE).to_grid_index(), |
56 index: PotSize::square(GRID_BIN_SIZE).unwrap().to_grid_index(), |
57 } |
57 } |
|
58 } |
|
59 |
|
60 fn linear_bin_index(&self, index: Point) -> usize { |
|
61 self.bins_count |
|
62 .linear_index(index.x as usize, index.y as usize) |
58 } |
63 } |
59 |
64 |
60 fn bin_index(&self, position: &FPPoint) -> Point { |
65 fn bin_index(&self, position: &FPPoint) -> Point { |
61 self.index.map(fppoint_round(position)) |
66 self.index.map(fppoint_round(position)) |
62 } |
67 } |
63 |
68 |
64 fn get_bin(&mut self, index: Point) -> &mut GridBin { |
69 fn get_bin(&mut self, index: Point) -> &mut GridBin { |
65 &mut self.bins[index.y as usize * self.bins_count.width + index.x as usize] |
70 let index = self.linear_bin_index(index); |
|
71 &mut self.bins[index] |
66 } |
72 } |
67 |
73 |
68 fn try_get_bin(&mut self, index: Point) -> Option<&mut GridBin> { |
74 fn try_get_bin(&mut self, index: Point) -> Option<&mut GridBin> { |
69 self.bins |
75 let index = self.linear_bin_index(index); |
70 .get_mut(index.y as usize * self.bins_count.width + index.x as usize) |
76 self.bins.get_mut(index) |
71 } |
77 } |
72 |
78 |
73 fn lookup_bin(&mut self, position: &FPPoint) -> &mut GridBin { |
79 fn lookup_bin(&mut self, position: &FPPoint) -> &mut GridBin { |
74 self.get_bin(self.bin_index(position)) |
80 self.get_bin(self.bin_index(position)) |
75 } |
81 } |
92 self.remove_all(gear_id); |
98 self.remove_all(gear_id); |
93 } |
99 } |
94 } else { |
100 } else { |
95 self.remove_all(gear_id); |
101 self.remove_all(gear_id); |
96 } |
102 } |
97 |
|
98 } |
103 } |
99 |
104 |
100 pub fn check_collisions(&self, collisions: &mut DetectedCollisions) { |
105 pub fn check_collisions(&self, collisions: &mut DetectedCollisions) { |
101 for bin in &self.bins { |
106 for bin in &self.bins { |
102 for (index, bounds) in bin.entries.iter().enumerate() { |
107 for (index, bounds) in bin.entries.iter().enumerate() {} |
103 |
|
104 } |
|
105 } |
108 } |
106 } |
109 } |
107 } |
110 } |