Skip to main content

loam_physics/
dirty.rs

1use crate::body::{BodyArena, BodyId, RigidBody};
2use crate::integrator::PhysicsSpace;
3
4#[derive(Default)]
5pub(crate) struct DirtyBodies {
6    ids: Vec<BodyId>,
7    marked: Vec<bool>,
8}
9
10impl DirtyBodies {
11    pub(crate) fn mark(&mut self, id: BodyId) {
12        let slot = id.slot() as usize;
13        if slot >= self.marked.len() {
14            self.marked.resize(slot + 1, false);
15        }
16        if self.marked[slot] {
17            return;
18        }
19        self.marked[slot] = true;
20        self.ids.push(id);
21    }
22
23    pub(crate) fn forget(&mut self, id: BodyId) {
24        if let Some(flag) = self.marked.get_mut(id.slot() as usize) {
25            *flag = false;
26        }
27    }
28
29    pub(crate) fn mark_every<S: PhysicsSpace>(&mut self, bodies: &BodyArena<S>) {
30        self.ids.clear();
31        for flag in &mut self.marked {
32            *flag = false;
33        }
34        for dense in 0..bodies.len() {
35            self.mark(bodies.id_at(dense));
36        }
37    }
38
39    pub(crate) fn drain<'a, S: PhysicsSpace>(
40        &'a mut self,
41        bodies: &'a BodyArena<S>,
42    ) -> DirtyDrain<'a, S> {
43        let Self { ids, marked } = self;
44        DirtyDrain {
45            bodies,
46            marked,
47            ids: ids.drain(..),
48        }
49    }
50}
51
52pub struct DirtyDrain<'a, S: PhysicsSpace> {
53    bodies: &'a BodyArena<S>,
54    marked: &'a mut [bool],
55    ids: std::vec::Drain<'a, BodyId>,
56}
57
58impl<'a, S: PhysicsSpace> Iterator for DirtyDrain<'a, S> {
59    type Item = (BodyId, &'a RigidBody<S>);
60
61    fn next(&mut self) -> Option<Self::Item> {
62        let bodies = self.bodies;
63        for id in self.ids.by_ref() {
64            if let Some(flag) = self.marked.get_mut(id.slot() as usize) {
65                *flag = false;
66            }
67            if let Some(body) = bodies.get(id) {
68                return Some((id, body));
69            }
70        }
71        None
72    }
73}
74
75impl<S: PhysicsSpace> Drop for DirtyDrain<'_, S> {
76    fn drop(&mut self) {
77        for id in self.ids.by_ref() {
78            if let Some(flag) = self.marked.get_mut(id.slot() as usize) {
79                *flag = false;
80            }
81        }
82    }
83}