diff -r a4dd3d307115 -r a4c17cfaa4c9 rust/hwphysics/src/lib.rs --- a/rust/hwphysics/src/lib.rs Thu Nov 08 22:00:43 2018 +0100 +++ b/rust/hwphysics/src/lib.rs Fri Nov 09 01:05:34 2018 +0300 @@ -1,191 +1,45 @@ -use std::{ - ops::RangeInclusive -}; +mod common; +mod physics; +mod grid; +mod collision; -use fpnum::*; -use integral_geometry::{ - Point, Size, GridIndex -}; +use fpnum::FPNum; use land2d::Land2D; -type Index = u16; - -#[derive(PartialEq, Eq, Clone, Copy, Debug)] -struct PhysicsData { - position: FPPoint, - velocity: FPPoint, -} - -#[derive(PartialEq, Eq, Clone, Copy, Debug)] -struct CollisionData { - bounds: CircleBounds -} - -#[derive(PartialEq, Eq, Clone, Copy, Debug)] -struct ContactData { - elasticity: FPNum, - friction: FPNum -} - -pub struct PhysicsCollection { - positions: Vec, - velocities: Vec -} - -impl PhysicsCollection { - fn push(&mut self, data: PhysicsData) { - self.positions.push(data.position); - self.velocities.push(data.velocity); +use crate::{ + common::GearId, + physics::{ + PhysicsProcessor, + PhysicsData + }, + collision::{ + CollisionProcessor, + CollisionData, + ContactData } - - fn iter_mut_pos(&mut self) -> impl Iterator { - self.positions.iter_mut().zip(self.velocities.iter()) - } -} +}; pub struct JoinedData { + gear_id: GearId, physics: PhysicsData, collision: CollisionData, contact: ContactData } pub struct World { - enabled_physics: PhysicsCollection, - disabled_physics: Vec, - - enabled_collision: Vec, - disabled_collision: Vec, - grid: Grid, - - physics_cleanup: Vec, - collision_output: Vec<(Index, Index)>, - land_collision_output: Vec -} - -#[derive(PartialEq, Eq, Clone, Copy, Debug)] -struct CircleBounds { - center: FPPoint, - radius: FPNum -} - -impl CircleBounds { - pub fn intersects(&self, other: &CircleBounds) -> bool { - (other.center - self.center).is_in_range(self.radius + other.radius) - } - - pub fn rows(&self) -> impl Iterator)> { - let radius = self.radius.abs_round() as usize; - let center = Point::from_fppoint(&self.center); - (center.y as usize - radius..=center.y as usize + radius) - .map(move |row| (row, center.x as usize - radius..=center.x as usize + radius)) - } -} - -fn fppoint_round(point: &FPPoint) -> Point { - Point::new(point.x().round() as i32, point.y().round() as i32) -} - -struct GridBin { - refs: Vec, - static_entries: Vec, - dynamic_entries: Vec -} - -impl GridBin { - fn new() -> Self { - Self { - refs: vec![], - static_entries: vec![], - dynamic_entries: vec![] - } - } -} - -const GRID_BIN_SIZE: usize = 256; - -struct Grid { - bins: Vec, - space_size: Size, - bins_count: Size, - index: GridIndex -} - -impl Grid { - fn new(size: Size) -> Self { - assert!(size.is_power_of_two()); - let bins_count = - Size::new(size.width / GRID_BIN_SIZE, - size.height / GRID_BIN_SIZE); - - Self { - bins: (0..bins_count.area()).map(|_| GridBin::new()).collect(), - space_size: size, - bins_count, - index: Size::square(GRID_BIN_SIZE).to_grid_index() - } - } - - fn bin_index(&self, position: &FPPoint) -> Point { - self.index.map(fppoint_round(position)) - } - - fn lookup_bin(&mut self, position: &FPPoint) -> &mut GridBin { - let index = self.bin_index(position); - &mut self.bins[index.x as usize * self.bins_count.width + index.y as usize] - } - - fn insert_static(&mut self, index: Index, position: &FPPoint, bounds: &CircleBounds) { - self.lookup_bin(position).static_entries.push(*bounds) - } - - fn insert_dynamic(&mut self, index: Index, position: &FPPoint, bounds: &CircleBounds) { - self.lookup_bin(position).dynamic_entries.push(*bounds) - } - - fn check_collisions(&self, collisions: &mut Vec<(Index, Index)>) { - for bin in &self.bins { - for bounds in &bin.dynamic_entries { - for other in &bin.dynamic_entries { - if bounds.intersects(other) && bounds != other { - collisions.push((0, 0)) - } - } - - for other in &bin.static_entries { - if bounds.intersects(other) { - collisions.push((0, 0)) - } - } - } - } - } + physics: PhysicsProcessor, + collision: CollisionProcessor, } impl World { pub fn step(&mut self, time_step: FPNum, land: &Land2D) { - for (pos, vel) in self.enabled_physics.iter_mut_pos() { - *pos += *vel - } - - self.grid.check_collisions(&mut self.collision_output); - } - - fn check_land_collisions(&mut self, land: &Land2D) { - for collision in &self.enabled_collision { - if collision.bounds.rows().any(|(y, r)| (&land[y][r]).iter().any(|v| *v != 0)) { - self.land_collision_output.push(0) - } - } + let updates = self.physics.process(time_step); + self.collision.process(land, &updates); } pub fn add_gear(&mut self, data: JoinedData) { - if data.physics.velocity == FPPoint::zero() { - self.disabled_physics.push(data.physics); - self.grid.insert_static(0, &data.physics.position, &data.collision.bounds); - } else { - self.enabled_physics.push(data.physics); - self.grid.insert_dynamic(0, &data.physics.position, &data.collision.bounds); - } + self.physics.push(data.gear_id, data.physics); + self.collision.push(data.gear_id, data.physics, data.collision); } }