rust/hwphysics/src/grid.rs
changeset 14178 a4c17cfaa4c9
child 14179 abbb74b9cb62
equal deleted inserted replaced
14177:a4dd3d307115 14178:a4c17cfaa4c9
       
     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 }