rust/hwphysics/src/collision.rs
author Wuzzy <Wuzzy2@mail.ru>
Tue, 27 Aug 2019 23:16:42 +0200
changeset 15375 5a934f83d5eb
parent 15287 478d5372eb4a
child 15385 6e3e5be8b2e2
permissions -rw-r--r--
Tempoary (!!!) workaround for incorrect key combination description in frontend This workaround fixes the incorrect string while preserving translations and the 1.0.0 string freeze. Remember to revert this commit and fix the string in binds.cpp after the 1.0.0 release!
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
15125
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14721
diff changeset
     1
use std::ops::RangeInclusive;
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14721
diff changeset
     2
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14721
diff changeset
     3
use crate::{
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14721
diff changeset
     4
    common::{GearData, GearDataProcessor, GearId},
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14721
diff changeset
     5
    grid::Grid,
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14721
diff changeset
     6
};
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14721
diff changeset
     7
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14721
diff changeset
     8
use fpnum::*;
15287
478d5372eb4a implement empty gear lookup entries
alfadur
parents: 15279
diff changeset
     9
use integral_geometry::{Point, Size};
15125
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14721
diff changeset
    10
use land2d::Land2D;
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14721
diff changeset
    11
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14721
diff changeset
    12
pub fn fppoint_round(point: &FPPoint) -> Point {
15275
7446258fab98 add time events
alfadur
parents: 15271
diff changeset
    13
    Point::new(point.x().round(), point.y().round())
15125
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14721
diff changeset
    14
}
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14721
diff changeset
    15
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14721
diff changeset
    16
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14721
diff changeset
    17
pub struct CircleBounds {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14721
diff changeset
    18
    pub center: FPPoint,
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14721
diff changeset
    19
    pub radius: FPNum,
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14721
diff changeset
    20
}
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14721
diff changeset
    21
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14721
diff changeset
    22
impl CircleBounds {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14721
diff changeset
    23
    pub fn intersects(&self, other: &CircleBounds) -> bool {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14721
diff changeset
    24
        (other.center - self.center).is_in_range(self.radius + other.radius)
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14721
diff changeset
    25
    }
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14721
diff changeset
    26
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14721
diff changeset
    27
    pub fn rows(&self) -> impl Iterator<Item = (usize, RangeInclusive<usize>)> {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14721
diff changeset
    28
        let radius = self.radius.abs_round() as usize;
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14721
diff changeset
    29
        let center = Point::from_fppoint(&self.center);
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14721
diff changeset
    30
        (center.y as usize - radius..=center.y as usize + radius)
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14721
diff changeset
    31
            .map(move |row| (row, center.x as usize - radius..=center.x as usize + radius))
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14721
diff changeset
    32
    }
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14721
diff changeset
    33
}
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14721
diff changeset
    34
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14721
diff changeset
    35
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14721
diff changeset
    36
pub struct CollisionData {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14721
diff changeset
    37
    pub bounds: CircleBounds,
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14721
diff changeset
    38
}
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14721
diff changeset
    39
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14721
diff changeset
    40
impl GearData for CollisionData {}
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14721
diff changeset
    41
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14721
diff changeset
    42
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14721
diff changeset
    43
pub struct ContactData {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14721
diff changeset
    44
    pub elasticity: FPNum,
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14721
diff changeset
    45
    pub friction: FPNum,
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14721
diff changeset
    46
}
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14721
diff changeset
    47
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14721
diff changeset
    48
impl GearData for ContactData {}
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14721
diff changeset
    49
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14721
diff changeset
    50
struct EnabledCollisionsCollection {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14721
diff changeset
    51
    gear_ids: Vec<GearId>,
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14721
diff changeset
    52
    collisions: Vec<CollisionData>,
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14721
diff changeset
    53
}
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14721
diff changeset
    54
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14721
diff changeset
    55
impl EnabledCollisionsCollection {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14721
diff changeset
    56
    fn new() -> Self {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14721
diff changeset
    57
        Self {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14721
diff changeset
    58
            gear_ids: Vec::new(),
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14721
diff changeset
    59
            collisions: Vec::new(),
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14721
diff changeset
    60
        }
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14721
diff changeset
    61
    }
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14721
diff changeset
    62
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14721
diff changeset
    63
    fn push(&mut self, gear_id: GearId, collision: CollisionData) {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14721
diff changeset
    64
        self.gear_ids.push(gear_id);
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14721
diff changeset
    65
        self.collisions.push(collision);
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14721
diff changeset
    66
    }
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14721
diff changeset
    67
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14721
diff changeset
    68
    fn iter(&self) -> impl Iterator<Item = (GearId, &CollisionData)> {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14721
diff changeset
    69
        self.gear_ids.iter().cloned().zip(self.collisions.iter())
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14721
diff changeset
    70
    }
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14721
diff changeset
    71
}
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14721
diff changeset
    72
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14721
diff changeset
    73
pub struct CollisionProcessor {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14721
diff changeset
    74
    grid: Grid,
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14721
diff changeset
    75
    enabled_collisions: EnabledCollisionsCollection,
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14721
diff changeset
    76
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14721
diff changeset
    77
    detected_collisions: DetectedCollisions,
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14721
diff changeset
    78
}
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14721
diff changeset
    79
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14721
diff changeset
    80
pub struct DetectedCollisions {
15268
24828281c9c5 reserve zero gear id
alfadur
parents: 15266
diff changeset
    81
    pub pairs: Vec<(GearId, Option<GearId>)>,
15125
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14721
diff changeset
    82
    pub positions: Vec<Point>,
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14721
diff changeset
    83
}
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14721
diff changeset
    84
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14721
diff changeset
    85
impl DetectedCollisions {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14721
diff changeset
    86
    pub fn new(capacity: usize) -> Self {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14721
diff changeset
    87
        Self {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14721
diff changeset
    88
            pairs: Vec::with_capacity(capacity),
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14721
diff changeset
    89
            positions: Vec::with_capacity(capacity),
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14721
diff changeset
    90
        }
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14721
diff changeset
    91
    }
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14721
diff changeset
    92
15268
24828281c9c5 reserve zero gear id
alfadur
parents: 15266
diff changeset
    93
    pub fn push(
24828281c9c5 reserve zero gear id
alfadur
parents: 15266
diff changeset
    94
        &mut self,
24828281c9c5 reserve zero gear id
alfadur
parents: 15266
diff changeset
    95
        contact_gear_id1: GearId,
24828281c9c5 reserve zero gear id
alfadur
parents: 15266
diff changeset
    96
        contact_gear_id2: Option<GearId>,
24828281c9c5 reserve zero gear id
alfadur
parents: 15266
diff changeset
    97
        position: &FPPoint,
24828281c9c5 reserve zero gear id
alfadur
parents: 15266
diff changeset
    98
    ) {
15125
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14721
diff changeset
    99
        self.pairs.push((contact_gear_id1, contact_gear_id2));
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14721
diff changeset
   100
        self.positions.push(fppoint_round(&position));
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14721
diff changeset
   101
    }
15271
b58f98bbc120 clear intermediate result structures between iterations
alfadur
parents: 15268
diff changeset
   102
b58f98bbc120 clear intermediate result structures between iterations
alfadur
parents: 15268
diff changeset
   103
    pub fn clear(&mut self) {
b58f98bbc120 clear intermediate result structures between iterations
alfadur
parents: 15268
diff changeset
   104
        self.pairs.clear();
b58f98bbc120 clear intermediate result structures between iterations
alfadur
parents: 15268
diff changeset
   105
        self.positions.clear()
b58f98bbc120 clear intermediate result structures between iterations
alfadur
parents: 15268
diff changeset
   106
    }
15125
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14721
diff changeset
   107
}
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14721
diff changeset
   108
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14721
diff changeset
   109
impl CollisionProcessor {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14721
diff changeset
   110
    pub fn new(size: Size) -> Self {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14721
diff changeset
   111
        Self {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14721
diff changeset
   112
            grid: Grid::new(size),
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14721
diff changeset
   113
            enabled_collisions: EnabledCollisionsCollection::new(),
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14721
diff changeset
   114
            detected_collisions: DetectedCollisions::new(0),
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14721
diff changeset
   115
        }
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14721
diff changeset
   116
    }
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14721
diff changeset
   117
15271
b58f98bbc120 clear intermediate result structures between iterations
alfadur
parents: 15268
diff changeset
   118
    pub fn process(
b58f98bbc120 clear intermediate result structures between iterations
alfadur
parents: 15268
diff changeset
   119
        &mut self,
b58f98bbc120 clear intermediate result structures between iterations
alfadur
parents: 15268
diff changeset
   120
        land: &Land2D<u32>,
b58f98bbc120 clear intermediate result structures between iterations
alfadur
parents: 15268
diff changeset
   121
        updates: &crate::physics::PositionUpdates,
b58f98bbc120 clear intermediate result structures between iterations
alfadur
parents: 15268
diff changeset
   122
    ) -> &DetectedCollisions {
b58f98bbc120 clear intermediate result structures between iterations
alfadur
parents: 15268
diff changeset
   123
        self.detected_collisions.clear();
15266
501dfa1c8deb update collision grid with position changes
alfadur
parents: 15125
diff changeset
   124
        for (id, old_position, new_position) in updates.iter() {
501dfa1c8deb update collision grid with position changes
alfadur
parents: 15125
diff changeset
   125
            self.grid.update_position(id, old_position, new_position)
501dfa1c8deb update collision grid with position changes
alfadur
parents: 15125
diff changeset
   126
        }
15271
b58f98bbc120 clear intermediate result structures between iterations
alfadur
parents: 15268
diff changeset
   127
15125
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14721
diff changeset
   128
        self.grid.check_collisions(&mut self.detected_collisions);
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14721
diff changeset
   129
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14721
diff changeset
   130
        for (gear_id, collision) in self.enabled_collisions.iter() {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14721
diff changeset
   131
            if collision
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14721
diff changeset
   132
                .bounds
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14721
diff changeset
   133
                .rows()
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14721
diff changeset
   134
                .any(|(y, r)| (&land[y][r]).iter().any(|v| *v != 0))
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14721
diff changeset
   135
            {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14721
diff changeset
   136
                self.detected_collisions
15268
24828281c9c5 reserve zero gear id
alfadur
parents: 15266
diff changeset
   137
                    .push(gear_id, None, &collision.bounds.center)
15125
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14721
diff changeset
   138
            }
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14721
diff changeset
   139
        }
15271
b58f98bbc120 clear intermediate result structures between iterations
alfadur
parents: 15268
diff changeset
   140
b58f98bbc120 clear intermediate result structures between iterations
alfadur
parents: 15268
diff changeset
   141
        &self.detected_collisions
15125
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14721
diff changeset
   142
    }
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14721
diff changeset
   143
}
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14721
diff changeset
   144
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14721
diff changeset
   145
impl GearDataProcessor<CollisionData> for CollisionProcessor {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14721
diff changeset
   146
    fn add(&mut self, gear_id: GearId, gear_data: CollisionData) {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14721
diff changeset
   147
        self.grid.insert_static(gear_id, &gear_data.bounds);
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14721
diff changeset
   148
    }
15279
42b710b0f883 add gear allocator
alfadur
parents: 15275
diff changeset
   149
42b710b0f883 add gear allocator
alfadur
parents: 15275
diff changeset
   150
    fn remove(&mut self, gear_id: GearId) {
42b710b0f883 add gear allocator
alfadur
parents: 15275
diff changeset
   151
        self.grid.remove(gear_id);
42b710b0f883 add gear allocator
alfadur
parents: 15275
diff changeset
   152
    }
15287
478d5372eb4a implement empty gear lookup entries
alfadur
parents: 15279
diff changeset
   153
478d5372eb4a implement empty gear lookup entries
alfadur
parents: 15279
diff changeset
   154
    fn get(&mut self, gear_id: GearId) -> Option<CollisionData> {
478d5372eb4a implement empty gear lookup entries
alfadur
parents: 15279
diff changeset
   155
        None
478d5372eb4a implement empty gear lookup entries
alfadur
parents: 15279
diff changeset
   156
    }
15125
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14721
diff changeset
   157
}