# HG changeset patch # User alfadur # Date 1567022794 -10800 # Node ID 6e3e5be8b2e21e5c8f8041596a9cb7f6ccb2bc84 # Parent 27915135f87fcfbe54680a13939d8eb712d47877 update hwphysics motion to use the new system diff -r 27915135f87f -r 6e3e5be8b2e2 rust/hwphysics/src/collision.rs --- a/rust/hwphysics/src/collision.rs Wed Aug 28 22:53:40 2019 +0300 +++ b/rust/hwphysics/src/collision.rs Wed Aug 28 23:06:34 2019 +0300 @@ -1,9 +1,6 @@ use std::ops::RangeInclusive; -use crate::{ - common::{GearData, GearDataProcessor, GearId}, - grid::Grid, -}; +use crate::{common::GearId, data::GearDataManager, grid::Grid}; use fpnum::*; use integral_geometry::{Point, Size}; @@ -37,16 +34,12 @@ 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, @@ -107,6 +100,11 @@ } impl CollisionProcessor { + pub fn register_components(data: &mut GearDataManager) { + data.register::(); + data.register::(); + } + pub fn new(size: Size) -> Self { Self { grid: Grid::new(size), @@ -115,6 +113,18 @@ } } + pub fn add(&mut self, gear_id: GearId, gear_data: CollisionData) { + self.grid.insert_static(gear_id, &gear_data.bounds); + } + + pub fn remove(&mut self, gear_id: GearId) { + self.grid.remove(gear_id); + } + + pub fn get(&mut self, gear_id: GearId) -> Option { + None + } + pub fn process( &mut self, land: &Land2D, @@ -141,17 +151,3 @@ &self.detected_collisions } } - -impl GearDataProcessor for CollisionProcessor { - fn add(&mut self, gear_id: GearId, gear_data: CollisionData) { - self.grid.insert_static(gear_id, &gear_data.bounds); - } - - fn remove(&mut self, gear_id: GearId) { - self.grid.remove(gear_id); - } - - fn get(&mut self, gear_id: GearId) -> Option { - None - } -} diff -r 27915135f87f -r 6e3e5be8b2e2 rust/hwphysics/src/common.rs --- a/rust/hwphysics/src/common.rs Wed Aug 28 22:53:40 2019 +0300 +++ b/rust/hwphysics/src/common.rs Wed Aug 28 23:06:34 2019 +0300 @@ -6,7 +6,6 @@ }; pub type GearId = NonZeroU16; -pub trait GearData {} #[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Debug)] #[repr(transparent)] @@ -37,16 +36,6 @@ } } -pub trait GearDataProcessor { - fn add(&mut self, gear_id: GearId, gear_data: T); - fn remove(&mut self, gear_id: GearId); - fn get(&mut self, gear_id: GearId) -> Option; -} - -pub trait GearDataAggregator { - fn find_processor(&mut self) -> &mut GearDataProcessor; -} - pub struct GearAllocator { max_id: u16, free_ids: BinaryHeap, @@ -73,91 +62,3 @@ self.free_ids.push(gear_id) } } - -#[derive(Clone, Copy, Default)] -pub struct LookupEntry { - index: Option, - value: T, -} - -impl LookupEntry { - #[inline] - pub fn index(&self) -> u16 { - self.index.map(|i| i.get()).unwrap_or(0) - 1 - } - - #[inline] - pub fn set_index(&mut self, index: u16) { - self.index = unsafe { Some(NonZeroU16::new_unchecked(index.saturating_add(1))) }; - } - - #[inline] - pub fn value(&self) -> &T { - &self.value - } - - #[inline] - pub fn value_mut(&mut self) -> &mut T { - &mut self.value - } - - #[inline] - pub fn set_value(&mut self, value: T) { - self.value = value; - } -} - -pub struct GearDataLookup { - lookup: Box<[LookupEntry]>, -} - -impl GearDataLookup { - pub fn new() -> Self { - Self { - lookup: vec![LookupEntry::default(); u16::max_value() as usize].into_boxed_slice(), - } - } -} - -impl GearDataLookup { - pub fn add(&mut self, gear_id: GearId, index: u16, value: T) { - // All possible Gear IDs are valid indices - let entry = unsafe { self.lookup.get_unchecked_mut(gear_id.get() as usize - 1) }; - entry.set_index(index); - entry.set_value(value); - } - - pub fn get(&self, gear_id: GearId) -> Option<&LookupEntry> { - // All possible Gear IDs are valid indices - let entry = unsafe { self.lookup.get_unchecked(gear_id.get() as usize - 1) }; - if let Some(index) = entry.index { - Some(entry) - } else { - None - } - } - - pub fn get_mut(&mut self, gear_id: GearId) -> Option<&mut LookupEntry> { - // All possible Gear IDs are valid indices - let entry = unsafe { self.lookup.get_unchecked_mut(gear_id.get() as usize - 1) }; - if let Some(index) = entry.index { - Some(entry) - } else { - None - } - } -} - -impl Index for GearDataLookup { - type Output = LookupEntry; - - fn index(&self, index: GearId) -> &Self::Output { - self.get(index).unwrap() - } -} - -impl IndexMut for GearDataLookup { - fn index_mut(&mut self, index: GearId) -> &mut Self::Output { - self.get_mut(index).unwrap() - } -} diff -r 27915135f87f -r 6e3e5be8b2e2 rust/hwphysics/src/data.rs --- a/rust/hwphysics/src/data.rs Wed Aug 28 22:53:40 2019 +0300 +++ b/rust/hwphysics/src/data.rs Wed Aug 28 23:06:34 2019 +0300 @@ -23,10 +23,8 @@ unsafe fn iter(slices: &[*mut u8], count: usize, mut f: F) { for i in 0..count { - unsafe { - f(*(*slices.get_unchecked(0) as *const GearId).add(i), - ($(&*(*slices.get_unchecked($n + 1) as *mut $t).add(i)),+,)); - } + f(*(*slices.get_unchecked(0) as *const GearId).add(i), + ($(&*(*slices.get_unchecked($n + 1) as *mut $t).add(i)),+,)); } } } @@ -38,10 +36,8 @@ unsafe fn iter(slices: &[*mut u8], count: usize, mut f: F) { for i in 0..count { - unsafe { - f(*(*slices.get_unchecked(0) as *const GearId).add(i), - ($(&mut *(*slices.get_unchecked($n + 1) as *mut $t).add(i)),+,)); - } + f(*(*slices.get_unchecked(0) as *const GearId).add(i), + ($(&mut *(*slices.get_unchecked($n + 1) as *mut $t).add(i)),+,)); } } } @@ -382,7 +378,6 @@ } } - pub fn iter(&mut self, mut f: F) { self.iter_id(|_, x| f(x)); } diff -r 27915135f87f -r 6e3e5be8b2e2 rust/hwphysics/src/lib.rs --- a/rust/hwphysics/src/lib.rs Wed Aug 28 22:53:40 2019 +0300 +++ b/rust/hwphysics/src/lib.rs Wed Aug 28 23:06:34 2019 +0300 @@ -10,41 +10,28 @@ use crate::{ collision::{CollisionData, CollisionProcessor, ContactData}, - common::{GearAllocator, GearData, GearDataAggregator, GearDataProcessor, GearId, Millis}, - physics::{PhysicsData, PhysicsProcessor}, + common::{GearAllocator, GearId, Millis}, + data::GearDataManager, + physics::PhysicsProcessor, time::TimeProcessor, }; -pub struct JoinedData { - gear_id: GearId, - physics: PhysicsData, - collision: CollisionData, - contact: ContactData, -} - pub struct World { allocator: GearAllocator, + data: GearDataManager, physics: PhysicsProcessor, collision: CollisionProcessor, time: TimeProcessor, } -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 { + let mut data = GearDataManager::new(); + PhysicsProcessor::register_components(&mut data); + CollisionProcessor::register_components(&mut data); + Self { + data, allocator: GearAllocator::new(), physics: PhysicsProcessor::new(), collision: CollisionProcessor::new(world_size), @@ -59,24 +46,21 @@ #[inline] pub fn delete_gear(&mut self, gear_id: GearId) { - self.physics.remove(gear_id); + self.data.remove_all(gear_id); self.collision.remove(gear_id); self.time.cancel(gear_id); self.allocator.free(gear_id) } pub fn step(&mut self, time_step: Millis, land: &Land2D) { - let updates = self.physics.process(time_step); - let collision = self.collision.process(land, &updates); + let updates = self.physics.process(&mut self.data, time_step); + let collisions = self.collision.process(land, &updates); let events = self.time.process(time_step); } - pub fn add_gear_data(&mut self, gear_id: GearId, data: T) - where - T: GearData, - Self: GearDataAggregator, - { - self.find_processor().add(gear_id, data); + #[inline] + pub fn add_gear_data(&mut self, gear_id: GearId, data: &T) { + self.data.add(gear_id, data); } } @@ -85,7 +69,7 @@ use crate::{ collision::{CircleBounds, CollisionData}, common::Millis, - physics::PhysicsData, + physics::{PositionData, VelocityData}, World, }; use fpnum::{fp, FPNum, FPPoint}; @@ -97,19 +81,14 @@ let world_size = Size::new(2048, 2048); let mut world = World::new(world_size); - let gear_id = std::num::NonZeroU16::new(46631).unwrap(); + let gear_id = world.new_gear().unwrap(); + + world.add_gear_data(gear_id, &PositionData(FPPoint::zero())); + world.add_gear_data(gear_id, &VelocityData(FPPoint::unit_y())); world.add_gear_data( gear_id, - PhysicsData { - position: FPPoint::zero(), - velocity: FPPoint::unit_y(), - }, - ); - - world.add_gear_data( - gear_id, - CollisionData { + &CollisionData { bounds: CircleBounds { center: FPPoint::zero(), radius: fp!(10), diff -r 27915135f87f -r 6e3e5be8b2e2 rust/hwphysics/src/physics.rs --- a/rust/hwphysics/src/physics.rs Wed Aug 28 22:53:40 2019 +0300 +++ b/rust/hwphysics/src/physics.rs Wed Aug 28 23:06:34 2019 +0300 @@ -1,97 +1,18 @@ -use crate::common::{GearData, GearDataLookup, GearDataProcessor, GearId, Millis}; +use crate::{ + common::{GearId, Millis}, + data::GearDataManager, +}; use fpnum::*; #[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) -> u16 { - self.gear_ids.push(gear_id); - self.positions.push(physics.position); - self.velocities.push(physics.velocity); - - (self.gear_ids.len() - 1) as u16 - } +#[repr(transparent)] +pub struct PositionData(pub FPPoint); - fn remove(&mut self, index: usize) -> Option { - self.gear_ids.swap_remove(index); - self.positions.swap_remove(index); - self.velocities.swap_remove(index); - - self.gear_ids.get(index).cloned() - } - - 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) -> u16 { - self.gear_ids.push(gear_id); - self.positions.push(physics.position); - - (self.gear_ids.len() - 1) as u16 - } - - fn remove(&mut self, index: usize) -> Option { - self.gear_ids.swap_remove(index); - self.positions.swap_remove(index); - - self.gear_ids.get(index).cloned() - } -} +#[derive(PartialEq, Eq, Clone, Copy, Debug)] +#[repr(transparent)] +pub struct VelocityData(pub FPPoint); pub struct PhysicsProcessor { - gear_lookup: GearDataLookup, - dynamic_physics: DynamicPhysicsCollection, - static_physics: StaticPhysicsCollection, - - physics_cleanup: Vec, position_updates: PositionUpdates, } @@ -128,75 +49,31 @@ } impl PhysicsProcessor { + pub fn register_components(data: &mut GearDataManager) { + data.register::(); + data.register::(); + } + pub fn new() -> Self { Self { - gear_lookup: GearDataLookup::new(), - dynamic_physics: DynamicPhysicsCollection::new(), - static_physics: StaticPhysicsCollection::new(), - physics_cleanup: Vec::new(), - position_updates: PositionUpdates::new(0), + position_updates: PositionUpdates::new(64), } } - pub fn process(&mut self, time_step: Millis) -> &PositionUpdates { + pub fn process(&mut self, data: &mut GearDataManager, 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) - } - } + + data.iter_id( + |gear_id, (pos, vel): (&mut PositionData, &mut VelocityData)| { + if !vel.0.is_zero() { + let old_pos = pos.0; + pos.0 += vel.0 * fp_step; + self.position_updates.push(gear_id, &old_pos, &pos.0) + } + }, + ); + &self.position_updates } } - -impl GearDataProcessor for PhysicsProcessor { - fn add(&mut self, gear_id: GearId, gear_data: PhysicsData) { - let is_dynamic = !gear_data.velocity.is_zero(); - let index = if is_dynamic { - self.dynamic_physics.push(gear_id, gear_data) - } else { - self.static_physics.push(gear_id, gear_data) - }; - - self.gear_lookup.add(gear_id, index, is_dynamic); - } - - fn remove(&mut self, gear_id: GearId) { - if let Some(entry) = self.gear_lookup.get(gear_id) { - let relocated_gear_id = if *entry.value() { - self.dynamic_physics.remove(entry.index() as usize) - } else { - self.static_physics.remove(entry.index() as usize) - }; - - if let Some(id) = relocated_gear_id { - let index = entry.index(); - self.gear_lookup[id].set_index(index); - } - } - } - - fn get(&mut self, gear_id: GearId) -> Option { - if let Some(entry) = self.gear_lookup.get(gear_id) { - let data = if *entry.value() { - PhysicsData { - position: self.dynamic_physics.positions[entry.index() as usize], - velocity: self.dynamic_physics.velocities[entry.index() as usize], - } - } else { - PhysicsData { - position: self.static_physics.positions[entry.index() as usize], - velocity: FPPoint::zero(), - } - }; - Some(data) - } else { - None - } - } -}