# HG changeset patch # User alfadur # Date 1541723781 -10800 # Node ID abbb74b9cb6236197afa232d21ccbdb8ff025430 # Parent a4c17cfaa4c966baf0c0dcd749f791c916021a4f generalize adding data to World diff -r a4c17cfaa4c9 -r abbb74b9cb62 rust/hwphysics/src/collision.rs --- a/rust/hwphysics/src/collision.rs Fri Nov 09 01:05:34 2018 +0300 +++ b/rust/hwphysics/src/collision.rs Fri Nov 09 03:36:21 2018 +0300 @@ -3,7 +3,7 @@ }; use crate::{ - common::GearId, + common::{GearId, GearData, GearDataProcessor}, physics::PhysicsData, grid::Grid }; @@ -42,18 +42,29 @@ pub bounds: CircleBounds } +impl GearData for CollisionData {} + #[derive(PartialEq, Eq, Clone, Copy, Debug)] pub struct ContactData { pub elasticity: FPNum, pub friction: FPNum } +impl GearData for ContactData {} + struct EnabledCollisionsCollection { gear_ids: Vec, collisions: Vec } impl EnabledCollisionsCollection { + fn new() -> Self { + Self { + gear_ids: Vec::new(), + collisions: Vec::new() + } + } + fn push(&mut self, gear_id: GearId, collision: CollisionData) { self.gear_ids.push(gear_id); self.collisions.push(collision); @@ -86,26 +97,32 @@ pub fn push(&mut self, contact_gear_id1: GearId, contact_gear_id2: GearId, position: &FPPoint) { self.pairs.push((contact_gear_id1, contact_gear_id2)); - self.positions.push(fppoint_round(position)); + self.positions.push(fppoint_round(&position)); } } impl CollisionProcessor { - pub fn process(&mut self, land: &Land2D, updates: &crate::physics::PositionUpdate) { + pub fn new(size: Size) -> Self { + Self { + grid: Grid::new(size), + enabled_collisions: EnabledCollisionsCollection::new(), + detected_collisions: DetectedCollisions::new(0) + } + } + + pub fn process(&mut self, land: &Land2D, updates: &crate::physics::PositionUpdates) { self.grid.check_collisions(&mut self.detected_collisions); for (gear_id, collision) in self.enabled_collisions.iter() { if collision.bounds.rows().any(|(y, r)| (&land[y][r]).iter().any(|v| *v != 0)) { - self.detected_collisions.push(0, 0, &collision.bounds.center) + self.detected_collisions.push(gear_id, 0, &collision.bounds.center) } } } +} - pub fn push(&mut self, gear_id: GearId, physics_data: PhysicsData, collision_data: CollisionData) { - if physics_data.velocity.is_zero() { - self.grid.insert_static(0, &physics_data.position, &collision_data.bounds); - } else { - self.grid.insert_dynamic(0, &physics_data.position, &collision_data.bounds); - } +impl GearDataProcessor for CollisionProcessor { + fn add(&mut self, gear_id: GearId, gear_data: CollisionData) { + self.grid.insert_static(gear_id, &gear_data.bounds); } } \ No newline at end of file diff -r a4c17cfaa4c9 -r abbb74b9cb62 rust/hwphysics/src/common.rs --- a/rust/hwphysics/src/common.rs Fri Nov 09 01:05:34 2018 +0300 +++ b/rust/hwphysics/src/common.rs Fri Nov 09 03:36:21 2018 +0300 @@ -1,1 +1,10 @@ -pub type GearId = u16; \ No newline at end of file +pub type GearId = u16; +pub trait GearData {} + +pub trait GearDataProcessor { + fn add(&mut self, gear_id: GearId, gear_data: T); +} + +pub trait GearDataAggregator { + fn find_processor(&mut self) -> &mut GearDataProcessor; +} diff -r a4c17cfaa4c9 -r abbb74b9cb62 rust/hwphysics/src/grid.rs --- a/rust/hwphysics/src/grid.rs Fri Nov 09 01:05:34 2018 +0300 +++ b/rust/hwphysics/src/grid.rs Fri Nov 09 03:36:21 2018 +0300 @@ -30,7 +30,7 @@ } } -const GRID_BIN_SIZE: usize = 256; +const GRID_BIN_SIZE: usize = 128; pub struct Grid { bins: Vec, @@ -63,12 +63,12 @@ &mut self.bins[index.x as usize * self.bins_count.width + index.y as usize] } - pub fn insert_static(&mut self, gear_id: GearId, position: &FPPoint, bounds: &CircleBounds) { - self.lookup_bin(position).static_entries.push(*bounds) + pub fn insert_static(&mut self, gear_id: GearId, bounds: &CircleBounds) { + self.lookup_bin(&bounds.center).static_entries.push(*bounds) } - pub fn insert_dynamic(&mut self, gear_id: GearId, position: &FPPoint, bounds: &CircleBounds) { - self.lookup_bin(position).dynamic_entries.push(*bounds) + pub fn insert_dynamic(&mut self, gear_id: GearId, bounds: &CircleBounds) { + self.lookup_bin(&bounds.center).dynamic_entries.push(*bounds) } pub fn check_collisions(&self, collisions: &mut DetectedCollisions) { diff -r a4c17cfaa4c9 -r abbb74b9cb62 rust/hwphysics/src/lib.rs --- a/rust/hwphysics/src/lib.rs Fri Nov 09 01:05:34 2018 +0300 +++ b/rust/hwphysics/src/lib.rs Fri Nov 09 03:36:21 2018 +0300 @@ -4,10 +4,16 @@ mod collision; use fpnum::FPNum; +use integral_geometry::Size; use land2d::Land2D; use crate::{ - common::GearId, + common::{ + GearId, + GearData, + GearDataAggregator, + GearDataProcessor + }, physics::{ PhysicsProcessor, PhysicsData @@ -31,19 +37,72 @@ collision: CollisionProcessor, } +macro_rules! processor_map { + ( $data_type: ident => $field: ident ) => { + impl GearDataAggregator<$data_type> for World { + fn find_processor(&mut self) -> &mut GearDataProcessor<$data_type> { + &mut self.$field + } + } + } +} + +processor_map!(PhysicsData => physics); +processor_map!(CollisionData => collision); + impl World { + pub fn new(world_size: Size) -> Self { + Self { + physics: PhysicsProcessor::new(), + collision: CollisionProcessor::new(world_size) + } + } + pub fn step(&mut self, time_step: FPNum, land: &Land2D) { let updates = self.physics.process(time_step); self.collision.process(land, &updates); } - pub fn add_gear(&mut self, data: JoinedData) { - self.physics.push(data.gear_id, data.physics); - self.collision.push(data.gear_id, data.physics, data.collision); + pub fn add_gear_data(&mut self, gear_id: GearId, data: T) + where T: GearData, + Self: GearDataAggregator + { + self.find_processor().add(gear_id, data); } } #[cfg(test)] mod tests { + use crate::{ + World, + physics::PhysicsData, + collision::{CollisionData, CircleBounds} + }; + use fpnum::{FPNum, FPPoint, fp}; + use integral_geometry::Size; + use land2d::Land2D; + #[test] + fn data_flow() { + let world_size = Size::new(2048, 2048); + + let mut world = World::new(world_size); + let gear_id = 46631; + + world.add_gear_data(gear_id, PhysicsData { + position: FPPoint::zero(), + velocity: FPPoint::unit_y() + }); + + world.add_gear_data(gear_id, CollisionData { + bounds: CircleBounds { + center: FPPoint::zero(), + radius: fp!(10) + } + }); + + let land = Land2D::new(Size::new(world_size.width - 2, world_size.height - 2), 0); + + world.step(fp!(1), &land); + } } diff -r a4c17cfaa4c9 -r abbb74b9cb62 rust/hwphysics/src/physics.rs --- a/rust/hwphysics/src/physics.rs Fri Nov 09 01:05:34 2018 +0300 +++ b/rust/hwphysics/src/physics.rs Fri Nov 09 03:36:21 2018 +0300 @@ -1,5 +1,5 @@ use crate::{ - common::GearId + common::{GearId, GearData, GearDataProcessor} }; use fpnum::*; use integral_geometry::{ @@ -12,6 +12,7 @@ pub velocity: FPPoint, } +impl GearData for PhysicsData {} pub struct DynamicPhysicsCollection { gear_ids: Vec, @@ -20,6 +21,14 @@ } impl DynamicPhysicsCollection { + fn new() -> Self { + Self { + gear_ids: Vec::new(), + positions: Vec::new(), + velocities: Vec::new() + } + } + fn len(&self) -> usize { self.gear_ids.len() } @@ -43,6 +52,13 @@ } impl StaticPhysicsCollection { + fn new() -> Self { + Self { + gear_ids: Vec::new(), + positions: Vec::new() + } + } + fn push(&mut self, gear_id: GearId, physics: PhysicsData) { self.gear_ids.push(gear_id); self.positions.push(physics.position); @@ -54,15 +70,15 @@ static_physics: StaticPhysicsCollection, physics_cleanup: Vec, - position_updates: PositionUpdate + position_updates: PositionUpdates } -pub struct PositionUpdate { +pub struct PositionUpdates { pub gear_ids: Vec, pub positions: Vec } -impl PositionUpdate { +impl PositionUpdates { pub fn new(capacity: usize) -> Self { Self { gear_ids: Vec::with_capacity(capacity), @@ -77,7 +93,16 @@ } impl PhysicsProcessor { - pub fn process(&mut self, time_step: FPNum) -> &PositionUpdate { + pub fn new() -> Self { + PhysicsProcessor { + dynamic_physics: DynamicPhysicsCollection::new(), + static_physics: StaticPhysicsCollection::new(), + physics_cleanup: Vec::new(), + position_updates: PositionUpdates::new(0) + } + } + + pub fn process(&mut self, time_step: FPNum) -> &PositionUpdates { for (gear_id, (pos, vel)) in self.dynamic_physics.iter_pos_update() { *pos += *vel * time_step; if !vel.is_zero() { @@ -96,4 +121,14 @@ self.dynamic_physics.push(gear_id, physics_data); } } +} + +impl GearDataProcessor for PhysicsProcessor { + fn add(&mut self, gear_id: GearId, gear_data: PhysicsData) { + if gear_data.velocity.is_zero() { + self.static_physics.push(gear_id, gear_data); + } else { + self.dynamic_physics.push(gear_id, gear_data); + } + } } \ No newline at end of file