--- 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<GearId>,
collisions: Vec<CollisionData>
}
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<u32>, 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<u32>, 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<CollisionData> 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
--- 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<T: GearData> {
+ fn add(&mut self, gear_id: GearId, gear_data: T);
+}
+
+pub trait GearDataAggregator<T: GearData> {
+ fn find_processor(&mut self) -> &mut GearDataProcessor<T>;
+}
--- 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<GridBin>,
@@ -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) {
--- 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<u32>) {
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<T>(&mut self, gear_id: GearId, data: T)
+ where T: GearData,
+ Self: GearDataAggregator<T>
+ {
+ 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);
+ }
}
--- 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<GearId>,
@@ -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<GearId>,
- position_updates: PositionUpdate
+ position_updates: PositionUpdates
}
-pub struct PositionUpdate {
+pub struct PositionUpdates {
pub gear_ids: Vec<GearId>,
pub positions: Vec<FPPoint>
}
-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<PhysicsData> 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