--- 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<GearId>,
collisions: Vec<CollisionData>,
@@ -107,6 +100,11 @@
}
impl CollisionProcessor {
+ pub fn register_components(data: &mut GearDataManager) {
+ data.register::<CollisionData>();
+ data.register::<ContactData>();
+ }
+
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<CollisionData> {
+ None
+ }
+
pub fn process(
&mut self,
land: &Land2D<u32>,
@@ -141,17 +151,3 @@
&self.detected_collisions
}
}
-
-impl GearDataProcessor<CollisionData> 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<CollisionData> {
- None
- }
-}
--- 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<T: GearData> {
- 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<T>;
-}
-
-pub trait GearDataAggregator<T: GearData> {
- fn find_processor(&mut self) -> &mut GearDataProcessor<T>;
-}
-
pub struct GearAllocator {
max_id: u16,
free_ids: BinaryHeap<GearId>,
@@ -73,91 +62,3 @@
self.free_ids.push(gear_id)
}
}
-
-#[derive(Clone, Copy, Default)]
-pub struct LookupEntry<T> {
- index: Option<NonZeroU16>,
- value: T,
-}
-
-impl<T> LookupEntry<T> {
- #[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<T> {
- lookup: Box<[LookupEntry<T>]>,
-}
-
-impl<T: Default + Copy> GearDataLookup<T> {
- pub fn new() -> Self {
- Self {
- lookup: vec![LookupEntry::default(); u16::max_value() as usize].into_boxed_slice(),
- }
- }
-}
-
-impl<T> GearDataLookup<T> {
- 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<T>> {
- // 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<T>> {
- // 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<T> Index<GearId> for GearDataLookup<T> {
- type Output = LookupEntry<T>;
-
- fn index(&self, index: GearId) -> &Self::Output {
- self.get(index).unwrap()
- }
-}
-
-impl<T> IndexMut<GearId> for GearDataLookup<T> {
- fn index_mut(&mut self, index: GearId) -> &mut Self::Output {
- self.get_mut(index).unwrap()
- }
-}
--- 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<F: FnMut(GearId, Self)>(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<F: FnMut(GearId, Self)>(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<T: TypeTuple + 'static, F: FnMut(T)>(&mut self, mut f: F) {
self.iter_id(|_, x| f(x));
}
--- 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<u32>) {
- 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<T>(&mut self, gear_id: GearId, data: T)
- where
- T: GearData,
- Self: GearDataAggregator<T>,
- {
- self.find_processor().add(gear_id, data);
+ #[inline]
+ pub fn add_gear_data<T: Clone + 'static>(&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),
--- 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<GearId>,
- positions: Vec<FPPoint>,
- velocities: Vec<FPPoint>,
-}
-
-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<GearId> {
- 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<Item = (GearId, (&mut FPPoint, &FPPoint))> {
- self.gear_ids
- .iter()
- .cloned()
- .zip(self.positions.iter_mut().zip(self.velocities.iter()))
- }
-}
-
-pub struct StaticPhysicsCollection {
- gear_ids: Vec<GearId>,
- positions: Vec<FPPoint>,
-}
-
-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<GearId> {
- 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<bool>,
- dynamic_physics: DynamicPhysicsCollection,
- static_physics: StaticPhysicsCollection,
-
- physics_cleanup: Vec<GearId>,
position_updates: PositionUpdates,
}
@@ -128,75 +49,31 @@
}
impl PhysicsProcessor {
+ pub fn register_components(data: &mut GearDataManager) {
+ data.register::<PositionData>();
+ data.register::<VelocityData>();
+ }
+
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<PhysicsData> 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<PhysicsData> {
- 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
- }
- }
-}