|
1 use crate::common::{GearData, GearDataProcessor, GearId, Millis}; |
|
2 use fpnum::*; |
|
3 use integral_geometry::{GridIndex, Point, Size}; |
|
4 |
|
5 #[derive(PartialEq, Eq, Clone, Copy, Debug)] |
|
6 pub struct PhysicsData { |
|
7 pub position: FPPoint, |
|
8 pub velocity: FPPoint, |
|
9 } |
|
10 |
|
11 impl GearData for PhysicsData {} |
|
12 |
|
13 impl PhysicsData { |
|
14 pub fn new(position: FPPoint, velocity: FPPoint) -> Self { |
|
15 Self { position, velocity } |
|
16 } |
|
17 } |
|
18 |
|
19 pub struct DynamicPhysicsCollection { |
|
20 gear_ids: Vec<GearId>, |
|
21 positions: Vec<FPPoint>, |
|
22 velocities: Vec<FPPoint>, |
|
23 } |
|
24 |
|
25 impl DynamicPhysicsCollection { |
|
26 fn new() -> Self { |
|
27 Self { |
|
28 gear_ids: Vec::new(), |
|
29 positions: Vec::new(), |
|
30 velocities: Vec::new(), |
|
31 } |
|
32 } |
|
33 |
|
34 fn len(&self) -> usize { |
|
35 self.gear_ids.len() |
|
36 } |
|
37 |
|
38 fn push(&mut self, gear_id: GearId, physics: PhysicsData) { |
|
39 self.gear_ids.push(gear_id); |
|
40 self.positions.push(physics.position); |
|
41 self.velocities.push(physics.velocity); |
|
42 } |
|
43 |
|
44 fn remove(&mut self, gear_id: GearId) { |
|
45 if let Some(index) = self.gear_ids.iter().position(|id| *id == gear_id) { |
|
46 self.gear_ids.swap_remove(index); |
|
47 self.positions.swap_remove(index); |
|
48 self.velocities.swap_remove(index); |
|
49 } |
|
50 } |
|
51 |
|
52 fn iter_pos_update(&mut self) -> impl Iterator<Item = (GearId, (&mut FPPoint, &FPPoint))> { |
|
53 self.gear_ids |
|
54 .iter() |
|
55 .cloned() |
|
56 .zip(self.positions.iter_mut().zip(self.velocities.iter())) |
|
57 } |
|
58 } |
|
59 |
|
60 pub struct StaticPhysicsCollection { |
|
61 gear_ids: Vec<GearId>, |
|
62 positions: Vec<FPPoint>, |
|
63 } |
|
64 |
|
65 impl StaticPhysicsCollection { |
|
66 fn new() -> Self { |
|
67 Self { |
|
68 gear_ids: Vec::new(), |
|
69 positions: Vec::new(), |
|
70 } |
|
71 } |
|
72 |
|
73 fn push(&mut self, gear_id: GearId, physics: PhysicsData) { |
|
74 self.gear_ids.push(gear_id); |
|
75 self.positions.push(physics.position); |
|
76 } |
|
77 |
|
78 fn remove(&mut self, gear_id: GearId) { |
|
79 if let Some(index) = self.gear_ids.iter().position(|id| *id == gear_id) { |
|
80 self.gear_ids.swap_remove(index); |
|
81 self.positions.swap_remove(index); |
|
82 } |
|
83 } |
|
84 } |
|
85 |
|
86 pub struct PhysicsProcessor { |
|
87 dynamic_physics: DynamicPhysicsCollection, |
|
88 static_physics: StaticPhysicsCollection, |
|
89 |
|
90 physics_cleanup: Vec<GearId>, |
|
91 position_updates: PositionUpdates, |
|
92 } |
|
93 |
|
94 pub struct PositionUpdates { |
|
95 pub gear_ids: Vec<GearId>, |
|
96 pub shifts: Vec<(FPPoint, FPPoint)>, |
|
97 } |
|
98 |
|
99 impl PositionUpdates { |
|
100 pub fn new(capacity: usize) -> Self { |
|
101 Self { |
|
102 gear_ids: Vec::with_capacity(capacity), |
|
103 shifts: Vec::with_capacity(capacity), |
|
104 } |
|
105 } |
|
106 |
|
107 pub fn push(&mut self, gear_id: GearId, old_position: &FPPoint, new_position: &FPPoint) { |
|
108 self.gear_ids.push(gear_id); |
|
109 self.shifts.push((*old_position, *new_position)); |
|
110 } |
|
111 |
|
112 pub fn iter(&self) -> impl Iterator<Item = (GearId, &FPPoint, &FPPoint)> { |
|
113 self.gear_ids |
|
114 .iter() |
|
115 .cloned() |
|
116 .zip(self.shifts.iter()) |
|
117 .map(|(id, (from, to))| (id, from, to)) |
|
118 } |
|
119 |
|
120 pub fn clear(&mut self) { |
|
121 self.gear_ids.clear(); |
|
122 self.shifts.clear(); |
|
123 } |
|
124 } |
|
125 |
|
126 impl PhysicsProcessor { |
|
127 pub fn new() -> Self { |
|
128 Self { |
|
129 dynamic_physics: DynamicPhysicsCollection::new(), |
|
130 static_physics: StaticPhysicsCollection::new(), |
|
131 physics_cleanup: Vec::new(), |
|
132 position_updates: PositionUpdates::new(0), |
|
133 } |
|
134 } |
|
135 |
|
136 pub fn process(&mut self, time_step: Millis) -> &PositionUpdates { |
|
137 let fp_step = time_step.to_fixed(); |
|
138 self.position_updates.clear(); |
|
139 for (gear_id, (pos, vel)) in self.dynamic_physics.iter_pos_update() { |
|
140 let old_pos = *pos; |
|
141 *pos += *vel * fp_step; |
|
142 if !vel.is_zero() { |
|
143 self.position_updates.push(gear_id, &old_pos, pos) |
|
144 } else { |
|
145 self.physics_cleanup.push(gear_id) |
|
146 } |
|
147 } |
|
148 &self.position_updates |
|
149 } |
|
150 |
|
151 pub fn push(&mut self, gear_id: GearId, physics_data: PhysicsData) { |
|
152 if physics_data.velocity.is_zero() { |
|
153 self.static_physics.push(gear_id, physics_data); |
|
154 } else { |
|
155 self.dynamic_physics.push(gear_id, physics_data); |
|
156 } |
|
157 } |
|
158 } |
|
159 |
|
160 impl GearDataProcessor<PhysicsData> for PhysicsProcessor { |
|
161 fn add(&mut self, gear_id: GearId, gear_data: PhysicsData) { |
|
162 if gear_data.velocity.is_zero() { |
|
163 self.static_physics.push(gear_id, gear_data); |
|
164 } else { |
|
165 self.dynamic_physics.push(gear_id, gear_data); |
|
166 } |
|
167 } |
|
168 |
|
169 fn remove(&mut self, gear_id: GearId) { |
|
170 self.static_physics.remove(gear_id); |
|
171 self.dynamic_physics.remove(gear_id) |
|
172 } |
|
173 } |