nphysics3d/object/
body_set.rs

1use generational_arena::Arena;
2use std::hash::Hash;
3
4use crate::object::{Body, DefaultColliderHandle, Multibody, RigidBody};
5use crate::world::GeometricalWorld;
6use na::RealField;
7
8/// Trait auto-implemented for types that can be used as a Body handle.
9///
10/// Body handles must be unique, i.e., they should not suffer from the ABA problem.
11pub trait BodyHandle: Copy + Hash + PartialEq + Eq + 'static + Send + Sync {}
12
13impl<T: Copy + Hash + PartialEq + Eq + 'static + Send + Sync> BodyHandle for T {}
14
15/// Trait implemented by sets of bodies.
16///
17/// A set of bodies maps a body handle to a body instance. In addition, it must maintain a set of
18/// body handle of bodies that have been removed (see the `pop_removal_event` method for details).
19pub trait BodySet<N: RealField + Copy> {
20    /// Type of a body handle identifying a body in this set.
21    type Handle: BodyHandle;
22
23    /// Gets a reference to the body identified by `handle`.
24    fn get(&self, handle: Self::Handle) -> Option<&dyn Body<N>>;
25    /// Gets a mutable reference to the body identified by `handle`.
26    fn get_mut(&mut self, handle: Self::Handle) -> Option<&mut dyn Body<N>>;
27
28    /// Gets a reference to the two bodies identified by `handle1` and `handle2`.
29    ///
30    /// Both handles are allowed to be equal.
31    fn get_pair(
32        &self,
33        handle1: Self::Handle,
34        handle2: Self::Handle,
35    ) -> (Option<&dyn Body<N>>, Option<&dyn Body<N>>) {
36        (self.get(handle1), self.get(handle2))
37    }
38
39    /// Check if this set contains a body identified by `handle`.
40    fn contains(&self, handle: Self::Handle) -> bool;
41
42    /// Iterate through all the bodies on this set, applying the closure `f` on them.
43    fn foreach(&self, f: &mut dyn FnMut(Self::Handle, &dyn Body<N>));
44    /// Mutable iterate through all the bodies on this set, applying the closure `f` on them.
45    fn foreach_mut(&mut self, f: &mut dyn FnMut(Self::Handle, &mut dyn Body<N>));
46
47    /// Gets the handle of one body that has been removed.
48    ///
49    /// A body set must keep track (using typically a stack or a queue) of every body that has been
50    /// removed from it. This is used by  nphysics to perform some internal cleanup actions, or
51    /// physical actions like waking bodies touching one that has been removed.
52    ///
53    /// This method should return a removed body handle only once.
54    fn pop_removal_event(&mut self) -> Option<Self::Handle>;
55}
56
57/// The default set containing all the bodies added to the world.
58///
59/// It is based on an arena using generational indices to avoid the ABA problem.
60pub struct DefaultBodySet<N: RealField + Copy> {
61    bodies: Arena<Box<dyn Body<N>>>,
62    removed: Vec<DefaultBodyHandle>,
63}
64
65impl<N: RealField + Copy> DefaultBodySet<N> {
66    /// Creates an empty set.
67    pub fn new() -> Self {
68        DefaultBodySet {
69            bodies: Arena::new(),
70            removed: Vec::new(),
71        }
72    }
73
74    /// Adds a body to this set.
75    pub fn insert(&mut self, body: impl Body<N>) -> DefaultBodyHandle {
76        self.bodies.insert(Box::new(body))
77    }
78
79    /// Adds a body (represented as a boxed trait-object) to this set.
80    pub fn insert_boxed(&mut self, body: Box<dyn Body<N>>) -> DefaultBodyHandle {
81        self.bodies.insert(body)
82    }
83
84    /// Removes a body from this set.
85    pub fn remove(&mut self, to_remove: DefaultBodyHandle) -> Option<Box<dyn Body<N>>> {
86        let res = self.bodies.remove(to_remove)?;
87        self.removed.push(to_remove);
88        Some(res)
89    }
90
91    /// Check if this set contains a body identified by `handle`.
92    fn contains(&self, handle: DefaultBodyHandle) -> bool {
93        self.bodies.contains(handle)
94    }
95
96    /// Gets a reference to the body identified by `handle`.
97    pub fn get(&self, handle: DefaultBodyHandle) -> Option<&dyn Body<N>> {
98        self.bodies.get(handle).map(|b| &**b)
99    }
100
101    /// Gets a mutable reference to the body identified by `handle`.
102    pub fn get_mut(&mut self, handle: DefaultBodyHandle) -> Option<&mut dyn Body<N>> {
103        self.bodies.get_mut(handle).map(|b| &mut **b)
104    }
105
106    /// Iterate through all the bodies and their handles.
107    pub fn iter(&self) -> impl Iterator<Item = (DefaultBodyHandle, &dyn Body<N>)> {
108        self.bodies.iter().map(|b| (b.0, &**b.1))
109    }
110
111    /// Mutably iterate through all the bodies and their handles.
112    pub fn iter_mut(&mut self) -> impl Iterator<Item = (DefaultBodyHandle, &mut dyn Body<N>)> {
113        self.bodies.iter_mut().map(|b| (b.0, &mut **b.1))
114    }
115
116    /// Gets the rigid body identified by `handle`.
117    ///
118    /// Returns `None` if the body does not exists, of if it exists but is not a rigid body.
119    pub fn rigid_body(&self, handle: DefaultBodyHandle) -> Option<&RigidBody<N>> {
120        self.get(handle).and_then(|b| b.downcast_ref())
121    }
122
123    /// Gets a mutable reference to the rigid body identified by `handle`.
124    ///
125    /// Returns `None` if the body does not exists, of if it exists but is not a rigid body.
126    pub fn rigid_body_mut(&mut self, handle: DefaultBodyHandle) -> Option<&mut RigidBody<N>> {
127        self.get_mut(handle).and_then(|b| b.downcast_mut())
128    }
129
130    /// Gets the multibody identified by `handle`.
131    ///
132    /// Returns `None` if the body does not exists, of if it exists but is not a multibody.
133    pub fn multibody(&self, handle: DefaultBodyHandle) -> Option<&Multibody<N>> {
134        self.get(handle).and_then(|b| b.downcast_ref())
135    }
136
137    /// Gets a mutable reference to the multibody identified by `handle`.
138    ///
139    /// Returns `None` if the body does not exists, of if it exists but is not a multibody.
140    pub fn multibody_mut(&mut self, handle: DefaultBodyHandle) -> Option<&mut Multibody<N>> {
141        self.get_mut(handle).and_then(|b| b.downcast_mut())
142    }
143}
144
145impl<N: RealField + Copy> BodySet<N> for DefaultBodySet<N> {
146    type Handle = DefaultBodyHandle;
147
148    fn get(&self, handle: Self::Handle) -> Option<&dyn Body<N>> {
149        self.get(handle)
150    }
151
152    fn get_mut(&mut self, handle: Self::Handle) -> Option<&mut dyn Body<N>> {
153        self.get_mut(handle)
154    }
155
156    fn contains(&self, handle: Self::Handle) -> bool {
157        self.contains(handle)
158    }
159
160    fn foreach(&self, f: &mut dyn FnMut(Self::Handle, &dyn Body<N>)) {
161        for (h, b) in self.iter() {
162            f(h, b)
163        }
164    }
165
166    fn foreach_mut(&mut self, f: &mut dyn FnMut(Self::Handle, &mut dyn Body<N>)) {
167        for (h, b) in self.iter_mut() {
168            f(h, b)
169        }
170    }
171
172    fn pop_removal_event(&mut self) -> Option<Self::Handle> {
173        self.removed.pop()
174    }
175}
176
177/// The body handle used by the `DefaultBodySet`.
178pub type DefaultBodyHandle = generational_arena::Index;
179/// The body part handle used by the `DefaultBodySet`.
180pub type DefaultBodyPartHandle = BodyPartHandle<DefaultBodyHandle>;
181
182/// A unique identifier of a body part added to the world.
183#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
184pub struct BodyPartHandle<Handle: BodyHandle>(pub Handle, pub usize);
185
186/// A abstract body descriptor to be passed to the physics `World` to create a body.
187pub trait BodyDesc<N: RealField + Copy> {
188    /// The type of body being generated.
189    type Body: Body<N>;
190
191    /// Called by the `World` to create a body with the given allocated handle.
192    fn build_with_handle(
193        &self,
194        gworld: &mut GeometricalWorld<N, DefaultBodyHandle, DefaultColliderHandle>,
195        handle: DefaultBodyHandle,
196    ) -> Self::Body;
197}