rust/hwphysics/src/physics.rs
branchui-scaling
changeset 15288 c4fd2813b127
parent 15280 66c987015f2d
child 15286 8095853811a6
equal deleted inserted replaced
13395:0135e64c6c66 15288:c4fd2813b127
       
     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 }