rapier3d/geometry/
collider_set.rs

1use crate::data::arena::Arena;
2use crate::data::{HasModifiedFlag, ModifiedObjects};
3use crate::dynamics::{IslandManager, RigidBodyHandle, RigidBodySet};
4use crate::geometry::{Collider, ColliderChanges, ColliderHandle, ColliderParent};
5use crate::math::Isometry;
6use std::ops::{Index, IndexMut};
7
8pub(crate) type ModifiedColliders = ModifiedObjects<ColliderHandle, Collider>;
9
10impl HasModifiedFlag for Collider {
11    #[inline]
12    fn has_modified_flag(&self) -> bool {
13        self.changes.contains(ColliderChanges::MODIFIED)
14    }
15
16    #[inline]
17    fn set_modified_flag(&mut self) {
18        self.changes |= ColliderChanges::MODIFIED;
19    }
20}
21
22#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
23#[derive(Clone, Default, Debug)]
24/// A set of colliders that can be handled by a physics `World`.
25pub struct ColliderSet {
26    pub(crate) colliders: Arena<Collider>,
27    pub(crate) modified_colliders: ModifiedColliders,
28    pub(crate) removed_colliders: Vec<ColliderHandle>,
29}
30
31impl ColliderSet {
32    /// Create a new empty set of colliders.
33    pub fn new() -> Self {
34        ColliderSet {
35            colliders: Arena::new(),
36            modified_colliders: Default::default(),
37            removed_colliders: Vec::new(),
38        }
39    }
40
41    /// Create a new set of colliders, with an initial capacity
42    /// for the set of colliders as well as the tracking of
43    /// modified colliders.
44    pub fn with_capacity(capacity: usize) -> Self {
45        ColliderSet {
46            colliders: Arena::with_capacity(capacity),
47            modified_colliders: ModifiedColliders::with_capacity(capacity),
48            removed_colliders: Vec::new(),
49        }
50    }
51
52    pub(crate) fn take_modified(&mut self) -> ModifiedColliders {
53        std::mem::take(&mut self.modified_colliders)
54    }
55
56    pub(crate) fn take_removed(&mut self) -> Vec<ColliderHandle> {
57        std::mem::take(&mut self.removed_colliders)
58    }
59
60    /// An always-invalid collider handle.
61    pub fn invalid_handle() -> ColliderHandle {
62        ColliderHandle::from_raw_parts(crate::INVALID_U32, crate::INVALID_U32)
63    }
64
65    /// Iterate through all the colliders on this set.
66    pub fn iter(&self) -> impl ExactSizeIterator<Item = (ColliderHandle, &Collider)> {
67        self.colliders.iter().map(|(h, c)| (ColliderHandle(h), c))
68    }
69
70    /// Iterate through all the enabled colliders on this set.
71    pub fn iter_enabled(&self) -> impl Iterator<Item = (ColliderHandle, &Collider)> {
72        self.colliders
73            .iter()
74            .map(|(h, c)| (ColliderHandle(h), c))
75            .filter(|(_, c)| c.is_enabled())
76    }
77
78    /// Iterates mutably through all the colliders on this set.
79    #[cfg(not(feature = "dev-remove-slow-accessors"))]
80    pub fn iter_mut(&mut self) -> impl Iterator<Item = (ColliderHandle, &mut Collider)> {
81        self.modified_colliders.clear();
82        let modified_colliders = &mut self.modified_colliders;
83        self.colliders.iter_mut().map(move |(h, co)| {
84            // NOTE: we push unchecked here since we are just re-populating the
85            //       `modified_colliders` set that we just cleared before iteration.
86            modified_colliders.push_unchecked(ColliderHandle(h), co);
87            (ColliderHandle(h), co)
88        })
89    }
90
91    /// Iterates mutably through all the enabled colliders on this set.
92    #[cfg(not(feature = "dev-remove-slow-accessors"))]
93    pub fn iter_enabled_mut(&mut self) -> impl Iterator<Item = (ColliderHandle, &mut Collider)> {
94        self.iter_mut().filter(|(_, c)| c.is_enabled())
95    }
96
97    /// The number of colliders on this set.
98    pub fn len(&self) -> usize {
99        self.colliders.len()
100    }
101
102    /// `true` if there are no colliders in this set.
103    pub fn is_empty(&self) -> bool {
104        self.colliders.is_empty()
105    }
106
107    /// Is this collider handle valid?
108    pub fn contains(&self, handle: ColliderHandle) -> bool {
109        self.colliders.contains(handle.0)
110    }
111
112    /// Inserts a new collider to this set and retrieve its handle.
113    pub fn insert(&mut self, coll: impl Into<Collider>) -> ColliderHandle {
114        let mut coll = coll.into();
115        // Make sure the internal links are reset, they may not be
116        // if this rigid-body was obtained by cloning another one.
117        coll.reset_internal_references();
118        coll.parent = None;
119        let handle = ColliderHandle(self.colliders.insert(coll));
120        // NOTE: we push unchecked because this is a brand-new collider
121        //       so it was initialized with the changed flag but isn’t in
122        //       the set yet.
123        self.modified_colliders
124            .push_unchecked(handle, &mut self.colliders[handle.0]);
125        handle
126    }
127
128    /// Inserts a new collider to this set, attach it to the given rigid-body, and retrieve its handle.
129    pub fn insert_with_parent(
130        &mut self,
131        coll: impl Into<Collider>,
132        parent_handle: RigidBodyHandle,
133        bodies: &mut RigidBodySet,
134    ) -> ColliderHandle {
135        let mut coll = coll.into();
136        // Make sure the internal links are reset, they may not be
137        // if this collider was obtained by cloning another one.
138        coll.reset_internal_references();
139
140        if let Some(prev_parent) = &mut coll.parent {
141            prev_parent.handle = parent_handle;
142        } else {
143            coll.parent = Some(ColliderParent {
144                handle: parent_handle,
145                pos_wrt_parent: coll.pos.0,
146            });
147        }
148
149        // NOTE: we use `get_mut` instead of `get_mut_internal` so that the
150        // modification flag is updated properly.
151        let parent = bodies
152            .get_mut_internal_with_modification_tracking(parent_handle)
153            .expect("Parent rigid body not found.");
154        let handle = ColliderHandle(self.colliders.insert(coll));
155        let coll = self.colliders.get_mut(handle.0).unwrap();
156        // NOTE: we push unchecked because this is a brand-new collider
157        //       so it was initialized with the changed flag but isn’t in
158        //       the set yet.
159        self.modified_colliders.push_unchecked(handle, coll);
160
161        parent.add_collider_internal(
162            handle,
163            coll.parent.as_mut().unwrap(),
164            &mut coll.pos,
165            &coll.shape,
166            &coll.mprops,
167        );
168        handle
169    }
170
171    /// Sets the parent of the given collider.
172    // TODO: find a way to define this as a method of Collider.
173    pub fn set_parent(
174        &mut self,
175        handle: ColliderHandle,
176        new_parent_handle: Option<RigidBodyHandle>,
177        bodies: &mut RigidBodySet,
178    ) {
179        if let Some(collider) = self.get_mut(handle) {
180            let curr_parent = collider.parent.map(|p| p.handle);
181            if new_parent_handle == curr_parent {
182                return; // Nothing to do, this is the same parent.
183            }
184
185            collider.changes |= ColliderChanges::PARENT;
186
187            if let Some(parent_handle) = curr_parent {
188                if let Some(rb) = bodies.get_mut(parent_handle) {
189                    rb.remove_collider_internal(handle);
190                }
191            }
192
193            match new_parent_handle {
194                Some(new_parent_handle) => {
195                    if let Some(parent) = &mut collider.parent {
196                        parent.handle = new_parent_handle;
197                    } else {
198                        collider.parent = Some(ColliderParent {
199                            handle: new_parent_handle,
200                            pos_wrt_parent: Isometry::identity(),
201                        })
202                    };
203
204                    if let Some(rb) = bodies.get_mut(new_parent_handle) {
205                        rb.add_collider_internal(
206                            handle,
207                            collider.parent.as_ref().unwrap(),
208                            &mut collider.pos,
209                            &collider.shape,
210                            &collider.mprops,
211                        );
212                    }
213                }
214                None => collider.parent = None,
215            }
216        }
217    }
218
219    /// Remove a collider from this set and update its parent accordingly.
220    ///
221    /// If `wake_up` is `true`, the rigid-body the removed collider is attached to
222    /// will be woken up.
223    pub fn remove(
224        &mut self,
225        handle: ColliderHandle,
226        islands: &mut IslandManager,
227        bodies: &mut RigidBodySet,
228        wake_up: bool,
229    ) -> Option<Collider> {
230        let collider = self.colliders.remove(handle.0)?;
231
232        /*
233         * Delete the collider from its parent body.
234         */
235        // NOTE: we use `get_mut_internal_with_modification_tracking` instead of `get_mut_internal` so that the
236        // modification flag is updated properly.
237        if let Some(parent) = &collider.parent {
238            if let Some(parent_rb) =
239                bodies.get_mut_internal_with_modification_tracking(parent.handle)
240            {
241                parent_rb.remove_collider_internal(handle);
242
243                if wake_up {
244                    islands.wake_up(bodies, parent.handle, true);
245                }
246            }
247        }
248
249        /*
250         * Publish removal.
251         */
252        self.removed_colliders.push(handle);
253
254        Some(collider)
255    }
256
257    /// Gets the collider with the given handle without a known generation.
258    ///
259    /// This is useful when you know you want the collider at position `i` but
260    /// don't know what is its current generation number. Generation numbers are
261    /// used to protect from the ABA problem because the collider position `i`
262    /// are recycled between two insertion and a removal.
263    ///
264    /// Using this is discouraged in favor of `self.get(handle)` which does not
265    /// suffer form the ABA problem.
266    pub fn get_unknown_gen(&self, i: u32) -> Option<(&Collider, ColliderHandle)> {
267        self.colliders
268            .get_unknown_gen(i)
269            .map(|(c, h)| (c, ColliderHandle(h)))
270    }
271
272    /// Gets a mutable reference to the collider with the given handle without a known generation.
273    ///
274    /// This is useful when you know you want the collider at position `i` but
275    /// don't know what is its current generation number. Generation numbers are
276    /// used to protect from the ABA problem because the collider position `i`
277    /// are recycled between two insertion and a removal.
278    ///
279    /// Using this is discouraged in favor of `self.get_mut(handle)` which does not
280    /// suffer form the ABA problem.
281    #[cfg(not(feature = "dev-remove-slow-accessors"))]
282    pub fn get_unknown_gen_mut(&mut self, i: u32) -> Option<(&mut Collider, ColliderHandle)> {
283        let (collider, handle) = self.colliders.get_unknown_gen_mut(i)?;
284        let handle = ColliderHandle(handle);
285        self.modified_colliders.push_once(handle, collider);
286        Some((collider, handle))
287    }
288
289    /// Get the collider with the given handle.
290    pub fn get(&self, handle: ColliderHandle) -> Option<&Collider> {
291        self.colliders.get(handle.0)
292    }
293
294    /// Gets a mutable reference to the collider with the given handle.
295    #[cfg(not(feature = "dev-remove-slow-accessors"))]
296    pub fn get_mut(&mut self, handle: ColliderHandle) -> Option<&mut Collider> {
297        let result = self.colliders.get_mut(handle.0)?;
298        self.modified_colliders.push_once(handle, result);
299        Some(result)
300    }
301
302    /// Gets a mutable reference to the two colliders with the given handles.
303    ///
304    /// If `handle1 == handle2`, only the first returned value will be `Some`.
305    #[cfg(not(feature = "dev-remove-slow-accessors"))]
306    pub fn get_pair_mut(
307        &mut self,
308        handle1: ColliderHandle,
309        handle2: ColliderHandle,
310    ) -> (Option<&mut Collider>, Option<&mut Collider>) {
311        if handle1 == handle2 {
312            (self.get_mut(handle1), None)
313        } else {
314            let (mut co1, mut co2) = self.colliders.get2_mut(handle1.0, handle2.0);
315            if let Some(co1) = co1.as_deref_mut() {
316                self.modified_colliders.push_once(handle1, co1);
317            }
318            if let Some(co2) = co2.as_deref_mut() {
319                self.modified_colliders.push_once(handle2, co2);
320            }
321            (co1, co2)
322        }
323    }
324
325    pub(crate) fn index_mut_internal(&mut self, handle: ColliderHandle) -> &mut Collider {
326        &mut self.colliders[handle.0]
327    }
328
329    pub(crate) fn get_mut_internal(&mut self, handle: ColliderHandle) -> Option<&mut Collider> {
330        self.colliders.get_mut(handle.0)
331    }
332
333    // Just a very long name instead of `.get_mut` to make sure
334    // this is really the method we wanted to use instead of `get_mut_internal`.
335    #[allow(dead_code)]
336    pub(crate) fn get_mut_internal_with_modification_tracking(
337        &mut self,
338        handle: ColliderHandle,
339    ) -> Option<&mut Collider> {
340        let result = self.colliders.get_mut(handle.0)?;
341        self.modified_colliders.push_once(handle, result);
342        Some(result)
343    }
344}
345
346impl Index<crate::data::Index> for ColliderSet {
347    type Output = Collider;
348
349    fn index(&self, index: crate::data::Index) -> &Collider {
350        &self.colliders[index]
351    }
352}
353
354impl Index<ColliderHandle> for ColliderSet {
355    type Output = Collider;
356
357    fn index(&self, index: ColliderHandle) -> &Collider {
358        &self.colliders[index.0]
359    }
360}
361
362#[cfg(not(feature = "dev-remove-slow-accessors"))]
363impl IndexMut<ColliderHandle> for ColliderSet {
364    fn index_mut(&mut self, handle: ColliderHandle) -> &mut Collider {
365        let collider = &mut self.colliders[handle.0];
366        self.modified_colliders.push_once(handle, collider);
367        collider
368    }
369}