arcane_engine/physics/
broadphase.rs1use std::collections::{HashMap, HashSet};
2
3use super::types::BodyId;
4
5pub struct SpatialHash {
6 #[allow(dead_code)]
7 cell_size: f32,
8 inv_cell_size: f32,
9 cells: HashMap<(i32, i32), Vec<BodyId>>,
10}
11
12impl SpatialHash {
13 pub fn new(cell_size: f32) -> Self {
14 let cell_size = if cell_size > 0.0 { cell_size } else { 64.0 };
15 Self {
16 cell_size,
17 inv_cell_size: 1.0 / cell_size,
18 cells: HashMap::new(),
19 }
20 }
21
22 pub fn clear(&mut self) {
23 self.cells.clear();
24 }
25
26 pub fn insert(&mut self, id: BodyId, min_x: f32, min_y: f32, max_x: f32, max_y: f32) {
28 let x0 = (min_x * self.inv_cell_size).floor() as i32;
29 let y0 = (min_y * self.inv_cell_size).floor() as i32;
30 let x1 = (max_x * self.inv_cell_size).floor() as i32;
31 let y1 = (max_y * self.inv_cell_size).floor() as i32;
32
33 for cx in x0..=x1 {
34 for cy in y0..=y1 {
35 self.cells.entry((cx, cy)).or_default().push(id);
36 }
37 }
38 }
39
40 pub fn get_pairs(&self) -> Vec<(BodyId, BodyId)> {
42 let mut seen = HashSet::new();
43 let mut pairs = Vec::new();
44
45 for cell_bodies in self.cells.values() {
46 let n = cell_bodies.len();
47 for i in 0..n {
48 for j in (i + 1)..n {
49 let a = cell_bodies[i];
50 let b = cell_bodies[j];
51 let pair = if a < b { (a, b) } else { (b, a) };
52 if seen.insert(pair) {
53 pairs.push(pair);
54 }
55 }
56 }
57 }
58 pairs
59 }
60}