rust/hwphysics/src/physics.rs
changeset 15380 6e3e5be8b2e2
parent 15282 478d5372eb4a
child 15381 52844baced17
equal deleted inserted replaced
15379:27915135f87f 15380:6e3e5be8b2e2
     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 }