|
1 use crate::{ |
|
2 common::{GearId, GearData, GearDataProcessor} |
|
3 }; |
|
4 use fpnum::*; |
|
5 use integral_geometry::{ |
|
6 Point, Size, GridIndex |
|
7 }; |
|
8 |
|
9 #[derive(PartialEq, Eq, Clone, Copy, Debug)] |
|
10 pub struct PhysicsData { |
|
11 pub position: FPPoint, |
|
12 pub velocity: FPPoint, |
|
13 } |
|
14 |
|
15 impl GearData for PhysicsData {} |
|
16 |
|
17 pub struct DynamicPhysicsCollection { |
|
18 gear_ids: Vec<GearId>, |
|
19 positions: Vec<FPPoint>, |
|
20 velocities: Vec<FPPoint>, |
|
21 } |
|
22 |
|
23 impl DynamicPhysicsCollection { |
|
24 fn new() -> Self { |
|
25 Self { |
|
26 gear_ids: Vec::new(), |
|
27 positions: Vec::new(), |
|
28 velocities: Vec::new() |
|
29 } |
|
30 } |
|
31 |
|
32 fn len(&self) -> usize { |
|
33 self.gear_ids.len() |
|
34 } |
|
35 |
|
36 fn push(&mut self, id: GearId, physics: PhysicsData) { |
|
37 self.gear_ids.push(id); |
|
38 self.positions.push(physics.position); |
|
39 self.velocities.push(physics.velocity); |
|
40 } |
|
41 |
|
42 fn iter_pos_update(&mut self) -> impl Iterator<Item = (GearId, (&mut FPPoint, &FPPoint))> { |
|
43 self.gear_ids.iter().cloned() |
|
44 .zip(self.positions.iter_mut() |
|
45 .zip(self.velocities.iter())) |
|
46 } |
|
47 } |
|
48 |
|
49 pub struct StaticPhysicsCollection { |
|
50 gear_ids: Vec<GearId>, |
|
51 positions: Vec<FPPoint> |
|
52 } |
|
53 |
|
54 impl StaticPhysicsCollection { |
|
55 fn new() -> Self { |
|
56 Self { |
|
57 gear_ids: Vec::new(), |
|
58 positions: Vec::new() |
|
59 } |
|
60 } |
|
61 |
|
62 fn push(&mut self, gear_id: GearId, physics: PhysicsData) { |
|
63 self.gear_ids.push(gear_id); |
|
64 self.positions.push(physics.position); |
|
65 } |
|
66 } |
|
67 |
|
68 pub struct PhysicsProcessor { |
|
69 dynamic_physics: DynamicPhysicsCollection, |
|
70 static_physics: StaticPhysicsCollection, |
|
71 |
|
72 physics_cleanup: Vec<GearId>, |
|
73 position_updates: PositionUpdates |
|
74 } |
|
75 |
|
76 pub struct PositionUpdates { |
|
77 pub gear_ids: Vec<GearId>, |
|
78 pub positions: Vec<FPPoint> |
|
79 } |
|
80 |
|
81 impl PositionUpdates { |
|
82 pub fn new(capacity: usize) -> Self { |
|
83 Self { |
|
84 gear_ids: Vec::with_capacity(capacity), |
|
85 positions: Vec::with_capacity(capacity), |
|
86 } |
|
87 } |
|
88 |
|
89 pub fn push(&mut self, gear_id: GearId, position: &FPPoint) { |
|
90 self.gear_ids.push(gear_id); |
|
91 self.positions.push(*position); |
|
92 } |
|
93 } |
|
94 |
|
95 impl PhysicsProcessor { |
|
96 pub fn new() -> Self { |
|
97 PhysicsProcessor { |
|
98 dynamic_physics: DynamicPhysicsCollection::new(), |
|
99 static_physics: StaticPhysicsCollection::new(), |
|
100 physics_cleanup: Vec::new(), |
|
101 position_updates: PositionUpdates::new(0) |
|
102 } |
|
103 } |
|
104 |
|
105 pub fn process(&mut self, time_step: FPNum) -> &PositionUpdates { |
|
106 for (gear_id, (pos, vel)) in self.dynamic_physics.iter_pos_update() { |
|
107 *pos += *vel * time_step; |
|
108 if !vel.is_zero() { |
|
109 self.position_updates.push(gear_id, pos) |
|
110 } else { |
|
111 self.physics_cleanup.push(gear_id) |
|
112 } |
|
113 } |
|
114 &self.position_updates |
|
115 } |
|
116 |
|
117 pub fn push(&mut self, gear_id: GearId, physics_data: PhysicsData) { |
|
118 if physics_data.velocity.is_zero() { |
|
119 self.static_physics.push(gear_id, physics_data); |
|
120 } else { |
|
121 self.dynamic_physics.push(gear_id, physics_data); |
|
122 } |
|
123 } |
|
124 } |
|
125 |
|
126 impl GearDataProcessor<PhysicsData> for PhysicsProcessor { |
|
127 fn add(&mut self, gear_id: GearId, gear_data: PhysicsData) { |
|
128 if gear_data.velocity.is_zero() { |
|
129 self.static_physics.push(gear_id, gear_data); |
|
130 } else { |
|
131 self.dynamic_physics.push(gear_id, gear_data); |
|
132 } |
|
133 } |
|
134 } |