1 use crate::common::{GearData, GearDataLookup, GearDataProcessor, GearId, Millis}; |
1 use crate::{ |
|
2 common::{GearId, Millis}, |
|
3 data::GearDataManager, |
|
4 }; |
2 use fpnum::*; |
5 use fpnum::*; |
3 |
6 |
4 #[derive(PartialEq, Eq, Clone, Copy, Debug)] |
7 #[derive(PartialEq, Eq, Clone, Copy, Debug)] |
5 pub struct PhysicsData { |
8 #[repr(transparent)] |
6 pub position: FPPoint, |
9 pub struct PositionData(pub FPPoint); |
7 pub velocity: FPPoint, |
|
8 } |
|
9 |
10 |
10 impl GearData for PhysicsData {} |
11 #[derive(PartialEq, Eq, Clone, Copy, Debug)] |
11 |
12 #[repr(transparent)] |
12 impl PhysicsData { |
13 pub struct VelocityData(pub FPPoint); |
13 pub fn new(position: FPPoint, velocity: FPPoint) -> Self { |
|
14 Self { position, velocity } |
|
15 } |
|
16 } |
|
17 |
|
18 pub struct DynamicPhysicsCollection { |
|
19 gear_ids: Vec<GearId>, |
|
20 positions: Vec<FPPoint>, |
|
21 velocities: Vec<FPPoint>, |
|
22 } |
|
23 |
|
24 impl DynamicPhysicsCollection { |
|
25 fn new() -> Self { |
|
26 Self { |
|
27 gear_ids: Vec::new(), |
|
28 positions: Vec::new(), |
|
29 velocities: Vec::new(), |
|
30 } |
|
31 } |
|
32 |
|
33 fn len(&self) -> usize { |
|
34 self.gear_ids.len() |
|
35 } |
|
36 |
|
37 fn push(&mut self, gear_id: GearId, physics: PhysicsData) -> u16 { |
|
38 self.gear_ids.push(gear_id); |
|
39 self.positions.push(physics.position); |
|
40 self.velocities.push(physics.velocity); |
|
41 |
|
42 (self.gear_ids.len() - 1) as u16 |
|
43 } |
|
44 |
|
45 fn remove(&mut self, index: usize) -> Option<GearId> { |
|
46 self.gear_ids.swap_remove(index); |
|
47 self.positions.swap_remove(index); |
|
48 self.velocities.swap_remove(index); |
|
49 |
|
50 self.gear_ids.get(index).cloned() |
|
51 } |
|
52 |
|
53 fn iter_pos_update(&mut self) -> impl Iterator<Item = (GearId, (&mut FPPoint, &FPPoint))> { |
|
54 self.gear_ids |
|
55 .iter() |
|
56 .cloned() |
|
57 .zip(self.positions.iter_mut().zip(self.velocities.iter())) |
|
58 } |
|
59 } |
|
60 |
|
61 pub struct StaticPhysicsCollection { |
|
62 gear_ids: Vec<GearId>, |
|
63 positions: Vec<FPPoint>, |
|
64 } |
|
65 |
|
66 impl StaticPhysicsCollection { |
|
67 fn new() -> Self { |
|
68 Self { |
|
69 gear_ids: Vec::new(), |
|
70 positions: Vec::new(), |
|
71 } |
|
72 } |
|
73 |
|
74 fn push(&mut self, gear_id: GearId, physics: PhysicsData) -> u16 { |
|
75 self.gear_ids.push(gear_id); |
|
76 self.positions.push(physics.position); |
|
77 |
|
78 (self.gear_ids.len() - 1) as u16 |
|
79 } |
|
80 |
|
81 fn remove(&mut self, index: usize) -> Option<GearId> { |
|
82 self.gear_ids.swap_remove(index); |
|
83 self.positions.swap_remove(index); |
|
84 |
|
85 self.gear_ids.get(index).cloned() |
|
86 } |
|
87 } |
|
88 |
14 |
89 pub struct PhysicsProcessor { |
15 pub struct PhysicsProcessor { |
90 gear_lookup: GearDataLookup<bool>, |
|
91 dynamic_physics: DynamicPhysicsCollection, |
|
92 static_physics: StaticPhysicsCollection, |
|
93 |
|
94 physics_cleanup: Vec<GearId>, |
|
95 position_updates: PositionUpdates, |
16 position_updates: PositionUpdates, |
96 } |
17 } |
97 |
18 |
98 pub struct PositionUpdates { |
19 pub struct PositionUpdates { |
99 pub gear_ids: Vec<GearId>, |
20 pub gear_ids: Vec<GearId>, |
126 self.shifts.clear(); |
47 self.shifts.clear(); |
127 } |
48 } |
128 } |
49 } |
129 |
50 |
130 impl PhysicsProcessor { |
51 impl PhysicsProcessor { |
|
52 pub fn register_components(data: &mut GearDataManager) { |
|
53 data.register::<PositionData>(); |
|
54 data.register::<VelocityData>(); |
|
55 } |
|
56 |
131 pub fn new() -> Self { |
57 pub fn new() -> Self { |
132 Self { |
58 Self { |
133 gear_lookup: GearDataLookup::new(), |
59 position_updates: PositionUpdates::new(64), |
134 dynamic_physics: DynamicPhysicsCollection::new(), |
|
135 static_physics: StaticPhysicsCollection::new(), |
|
136 physics_cleanup: Vec::new(), |
|
137 position_updates: PositionUpdates::new(0), |
|
138 } |
60 } |
139 } |
61 } |
140 |
62 |
141 pub fn process(&mut self, time_step: Millis) -> &PositionUpdates { |
63 pub fn process(&mut self, data: &mut GearDataManager, time_step: Millis) -> &PositionUpdates { |
142 let fp_step = time_step.to_fixed(); |
64 let fp_step = time_step.to_fixed(); |
143 self.position_updates.clear(); |
65 self.position_updates.clear(); |
144 for (gear_id, (pos, vel)) in self.dynamic_physics.iter_pos_update() { |
66 |
145 let old_pos = *pos; |
67 data.iter_id( |
146 *pos += *vel * fp_step; |
68 |gear_id, (pos, vel): (&mut PositionData, &mut VelocityData)| { |
147 if !vel.is_zero() { |
69 if !vel.0.is_zero() { |
148 self.position_updates.push(gear_id, &old_pos, pos) |
70 let old_pos = pos.0; |
149 } else { |
71 pos.0 += vel.0 * fp_step; |
150 self.physics_cleanup.push(gear_id) |
72 self.position_updates.push(gear_id, &old_pos, &pos.0) |
151 } |
73 } |
152 } |
74 }, |
|
75 ); |
|
76 |
153 &self.position_updates |
77 &self.position_updates |
154 } |
78 } |
155 } |
79 } |
156 |
|
157 impl GearDataProcessor<PhysicsData> for PhysicsProcessor { |
|
158 fn add(&mut self, gear_id: GearId, gear_data: PhysicsData) { |
|
159 let is_dynamic = !gear_data.velocity.is_zero(); |
|
160 let index = if is_dynamic { |
|
161 self.dynamic_physics.push(gear_id, gear_data) |
|
162 } else { |
|
163 self.static_physics.push(gear_id, gear_data) |
|
164 }; |
|
165 |
|
166 self.gear_lookup.add(gear_id, index, is_dynamic); |
|
167 } |
|
168 |
|
169 fn remove(&mut self, gear_id: GearId) { |
|
170 if let Some(entry) = self.gear_lookup.get(gear_id) { |
|
171 let relocated_gear_id = if *entry.value() { |
|
172 self.dynamic_physics.remove(entry.index() as usize) |
|
173 } else { |
|
174 self.static_physics.remove(entry.index() as usize) |
|
175 }; |
|
176 |
|
177 if let Some(id) = relocated_gear_id { |
|
178 let index = entry.index(); |
|
179 self.gear_lookup[id].set_index(index); |
|
180 } |
|
181 } |
|
182 } |
|
183 |
|
184 fn get(&mut self, gear_id: GearId) -> Option<PhysicsData> { |
|
185 if let Some(entry) = self.gear_lookup.get(gear_id) { |
|
186 let data = if *entry.value() { |
|
187 PhysicsData { |
|
188 position: self.dynamic_physics.positions[entry.index() as usize], |
|
189 velocity: self.dynamic_physics.velocities[entry.index() as usize], |
|
190 } |
|
191 } else { |
|
192 PhysicsData { |
|
193 position: self.static_physics.positions[entry.index() as usize], |
|
194 velocity: FPPoint::zero(), |
|
195 } |
|
196 }; |
|
197 Some(data) |
|
198 } else { |
|
199 None |
|
200 } |
|
201 } |
|
202 } |
|