rust/hwphysics/src/lib.rs
branchui-scaling
changeset 15288 c4fd2813b127
parent 15280 66c987015f2d
child 15286 8095853811a6
equal deleted inserted replaced
13395:0135e64c6c66 15288:c4fd2813b127
       
     1 pub mod collision;
       
     2 pub mod common;
       
     3 mod grid;
       
     4 pub mod physics;
       
     5 pub mod time;
       
     6 
       
     7 use fpnum::FPNum;
       
     8 use integral_geometry::Size;
       
     9 use land2d::Land2D;
       
    10 
       
    11 use crate::{
       
    12     collision::{CollisionData, CollisionProcessor, ContactData},
       
    13     common::{GearAllocator, GearData, GearDataAggregator, GearDataProcessor, GearId, Millis},
       
    14     physics::{PhysicsData, PhysicsProcessor},
       
    15     time::TimeProcessor,
       
    16 };
       
    17 
       
    18 pub struct JoinedData {
       
    19     gear_id: GearId,
       
    20     physics: PhysicsData,
       
    21     collision: CollisionData,
       
    22     contact: ContactData,
       
    23 }
       
    24 
       
    25 pub struct World {
       
    26     allocator: GearAllocator,
       
    27     physics: PhysicsProcessor,
       
    28     collision: CollisionProcessor,
       
    29     time: TimeProcessor,
       
    30 }
       
    31 
       
    32 macro_rules! processor_map {
       
    33     ( $data_type: ident => $field: ident ) => {
       
    34         impl GearDataAggregator<$data_type> for World {
       
    35             fn find_processor(&mut self) -> &mut GearDataProcessor<$data_type> {
       
    36                 &mut self.$field
       
    37             }
       
    38         }
       
    39     };
       
    40 }
       
    41 
       
    42 processor_map!(PhysicsData => physics);
       
    43 processor_map!(CollisionData => collision);
       
    44 
       
    45 impl World {
       
    46     pub fn new(world_size: Size) -> Self {
       
    47         Self {
       
    48             allocator: GearAllocator::new(),
       
    49             physics: PhysicsProcessor::new(),
       
    50             collision: CollisionProcessor::new(world_size),
       
    51             time: TimeProcessor::new(),
       
    52         }
       
    53     }
       
    54 
       
    55     #[inline]
       
    56     pub fn new_gear(&mut self) -> Option<GearId> {
       
    57         self.allocator.alloc()
       
    58     }
       
    59 
       
    60     #[inline]
       
    61     pub fn delete_gear(&mut self, gear_id: GearId) {
       
    62         self.physics.remove(gear_id);
       
    63         self.collision.remove(gear_id);
       
    64         self.time.cancel(gear_id);
       
    65         self.allocator.free(gear_id)
       
    66     }
       
    67 
       
    68     pub fn step(&mut self, time_step: Millis, land: &Land2D<u32>) {
       
    69         let updates = self.physics.process(time_step);
       
    70         let collision = self.collision.process(land, &updates);
       
    71         let events = self.time.process(time_step);
       
    72     }
       
    73 
       
    74     pub fn add_gear_data<T>(&mut self, gear_id: GearId, data: T)
       
    75     where
       
    76         T: GearData,
       
    77         Self: GearDataAggregator<T>,
       
    78     {
       
    79         self.find_processor().add(gear_id, data);
       
    80     }
       
    81 }
       
    82 
       
    83 #[cfg(test)]
       
    84 mod tests {
       
    85     use crate::{
       
    86         collision::{CircleBounds, CollisionData},
       
    87         physics::PhysicsData,
       
    88         World,
       
    89     };
       
    90     use fpnum::{fp, FPNum, FPPoint};
       
    91     use integral_geometry::Size;
       
    92     use land2d::Land2D;
       
    93 
       
    94     #[test]
       
    95     fn data_flow() {
       
    96         let world_size = Size::new(2048, 2048);
       
    97 
       
    98         let mut world = World::new(world_size);
       
    99         let gear_id = 46631;
       
   100 
       
   101         world.add_gear_data(
       
   102             gear_id,
       
   103             PhysicsData {
       
   104                 position: FPPoint::zero(),
       
   105                 velocity: FPPoint::unit_y(),
       
   106             },
       
   107         );
       
   108 
       
   109         world.add_gear_data(
       
   110             gear_id,
       
   111             CollisionData {
       
   112                 bounds: CircleBounds {
       
   113                     center: FPPoint::zero(),
       
   114                     radius: fp!(10),
       
   115                 },
       
   116             },
       
   117         );
       
   118 
       
   119         let land = Land2D::new(Size::new(world_size.width - 2, world_size.height - 2), 0);
       
   120 
       
   121         world.step(fp!(1), &land);
       
   122     }
       
   123 }