diff -r 0135e64c6c66 -r c4fd2813b127 rust/hwphysics/src/physics.rs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rust/hwphysics/src/physics.rs Wed Jul 31 23:14:27 2019 +0200 @@ -0,0 +1,173 @@ +use crate::common::{GearData, GearDataProcessor, GearId, Millis}; +use fpnum::*; +use integral_geometry::{GridIndex, Point, Size}; + +#[derive(PartialEq, Eq, Clone, Copy, Debug)] +pub struct PhysicsData { + pub position: FPPoint, + pub velocity: FPPoint, +} + +impl GearData for PhysicsData {} + +impl PhysicsData { + pub fn new(position: FPPoint, velocity: FPPoint) -> Self { + Self { position, velocity } + } +} + +pub struct DynamicPhysicsCollection { + gear_ids: Vec, + positions: Vec, + velocities: Vec, +} + +impl DynamicPhysicsCollection { + fn new() -> Self { + Self { + gear_ids: Vec::new(), + positions: Vec::new(), + velocities: Vec::new(), + } + } + + fn len(&self) -> usize { + self.gear_ids.len() + } + + fn push(&mut self, gear_id: GearId, physics: PhysicsData) { + self.gear_ids.push(gear_id); + self.positions.push(physics.position); + self.velocities.push(physics.velocity); + } + + fn remove(&mut self, gear_id: GearId) { + if let Some(index) = self.gear_ids.iter().position(|id| *id == gear_id) { + self.gear_ids.swap_remove(index); + self.positions.swap_remove(index); + self.velocities.swap_remove(index); + } + } + + fn iter_pos_update(&mut self) -> impl Iterator { + self.gear_ids + .iter() + .cloned() + .zip(self.positions.iter_mut().zip(self.velocities.iter())) + } +} + +pub struct StaticPhysicsCollection { + gear_ids: Vec, + positions: Vec, +} + +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); + } + + fn remove(&mut self, gear_id: GearId) { + if let Some(index) = self.gear_ids.iter().position(|id| *id == gear_id) { + self.gear_ids.swap_remove(index); + self.positions.swap_remove(index); + } + } +} + +pub struct PhysicsProcessor { + dynamic_physics: DynamicPhysicsCollection, + static_physics: StaticPhysicsCollection, + + physics_cleanup: Vec, + position_updates: PositionUpdates, +} + +pub struct PositionUpdates { + pub gear_ids: Vec, + pub shifts: Vec<(FPPoint, FPPoint)>, +} + +impl PositionUpdates { + pub fn new(capacity: usize) -> Self { + Self { + gear_ids: Vec::with_capacity(capacity), + shifts: Vec::with_capacity(capacity), + } + } + + pub fn push(&mut self, gear_id: GearId, old_position: &FPPoint, new_position: &FPPoint) { + self.gear_ids.push(gear_id); + self.shifts.push((*old_position, *new_position)); + } + + pub fn iter(&self) -> impl Iterator { + self.gear_ids + .iter() + .cloned() + .zip(self.shifts.iter()) + .map(|(id, (from, to))| (id, from, to)) + } + + pub fn clear(&mut self) { + self.gear_ids.clear(); + self.shifts.clear(); + } +} + +impl PhysicsProcessor { + pub fn new() -> Self { + Self { + dynamic_physics: DynamicPhysicsCollection::new(), + static_physics: StaticPhysicsCollection::new(), + physics_cleanup: Vec::new(), + position_updates: PositionUpdates::new(0), + } + } + + pub fn process(&mut self, time_step: Millis) -> &PositionUpdates { + let fp_step = time_step.to_fixed(); + self.position_updates.clear(); + for (gear_id, (pos, vel)) in self.dynamic_physics.iter_pos_update() { + let old_pos = *pos; + *pos += *vel * fp_step; + if !vel.is_zero() { + self.position_updates.push(gear_id, &old_pos, pos) + } else { + self.physics_cleanup.push(gear_id) + } + } + &self.position_updates + } + + pub fn push(&mut self, gear_id: GearId, physics_data: PhysicsData) { + if physics_data.velocity.is_zero() { + self.static_physics.push(gear_id, physics_data); + } else { + 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); + } + } + + fn remove(&mut self, gear_id: GearId) { + self.static_physics.remove(gear_id); + self.dynamic_physics.remove(gear_id) + } +}