1 use std::{ |
1 use std::ops::RangeInclusive; |
2 ops::RangeInclusive |
|
3 }; |
|
4 |
2 |
5 use crate::{ |
3 use crate::{ |
6 common::{GearId, GearData, GearDataProcessor}, |
4 common::{GearData, GearDataProcessor, GearId}, |
|
5 grid::Grid, |
7 physics::PhysicsData, |
6 physics::PhysicsData, |
8 grid::Grid |
|
9 }; |
7 }; |
10 |
8 |
11 use fpnum::*; |
9 use fpnum::*; |
12 use integral_geometry::{ |
10 use integral_geometry::{GridIndex, Point, Size}; |
13 Point, Size, GridIndex |
|
14 }; |
|
15 use land2d::Land2D; |
11 use land2d::Land2D; |
16 |
12 |
17 pub fn fppoint_round(point: &FPPoint) -> Point { |
13 pub fn fppoint_round(point: &FPPoint) -> Point { |
18 Point::new(point.x().round() as i32, point.y().round() as i32) |
14 Point::new(point.x().round() as i32, point.y().round() as i32) |
19 } |
15 } |
20 |
16 |
21 #[derive(PartialEq, Eq, Clone, Copy, Debug)] |
17 #[derive(PartialEq, Eq, Clone, Copy, Debug)] |
22 pub struct CircleBounds { |
18 pub struct CircleBounds { |
23 pub center: FPPoint, |
19 pub center: FPPoint, |
24 pub radius: FPNum |
20 pub radius: FPNum, |
25 } |
21 } |
26 |
22 |
27 impl CircleBounds { |
23 impl CircleBounds { |
28 pub fn intersects(&self, other: &CircleBounds) -> bool { |
24 pub fn intersects(&self, other: &CircleBounds) -> bool { |
29 (other.center - self.center).is_in_range(self.radius + other.radius) |
25 (other.center - self.center).is_in_range(self.radius + other.radius) |
37 } |
33 } |
38 } |
34 } |
39 |
35 |
40 #[derive(PartialEq, Eq, Clone, Copy, Debug)] |
36 #[derive(PartialEq, Eq, Clone, Copy, Debug)] |
41 pub struct CollisionData { |
37 pub struct CollisionData { |
42 pub bounds: CircleBounds |
38 pub bounds: CircleBounds, |
43 } |
39 } |
44 |
40 |
45 impl GearData for CollisionData {} |
41 impl GearData for CollisionData {} |
46 |
42 |
47 #[derive(PartialEq, Eq, Clone, Copy, Debug)] |
43 #[derive(PartialEq, Eq, Clone, Copy, Debug)] |
48 pub struct ContactData { |
44 pub struct ContactData { |
49 pub elasticity: FPNum, |
45 pub elasticity: FPNum, |
50 pub friction: FPNum |
46 pub friction: FPNum, |
51 } |
47 } |
52 |
48 |
53 impl GearData for ContactData {} |
49 impl GearData for ContactData {} |
54 |
50 |
55 struct EnabledCollisionsCollection { |
51 struct EnabledCollisionsCollection { |
56 gear_ids: Vec<GearId>, |
52 gear_ids: Vec<GearId>, |
57 collisions: Vec<CollisionData> |
53 collisions: Vec<CollisionData>, |
58 } |
54 } |
59 |
55 |
60 impl EnabledCollisionsCollection { |
56 impl EnabledCollisionsCollection { |
61 fn new() -> Self { |
57 fn new() -> Self { |
62 Self { |
58 Self { |
63 gear_ids: Vec::new(), |
59 gear_ids: Vec::new(), |
64 collisions: Vec::new() |
60 collisions: Vec::new(), |
65 } |
61 } |
66 } |
62 } |
67 |
63 |
68 fn push(&mut self, gear_id: GearId, collision: CollisionData) { |
64 fn push(&mut self, gear_id: GearId, collision: CollisionData) { |
69 self.gear_ids.push(gear_id); |
65 self.gear_ids.push(gear_id); |
82 detected_collisions: DetectedCollisions, |
78 detected_collisions: DetectedCollisions, |
83 } |
79 } |
84 |
80 |
85 pub struct DetectedCollisions { |
81 pub struct DetectedCollisions { |
86 pub pairs: Vec<(GearId, GearId)>, |
82 pub pairs: Vec<(GearId, GearId)>, |
87 pub positions: Vec<Point> |
83 pub positions: Vec<Point>, |
88 } |
84 } |
89 |
85 |
90 impl DetectedCollisions { |
86 impl DetectedCollisions { |
91 pub fn new(capacity: usize) -> Self { |
87 pub fn new(capacity: usize) -> Self { |
92 Self { |
88 Self { |
104 impl CollisionProcessor { |
100 impl CollisionProcessor { |
105 pub fn new(size: Size) -> Self { |
101 pub fn new(size: Size) -> Self { |
106 Self { |
102 Self { |
107 grid: Grid::new(size), |
103 grid: Grid::new(size), |
108 enabled_collisions: EnabledCollisionsCollection::new(), |
104 enabled_collisions: EnabledCollisionsCollection::new(), |
109 detected_collisions: DetectedCollisions::new(0) |
105 detected_collisions: DetectedCollisions::new(0), |
110 } |
106 } |
111 } |
107 } |
112 |
108 |
113 pub fn process(&mut self, land: &Land2D<u32>, updates: &crate::physics::PositionUpdates) { |
109 pub fn process(&mut self, land: &Land2D<u32>, updates: &crate::physics::PositionUpdates) { |
114 self.grid.check_collisions(&mut self.detected_collisions); |
110 self.grid.check_collisions(&mut self.detected_collisions); |
115 |
111 |
116 for (gear_id, collision) in self.enabled_collisions.iter() { |
112 for (gear_id, collision) in self.enabled_collisions.iter() { |
117 if collision.bounds.rows().any(|(y, r)| (&land[y][r]).iter().any(|v| *v != 0)) { |
113 if collision |
118 self.detected_collisions.push(gear_id, 0, &collision.bounds.center) |
114 .bounds |
|
115 .rows() |
|
116 .any(|(y, r)| (&land[y][r]).iter().any(|v| *v != 0)) |
|
117 { |
|
118 self.detected_collisions |
|
119 .push(gear_id, 0, &collision.bounds.center) |
119 } |
120 } |
120 } |
121 } |
121 } |
122 } |
122 } |
123 } |
123 |
124 |