rust/hwphysics/src/grid.rs
changeset 15261 501dfa1c8deb
parent 15120 febccab419b1
child 15262 d8c4fd911b37
equal deleted inserted replaced
15260:775d7efa4e5c 15261:501dfa1c8deb
     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 {