5 |
5 |
6 use fpnum::FPPoint; |
6 use fpnum::FPPoint; |
7 use integral_geometry::{GridIndex, Point, Size}; |
7 use integral_geometry::{GridIndex, Point, Size}; |
8 |
8 |
9 struct GridBin { |
9 struct GridBin { |
10 refs: Vec<GearId>, |
10 static_refs: Vec<GearId>, |
11 static_entries: Vec<CircleBounds>, |
11 static_entries: Vec<CircleBounds>, |
|
12 |
|
13 dynamic_refs: Vec<GearId>, |
12 dynamic_entries: Vec<CircleBounds>, |
14 dynamic_entries: Vec<CircleBounds>, |
13 } |
15 } |
14 |
16 |
15 impl GridBin { |
17 impl GridBin { |
16 fn new() -> Self { |
18 fn new() -> Self { |
17 Self { |
19 Self { |
18 refs: vec![], |
20 static_refs: vec![], |
19 static_entries: vec![], |
21 static_entries: vec![], |
|
22 dynamic_refs: vec![], |
20 dynamic_entries: vec![], |
23 dynamic_entries: vec![], |
21 } |
24 } |
22 } |
25 } |
23 } |
26 } |
24 |
27 |
46 |
49 |
47 fn bin_index(&self, position: &FPPoint) -> Point { |
50 fn bin_index(&self, position: &FPPoint) -> Point { |
48 self.index.map(fppoint_round(position)) |
51 self.index.map(fppoint_round(position)) |
49 } |
52 } |
50 |
53 |
51 fn lookup_bin(&mut self, position: &FPPoint) -> &mut GridBin { |
54 fn get_bin(&mut self, index: Point) -> &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] |
55 &mut self.bins[index.x as usize * self.bins_count.width + index.y as usize] |
54 } |
56 } |
55 |
57 |
|
58 fn lookup_bin(&mut self, position: &FPPoint) -> &mut GridBin { |
|
59 self.get_bin(self.bin_index(position)) |
|
60 } |
|
61 |
56 pub fn insert_static(&mut self, gear_id: GearId, bounds: &CircleBounds) { |
62 pub fn insert_static(&mut self, gear_id: GearId, bounds: &CircleBounds) { |
57 self.lookup_bin(&bounds.center).static_entries.push(*bounds) |
63 let bin = self.lookup_bin(&bounds.center); |
|
64 bin.static_refs.push(gear_id); |
|
65 bin.static_entries.push(*bounds) |
58 } |
66 } |
59 |
67 |
60 pub fn insert_dynamic(&mut self, gear_id: GearId, bounds: &CircleBounds) { |
68 pub fn insert_dynamic(&mut self, gear_id: GearId, bounds: &CircleBounds) { |
61 self.lookup_bin(&bounds.center) |
69 let bin = self.lookup_bin(&bounds.center); |
62 .dynamic_entries |
70 bin.dynamic_refs.push(gear_id); |
63 .push(*bounds) |
71 bin.dynamic_entries.push(*bounds); |
|
72 } |
|
73 |
|
74 pub fn update_position( |
|
75 &mut self, |
|
76 gear_id: GearId, |
|
77 old_position: &FPPoint, |
|
78 new_position: &FPPoint, |
|
79 ) { |
|
80 let old_bin_index = self.bin_index(old_position); |
|
81 let new_bin_index = self.bin_index(new_position); |
|
82 |
|
83 let old_bin = self.lookup_bin(old_position); |
|
84 if let Some(index) = old_bin.static_refs.iter().position(|id| *id == gear_id) { |
|
85 let bounds = old_bin.static_entries.swap_remove(index); |
|
86 old_bin.static_refs.swap_remove(index); |
|
87 |
|
88 let new_bin = if old_bin_index == new_bin_index { |
|
89 old_bin |
|
90 } else { |
|
91 self.get_bin(new_bin_index) |
|
92 }; |
|
93 |
|
94 new_bin.dynamic_refs.push(gear_id); |
|
95 new_bin.dynamic_entries.push(CircleBounds { |
|
96 center: *new_position, |
|
97 ..bounds |
|
98 }); |
|
99 } else if let Some(index) = old_bin.dynamic_refs.iter().position(|id| *id == gear_id) { |
|
100 if old_bin_index == new_bin_index { |
|
101 old_bin.dynamic_entries[index].center = *new_position |
|
102 } else { |
|
103 let bounds = old_bin.dynamic_entries.swap_remove(index); |
|
104 let new_bin = self.get_bin(new_bin_index); |
|
105 |
|
106 new_bin.dynamic_refs.push(gear_id); |
|
107 new_bin.dynamic_entries.push(CircleBounds { |
|
108 center: *new_position, |
|
109 ..bounds |
|
110 }); |
|
111 } |
|
112 } |
64 } |
113 } |
65 |
114 |
66 pub fn check_collisions(&self, collisions: &mut DetectedCollisions) { |
115 pub fn check_collisions(&self, collisions: &mut DetectedCollisions) { |
67 for bin in &self.bins { |
116 for bin in &self.bins { |
68 for bounds in &bin.dynamic_entries { |
117 for bounds in &bin.dynamic_entries { |