rust/hwphysics/src/collision.rs
author Wuzzy <Wuzzy2@mail.ru>
Thu, 25 Apr 2019 23:01:05 +0200
changeset 14844 e239378a9400
parent 14721 8e74d4eb89f5
child 15125 febccab419b1
permissions -rw-r--r--
Prevent entering “/”, “\” and “:” in team and scheme names. The name of teams and schems is saved in the file name itself, so these characters would cause trouble as they are used in path names in Linux and Windows.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
14721
8e74d4eb89f5 add random falling stuff
alfadur
parents: 14707
diff changeset
     1
use std::ops::RangeInclusive;
14183
a4c17cfaa4c9 split hwphysics into modules
alfadur
parents:
diff changeset
     2
a4c17cfaa4c9 split hwphysics into modules
alfadur
parents:
diff changeset
     3
use crate::{
14721
8e74d4eb89f5 add random falling stuff
alfadur
parents: 14707
diff changeset
     4
    common::{GearData, GearDataProcessor, GearId},
8e74d4eb89f5 add random falling stuff
alfadur
parents: 14707
diff changeset
     5
    grid::Grid,
14183
a4c17cfaa4c9 split hwphysics into modules
alfadur
parents:
diff changeset
     6
    physics::PhysicsData,
a4c17cfaa4c9 split hwphysics into modules
alfadur
parents:
diff changeset
     7
};
a4c17cfaa4c9 split hwphysics into modules
alfadur
parents:
diff changeset
     8
a4c17cfaa4c9 split hwphysics into modules
alfadur
parents:
diff changeset
     9
use fpnum::*;
14721
8e74d4eb89f5 add random falling stuff
alfadur
parents: 14707
diff changeset
    10
use integral_geometry::{GridIndex, Point, Size};
14183
a4c17cfaa4c9 split hwphysics into modules
alfadur
parents:
diff changeset
    11
use land2d::Land2D;
a4c17cfaa4c9 split hwphysics into modules
alfadur
parents:
diff changeset
    12
a4c17cfaa4c9 split hwphysics into modules
alfadur
parents:
diff changeset
    13
pub fn fppoint_round(point: &FPPoint) -> Point {
a4c17cfaa4c9 split hwphysics into modules
alfadur
parents:
diff changeset
    14
    Point::new(point.x().round() as i32, point.y().round() as i32)
a4c17cfaa4c9 split hwphysics into modules
alfadur
parents:
diff changeset
    15
}
a4c17cfaa4c9 split hwphysics into modules
alfadur
parents:
diff changeset
    16
a4c17cfaa4c9 split hwphysics into modules
alfadur
parents:
diff changeset
    17
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
a4c17cfaa4c9 split hwphysics into modules
alfadur
parents:
diff changeset
    18
pub struct CircleBounds {
a4c17cfaa4c9 split hwphysics into modules
alfadur
parents:
diff changeset
    19
    pub center: FPPoint,
14721
8e74d4eb89f5 add random falling stuff
alfadur
parents: 14707
diff changeset
    20
    pub radius: FPNum,
14183
a4c17cfaa4c9 split hwphysics into modules
alfadur
parents:
diff changeset
    21
}
a4c17cfaa4c9 split hwphysics into modules
alfadur
parents:
diff changeset
    22
a4c17cfaa4c9 split hwphysics into modules
alfadur
parents:
diff changeset
    23
impl CircleBounds {
a4c17cfaa4c9 split hwphysics into modules
alfadur
parents:
diff changeset
    24
    pub fn intersects(&self, other: &CircleBounds) -> bool {
a4c17cfaa4c9 split hwphysics into modules
alfadur
parents:
diff changeset
    25
        (other.center - self.center).is_in_range(self.radius + other.radius)
a4c17cfaa4c9 split hwphysics into modules
alfadur
parents:
diff changeset
    26
    }
a4c17cfaa4c9 split hwphysics into modules
alfadur
parents:
diff changeset
    27
a4c17cfaa4c9 split hwphysics into modules
alfadur
parents:
diff changeset
    28
    pub fn rows(&self) -> impl Iterator<Item = (usize, RangeInclusive<usize>)> {
a4c17cfaa4c9 split hwphysics into modules
alfadur
parents:
diff changeset
    29
        let radius = self.radius.abs_round() as usize;
a4c17cfaa4c9 split hwphysics into modules
alfadur
parents:
diff changeset
    30
        let center = Point::from_fppoint(&self.center);
a4c17cfaa4c9 split hwphysics into modules
alfadur
parents:
diff changeset
    31
        (center.y as usize - radius..=center.y as usize + radius)
a4c17cfaa4c9 split hwphysics into modules
alfadur
parents:
diff changeset
    32
            .map(move |row| (row, center.x as usize - radius..=center.x as usize + radius))
a4c17cfaa4c9 split hwphysics into modules
alfadur
parents:
diff changeset
    33
    }
a4c17cfaa4c9 split hwphysics into modules
alfadur
parents:
diff changeset
    34
}
a4c17cfaa4c9 split hwphysics into modules
alfadur
parents:
diff changeset
    35
a4c17cfaa4c9 split hwphysics into modules
alfadur
parents:
diff changeset
    36
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
a4c17cfaa4c9 split hwphysics into modules
alfadur
parents:
diff changeset
    37
pub struct CollisionData {
14721
8e74d4eb89f5 add random falling stuff
alfadur
parents: 14707
diff changeset
    38
    pub bounds: CircleBounds,
14183
a4c17cfaa4c9 split hwphysics into modules
alfadur
parents:
diff changeset
    39
}
a4c17cfaa4c9 split hwphysics into modules
alfadur
parents:
diff changeset
    40
14184
abbb74b9cb62 generalize adding data to World
alfadur
parents: 14183
diff changeset
    41
impl GearData for CollisionData {}
abbb74b9cb62 generalize adding data to World
alfadur
parents: 14183
diff changeset
    42
14183
a4c17cfaa4c9 split hwphysics into modules
alfadur
parents:
diff changeset
    43
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
a4c17cfaa4c9 split hwphysics into modules
alfadur
parents:
diff changeset
    44
pub struct ContactData {
a4c17cfaa4c9 split hwphysics into modules
alfadur
parents:
diff changeset
    45
    pub elasticity: FPNum,
14721
8e74d4eb89f5 add random falling stuff
alfadur
parents: 14707
diff changeset
    46
    pub friction: FPNum,
14183
a4c17cfaa4c9 split hwphysics into modules
alfadur
parents:
diff changeset
    47
}
a4c17cfaa4c9 split hwphysics into modules
alfadur
parents:
diff changeset
    48
14184
abbb74b9cb62 generalize adding data to World
alfadur
parents: 14183
diff changeset
    49
impl GearData for ContactData {}
abbb74b9cb62 generalize adding data to World
alfadur
parents: 14183
diff changeset
    50
14183
a4c17cfaa4c9 split hwphysics into modules
alfadur
parents:
diff changeset
    51
struct EnabledCollisionsCollection {
a4c17cfaa4c9 split hwphysics into modules
alfadur
parents:
diff changeset
    52
    gear_ids: Vec<GearId>,
14721
8e74d4eb89f5 add random falling stuff
alfadur
parents: 14707
diff changeset
    53
    collisions: Vec<CollisionData>,
14183
a4c17cfaa4c9 split hwphysics into modules
alfadur
parents:
diff changeset
    54
}
a4c17cfaa4c9 split hwphysics into modules
alfadur
parents:
diff changeset
    55
a4c17cfaa4c9 split hwphysics into modules
alfadur
parents:
diff changeset
    56
impl EnabledCollisionsCollection {
14184
abbb74b9cb62 generalize adding data to World
alfadur
parents: 14183
diff changeset
    57
    fn new() -> Self {
abbb74b9cb62 generalize adding data to World
alfadur
parents: 14183
diff changeset
    58
        Self {
abbb74b9cb62 generalize adding data to World
alfadur
parents: 14183
diff changeset
    59
            gear_ids: Vec::new(),
14721
8e74d4eb89f5 add random falling stuff
alfadur
parents: 14707
diff changeset
    60
            collisions: Vec::new(),
14184
abbb74b9cb62 generalize adding data to World
alfadur
parents: 14183
diff changeset
    61
        }
abbb74b9cb62 generalize adding data to World
alfadur
parents: 14183
diff changeset
    62
    }
abbb74b9cb62 generalize adding data to World
alfadur
parents: 14183
diff changeset
    63
14183
a4c17cfaa4c9 split hwphysics into modules
alfadur
parents:
diff changeset
    64
    fn push(&mut self, gear_id: GearId, collision: CollisionData) {
a4c17cfaa4c9 split hwphysics into modules
alfadur
parents:
diff changeset
    65
        self.gear_ids.push(gear_id);
a4c17cfaa4c9 split hwphysics into modules
alfadur
parents:
diff changeset
    66
        self.collisions.push(collision);
a4c17cfaa4c9 split hwphysics into modules
alfadur
parents:
diff changeset
    67
    }
a4c17cfaa4c9 split hwphysics into modules
alfadur
parents:
diff changeset
    68
a4c17cfaa4c9 split hwphysics into modules
alfadur
parents:
diff changeset
    69
    fn iter(&self) -> impl Iterator<Item = (GearId, &CollisionData)> {
a4c17cfaa4c9 split hwphysics into modules
alfadur
parents:
diff changeset
    70
        self.gear_ids.iter().cloned().zip(self.collisions.iter())
a4c17cfaa4c9 split hwphysics into modules
alfadur
parents:
diff changeset
    71
    }
a4c17cfaa4c9 split hwphysics into modules
alfadur
parents:
diff changeset
    72
}
a4c17cfaa4c9 split hwphysics into modules
alfadur
parents:
diff changeset
    73
a4c17cfaa4c9 split hwphysics into modules
alfadur
parents:
diff changeset
    74
pub struct CollisionProcessor {
a4c17cfaa4c9 split hwphysics into modules
alfadur
parents:
diff changeset
    75
    grid: Grid,
a4c17cfaa4c9 split hwphysics into modules
alfadur
parents:
diff changeset
    76
    enabled_collisions: EnabledCollisionsCollection,
a4c17cfaa4c9 split hwphysics into modules
alfadur
parents:
diff changeset
    77
a4c17cfaa4c9 split hwphysics into modules
alfadur
parents:
diff changeset
    78
    detected_collisions: DetectedCollisions,
a4c17cfaa4c9 split hwphysics into modules
alfadur
parents:
diff changeset
    79
}
a4c17cfaa4c9 split hwphysics into modules
alfadur
parents:
diff changeset
    80
a4c17cfaa4c9 split hwphysics into modules
alfadur
parents:
diff changeset
    81
pub struct DetectedCollisions {
a4c17cfaa4c9 split hwphysics into modules
alfadur
parents:
diff changeset
    82
    pub pairs: Vec<(GearId, GearId)>,
14721
8e74d4eb89f5 add random falling stuff
alfadur
parents: 14707
diff changeset
    83
    pub positions: Vec<Point>,
14183
a4c17cfaa4c9 split hwphysics into modules
alfadur
parents:
diff changeset
    84
}
a4c17cfaa4c9 split hwphysics into modules
alfadur
parents:
diff changeset
    85
a4c17cfaa4c9 split hwphysics into modules
alfadur
parents:
diff changeset
    86
impl DetectedCollisions {
a4c17cfaa4c9 split hwphysics into modules
alfadur
parents:
diff changeset
    87
    pub fn new(capacity: usize) -> Self {
a4c17cfaa4c9 split hwphysics into modules
alfadur
parents:
diff changeset
    88
        Self {
a4c17cfaa4c9 split hwphysics into modules
alfadur
parents:
diff changeset
    89
            pairs: Vec::with_capacity(capacity),
a4c17cfaa4c9 split hwphysics into modules
alfadur
parents:
diff changeset
    90
            positions: Vec::with_capacity(capacity),
a4c17cfaa4c9 split hwphysics into modules
alfadur
parents:
diff changeset
    91
        }
a4c17cfaa4c9 split hwphysics into modules
alfadur
parents:
diff changeset
    92
    }
a4c17cfaa4c9 split hwphysics into modules
alfadur
parents:
diff changeset
    93
a4c17cfaa4c9 split hwphysics into modules
alfadur
parents:
diff changeset
    94
    pub fn push(&mut self, contact_gear_id1: GearId, contact_gear_id2: GearId, position: &FPPoint) {
a4c17cfaa4c9 split hwphysics into modules
alfadur
parents:
diff changeset
    95
        self.pairs.push((contact_gear_id1, contact_gear_id2));
14184
abbb74b9cb62 generalize adding data to World
alfadur
parents: 14183
diff changeset
    96
        self.positions.push(fppoint_round(&position));
14183
a4c17cfaa4c9 split hwphysics into modules
alfadur
parents:
diff changeset
    97
    }
a4c17cfaa4c9 split hwphysics into modules
alfadur
parents:
diff changeset
    98
}
a4c17cfaa4c9 split hwphysics into modules
alfadur
parents:
diff changeset
    99
a4c17cfaa4c9 split hwphysics into modules
alfadur
parents:
diff changeset
   100
impl CollisionProcessor {
14184
abbb74b9cb62 generalize adding data to World
alfadur
parents: 14183
diff changeset
   101
    pub fn new(size: Size) -> Self {
abbb74b9cb62 generalize adding data to World
alfadur
parents: 14183
diff changeset
   102
        Self {
abbb74b9cb62 generalize adding data to World
alfadur
parents: 14183
diff changeset
   103
            grid: Grid::new(size),
abbb74b9cb62 generalize adding data to World
alfadur
parents: 14183
diff changeset
   104
            enabled_collisions: EnabledCollisionsCollection::new(),
14721
8e74d4eb89f5 add random falling stuff
alfadur
parents: 14707
diff changeset
   105
            detected_collisions: DetectedCollisions::new(0),
14184
abbb74b9cb62 generalize adding data to World
alfadur
parents: 14183
diff changeset
   106
        }
abbb74b9cb62 generalize adding data to World
alfadur
parents: 14183
diff changeset
   107
    }
abbb74b9cb62 generalize adding data to World
alfadur
parents: 14183
diff changeset
   108
abbb74b9cb62 generalize adding data to World
alfadur
parents: 14183
diff changeset
   109
    pub fn process(&mut self, land: &Land2D<u32>, updates: &crate::physics::PositionUpdates) {
14183
a4c17cfaa4c9 split hwphysics into modules
alfadur
parents:
diff changeset
   110
        self.grid.check_collisions(&mut self.detected_collisions);
a4c17cfaa4c9 split hwphysics into modules
alfadur
parents:
diff changeset
   111
a4c17cfaa4c9 split hwphysics into modules
alfadur
parents:
diff changeset
   112
        for (gear_id, collision) in self.enabled_collisions.iter() {
14721
8e74d4eb89f5 add random falling stuff
alfadur
parents: 14707
diff changeset
   113
            if collision
8e74d4eb89f5 add random falling stuff
alfadur
parents: 14707
diff changeset
   114
                .bounds
8e74d4eb89f5 add random falling stuff
alfadur
parents: 14707
diff changeset
   115
                .rows()
8e74d4eb89f5 add random falling stuff
alfadur
parents: 14707
diff changeset
   116
                .any(|(y, r)| (&land[y][r]).iter().any(|v| *v != 0))
8e74d4eb89f5 add random falling stuff
alfadur
parents: 14707
diff changeset
   117
            {
8e74d4eb89f5 add random falling stuff
alfadur
parents: 14707
diff changeset
   118
                self.detected_collisions
8e74d4eb89f5 add random falling stuff
alfadur
parents: 14707
diff changeset
   119
                    .push(gear_id, 0, &collision.bounds.center)
14183
a4c17cfaa4c9 split hwphysics into modules
alfadur
parents:
diff changeset
   120
            }
a4c17cfaa4c9 split hwphysics into modules
alfadur
parents:
diff changeset
   121
        }
a4c17cfaa4c9 split hwphysics into modules
alfadur
parents:
diff changeset
   122
    }
14184
abbb74b9cb62 generalize adding data to World
alfadur
parents: 14183
diff changeset
   123
}
14183
a4c17cfaa4c9 split hwphysics into modules
alfadur
parents:
diff changeset
   124
14184
abbb74b9cb62 generalize adding data to World
alfadur
parents: 14183
diff changeset
   125
impl GearDataProcessor<CollisionData> for CollisionProcessor {
abbb74b9cb62 generalize adding data to World
alfadur
parents: 14183
diff changeset
   126
    fn add(&mut self, gear_id: GearId, gear_data: CollisionData) {
abbb74b9cb62 generalize adding data to World
alfadur
parents: 14183
diff changeset
   127
        self.grid.insert_static(gear_id, &gear_data.bounds);
14183
a4c17cfaa4c9 split hwphysics into modules
alfadur
parents:
diff changeset
   128
    }
14707
29dbe9ce8b7d add basic map rendering with gl
fkaa
parents: 14184
diff changeset
   129
}