rapier2d/dynamics/
rigid_body_set.rs

1use crate::data::{Arena, HasModifiedFlag, ModifiedObjects};
2use crate::dynamics::{
3    ImpulseJointSet, IslandManager, MultibodyJointSet, RigidBody, RigidBodyBuilder,
4    RigidBodyChanges, RigidBodyHandle,
5};
6use crate::geometry::ColliderSet;
7use std::ops::{Index, IndexMut};
8
9#[cfg(doc)]
10use crate::pipeline::PhysicsPipeline;
11
12#[derive(Copy, Clone, Debug, PartialEq, Eq)]
13#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
14/// A pair of rigid body handles.
15pub struct BodyPair {
16    /// The first rigid body handle.
17    pub body1: RigidBodyHandle,
18    /// The second rigid body handle.
19    pub body2: RigidBodyHandle,
20}
21
22impl BodyPair {
23    /// Builds a new pair of rigid-body handles.
24    pub fn new(body1: RigidBodyHandle, body2: RigidBodyHandle) -> Self {
25        BodyPair { body1, body2 }
26    }
27}
28
29pub(crate) type ModifiedRigidBodies = ModifiedObjects<RigidBodyHandle, RigidBody>;
30
31impl HasModifiedFlag for RigidBody {
32    #[inline]
33    fn has_modified_flag(&self) -> bool {
34        self.changes.contains(RigidBodyChanges::MODIFIED)
35    }
36
37    #[inline]
38    fn set_modified_flag(&mut self) {
39        self.changes |= RigidBodyChanges::MODIFIED;
40    }
41}
42
43#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
44#[derive(Clone, Default, Debug)]
45/// The collection that stores all rigid bodies in your physics world.
46///
47/// This is where you add, remove, and access all your physics objects. Think of it as
48/// a "database" of all rigid bodies, where each body gets a unique handle for fast lookup.
49///
50/// # Why use handles?
51///
52/// Instead of storing bodies directly, you get back a [`RigidBodyHandle`] when inserting.
53/// This handle is lightweight (just an index + generation) and remains valid even if other
54/// bodies are removed, protecting you from use-after-free bugs.
55///
56/// # Example
57///
58/// ```
59/// # use rapier3d::prelude::*;
60/// let mut bodies = RigidBodySet::new();
61///
62/// // Add a dynamic body
63/// let handle = bodies.insert(RigidBodyBuilder::dynamic());
64///
65/// // Access it later
66/// if let Some(body) = bodies.get_mut(handle) {
67///     body.apply_impulse(vector![0.0, 10.0, 0.0], true);
68/// }
69/// ```
70pub struct RigidBodySet {
71    // NOTE: the pub(crate) are needed by the broad phase
72    // to avoid borrowing issues. It is also needed for
73    // parallelism because the `Receiver` breaks the Sync impl.
74    // Could we avoid this?
75    pub(crate) bodies: Arena<RigidBody>,
76    pub(crate) modified_bodies: ModifiedRigidBodies,
77    #[cfg_attr(feature = "serde-serialize", serde(skip))]
78    pub(crate) default_fixed: RigidBody,
79}
80
81impl RigidBodySet {
82    /// Creates a new empty collection of rigid bodies.
83    ///
84    /// Call this once when setting up your physics world. The collection will
85    /// automatically grow as you add more bodies.
86    pub fn new() -> Self {
87        RigidBodySet {
88            bodies: Arena::new(),
89            modified_bodies: ModifiedObjects::default(),
90            default_fixed: RigidBodyBuilder::fixed().build(),
91        }
92    }
93
94    /// Creates a new collection with pre-allocated space for the given number of bodies.
95    ///
96    /// Use this if you know approximately how many bodies you'll need, to avoid
97    /// multiple reallocations as the collection grows.
98    ///
99    /// # Example
100    /// ```
101    /// # use rapier3d::prelude::*;
102    /// // You know you'll have ~1000 bodies
103    /// let mut bodies = RigidBodySet::with_capacity(1000);
104    /// ```
105    pub fn with_capacity(capacity: usize) -> Self {
106        RigidBodySet {
107            bodies: Arena::with_capacity(capacity),
108            modified_bodies: ModifiedRigidBodies::with_capacity(capacity),
109            default_fixed: RigidBodyBuilder::fixed().build(),
110        }
111    }
112
113    pub(crate) fn take_modified(&mut self) -> ModifiedRigidBodies {
114        std::mem::take(&mut self.modified_bodies)
115    }
116
117    /// Returns how many rigid bodies are currently in this collection.
118    pub fn len(&self) -> usize {
119        self.bodies.len()
120    }
121
122    /// Returns `true` if there are no rigid bodies in this collection.
123    pub fn is_empty(&self) -> bool {
124        self.bodies.is_empty()
125    }
126
127    /// Checks if the given handle points to a valid rigid body that still exists.
128    ///
129    /// Returns `false` if the body was removed or the handle is invalid.
130    pub fn contains(&self, handle: RigidBodyHandle) -> bool {
131        self.bodies.contains(handle.0)
132    }
133
134    /// Adds a rigid body to the world and returns its handle for future access.
135    ///
136    /// The handle is how you'll refer to this body later (to move it, apply forces, etc.).
137    /// Keep the handle somewhere accessible - you can't get the body back without it!
138    ///
139    /// # Example
140    /// ```
141    /// # use rapier3d::prelude::*;
142    /// # let mut bodies = RigidBodySet::new();
143    /// let handle = bodies.insert(
144    ///     RigidBodyBuilder::dynamic()
145    ///         .translation(vector![0.0, 5.0, 0.0])
146    ///         .build()
147    /// );
148    /// // Store `handle` to access this body later
149    /// ```
150    pub fn insert(&mut self, rb: impl Into<RigidBody>) -> RigidBodyHandle {
151        let mut rb = rb.into();
152        // Make sure the internal links are reset, they may not be
153        // if this rigid-body was obtained by cloning another one.
154        rb.reset_internal_references();
155        rb.changes.set(RigidBodyChanges::all(), true);
156
157        let handle = RigidBodyHandle(self.bodies.insert(rb));
158        // Using push_unchecked because this is a brand new rigid-body with the MODIFIED
159        // flags set but isn’t in the modified_bodies yet.
160        self.modified_bodies
161            .push_unchecked(handle, &mut self.bodies[handle.0]);
162        handle
163    }
164
165    /// Removes a rigid body from the world along with all its attached colliders and joints.
166    ///
167    /// This is a complete cleanup operation that removes:
168    /// - The rigid body itself
169    /// - All colliders attached to it (if `remove_attached_colliders` is `true`)
170    /// - All joints connected to this body
171    ///
172    /// Returns the removed body if it existed, or `None` if the handle was invalid.
173    ///
174    /// # Parameters
175    ///
176    /// * `remove_attached_colliders` - If `true`, removes all colliders attached to this body.
177    ///   If `false`, the colliders are detached and become independent.
178    ///
179    /// # Example
180    /// ```
181    /// # use rapier3d::prelude::*;
182    /// # let mut bodies = RigidBodySet::new();
183    /// # let mut islands = IslandManager::new();
184    /// # let mut colliders = ColliderSet::new();
185    /// # let mut impulse_joints = ImpulseJointSet::new();
186    /// # let mut multibody_joints = MultibodyJointSet::new();
187    /// # let handle = bodies.insert(RigidBodyBuilder::dynamic());
188    /// // Remove a body and everything attached to it
189    /// if let Some(body) = bodies.remove(
190    ///     handle,
191    ///     &mut islands,
192    ///     &mut colliders,
193    ///     &mut impulse_joints,
194    ///     &mut multibody_joints,
195    ///     true  // Remove colliders too
196    /// ) {
197    ///     println!("Removed body at {:?}", body.translation());
198    /// }
199    /// ```
200    #[profiling::function]
201    pub fn remove(
202        &mut self,
203        handle: RigidBodyHandle,
204        islands: &mut IslandManager,
205        colliders: &mut ColliderSet,
206        impulse_joints: &mut ImpulseJointSet,
207        multibody_joints: &mut MultibodyJointSet,
208        remove_attached_colliders: bool,
209    ) -> Option<RigidBody> {
210        let rb = self.bodies.remove(handle.0)?;
211        /*
212         * Update active sets.
213         */
214        islands.rigid_body_removed(handle, &rb.ids, self);
215
216        /*
217         * Remove colliders attached to this rigid-body.
218         */
219        if remove_attached_colliders {
220            for collider in rb.colliders() {
221                colliders.remove(*collider, islands, self, false);
222            }
223        } else {
224            // If we don’t remove the attached colliders, simply detach them.
225            let colliders_to_detach = rb.colliders().to_vec();
226            for co_handle in colliders_to_detach {
227                colliders.set_parent(co_handle, None, self);
228            }
229        }
230
231        /*
232         * Remove impulse_joints attached to this rigid-body.
233         */
234        impulse_joints.remove_joints_attached_to_rigid_body(handle);
235        multibody_joints.remove_joints_attached_to_rigid_body(handle);
236
237        Some(rb)
238    }
239
240    /// Gets a rigid body by its index without knowing the generation number.
241    ///
242    /// ⚠️ **Advanced/unsafe usage** - prefer [`get()`](Self::get) instead!
243    ///
244    /// This bypasses the generation check that normally protects against the ABA problem
245    /// (where an index gets reused after removal). Only use this if you're certain the
246    /// body at this index is the one you expect.
247    ///
248    /// Returns both the body and its current handle (with the correct generation).
249    pub fn get_unknown_gen(&self, i: u32) -> Option<(&RigidBody, RigidBodyHandle)> {
250        self.bodies
251            .get_unknown_gen(i)
252            .map(|(b, h)| (b, RigidBodyHandle(h)))
253    }
254
255    /// Gets a mutable reference to a rigid body by its index without knowing the generation.
256    ///
257    /// ⚠️ **Advanced/unsafe usage** - prefer [`get_mut()`](Self::get_mut) instead!
258    ///
259    /// This bypasses the generation check. See [`get_unknown_gen()`](Self::get_unknown_gen)
260    /// for more details on when this is appropriate (rarely).
261    #[cfg(not(feature = "dev-remove-slow-accessors"))]
262    pub fn get_unknown_gen_mut(&mut self, i: u32) -> Option<(&mut RigidBody, RigidBodyHandle)> {
263        let (rb, handle) = self.bodies.get_unknown_gen_mut(i)?;
264        let handle = RigidBodyHandle(handle);
265        self.modified_bodies.push_once(handle, rb);
266        Some((rb, handle))
267    }
268
269    /// Gets a read-only reference to the rigid body with the given handle.
270    ///
271    /// Returns `None` if the handle is invalid or the body was removed.
272    ///
273    /// Use this to read body properties like position, velocity, mass, etc.
274    pub fn get(&self, handle: RigidBodyHandle) -> Option<&RigidBody> {
275        self.bodies.get(handle.0)
276    }
277
278    /// Gets a mutable reference to the rigid body with the given handle.
279    ///
280    /// Returns `None` if the handle is invalid or the body was removed.
281    ///
282    /// Use this to modify body properties, apply forces/impulses, change velocities, etc.
283    ///
284    /// # Example
285    /// ```
286    /// # use rapier3d::prelude::*;
287    /// # let mut bodies = RigidBodySet::new();
288    /// # let handle = bodies.insert(RigidBodyBuilder::dynamic());
289    /// if let Some(body) = bodies.get_mut(handle) {
290    ///     body.set_linvel(vector![1.0, 0.0, 0.0], true);
291    ///     body.apply_impulse(vector![0.0, 100.0, 0.0], true);
292    /// }
293    /// ```
294    #[cfg(not(feature = "dev-remove-slow-accessors"))]
295    pub fn get_mut(&mut self, handle: RigidBodyHandle) -> Option<&mut RigidBody> {
296        let result = self.bodies.get_mut(handle.0)?;
297        self.modified_bodies.push_once(handle, result);
298        Some(result)
299    }
300
301    /// Gets mutable references to two different rigid bodies at once.
302    ///
303    /// This is useful when you need to modify two bodies simultaneously (e.g., when manually
304    /// handling collisions between them). If both handles are the same, only the first value
305    /// will be `Some`.
306    ///
307    /// # Example
308    /// ```
309    /// # use rapier3d::prelude::*;
310    /// # let mut bodies = RigidBodySet::new();
311    /// # let handle1 = bodies.insert(RigidBodyBuilder::dynamic());
312    /// # let handle2 = bodies.insert(RigidBodyBuilder::dynamic());
313    /// let (body1, body2) = bodies.get_pair_mut(handle1, handle2);
314    /// if let (Some(b1), Some(b2)) = (body1, body2) {
315    ///     // Can modify both bodies at once
316    ///     b1.apply_impulse(vector![10.0, 0.0, 0.0], true);
317    ///     b2.apply_impulse(vector![-10.0, 0.0, 0.0], true);
318    /// }
319    /// ```
320    #[cfg(not(feature = "dev-remove-slow-accessors"))]
321    pub fn get_pair_mut(
322        &mut self,
323        handle1: RigidBodyHandle,
324        handle2: RigidBodyHandle,
325    ) -> (Option<&mut RigidBody>, Option<&mut RigidBody>) {
326        if handle1 == handle2 {
327            (self.get_mut(handle1), None)
328        } else {
329            let (mut rb1, mut rb2) = self.bodies.get2_mut(handle1.0, handle2.0);
330            if let Some(rb1) = rb1.as_deref_mut() {
331                self.modified_bodies.push_once(handle1, rb1);
332            }
333            if let Some(rb2) = rb2.as_deref_mut() {
334                self.modified_bodies.push_once(handle2, rb2);
335            }
336            (rb1, rb2)
337        }
338    }
339
340    pub(crate) fn get_mut_internal(&mut self, handle: RigidBodyHandle) -> Option<&mut RigidBody> {
341        self.bodies.get_mut(handle.0)
342    }
343
344    pub(crate) fn index_mut_internal(&mut self, handle: RigidBodyHandle) -> &mut RigidBody {
345        &mut self.bodies[handle.0]
346    }
347
348    // Just a very long name instead of `.get_mut` to make sure
349    // this is really the method we wanted to use instead of `get_mut_internal`.
350    pub(crate) fn get_mut_internal_with_modification_tracking(
351        &mut self,
352        handle: RigidBodyHandle,
353    ) -> Option<&mut RigidBody> {
354        let result = self.bodies.get_mut(handle.0)?;
355        self.modified_bodies.push_once(handle, result);
356        Some(result)
357    }
358
359    /// Iterates over all rigid bodies in this collection.
360    ///
361    /// Each iteration yields a `(handle, &RigidBody)` pair. Use this to read properties
362    /// of all bodies (positions, velocities, etc.) without modifying them.
363    ///
364    /// # Example
365    /// ```
366    /// # use rapier3d::prelude::*;
367    /// # let mut bodies = RigidBodySet::new();
368    /// # bodies.insert(RigidBodyBuilder::dynamic());
369    /// for (handle, body) in bodies.iter() {
370    ///     println!("Body {:?} is at {:?}", handle, body.translation());
371    /// }
372    /// ```
373    pub fn iter(&self) -> impl Iterator<Item = (RigidBodyHandle, &RigidBody)> {
374        self.bodies.iter().map(|(h, b)| (RigidBodyHandle(h), b))
375    }
376
377    /// Iterates over all rigid bodies with mutable access.
378    ///
379    /// Each iteration yields a `(handle, &mut RigidBody)` pair. Use this to modify
380    /// multiple bodies in one pass.
381    ///
382    /// # Example
383    /// ```
384    /// # use rapier3d::prelude::*;
385    /// # let mut bodies = RigidBodySet::new();
386    /// # bodies.insert(RigidBodyBuilder::dynamic());
387    /// // Apply gravity manually to all dynamic bodies
388    /// for (handle, body) in bodies.iter_mut() {
389    ///     if body.is_dynamic() {
390    ///         body.add_force(vector![0.0, -9.81 * body.mass(), 0.0], true);
391    ///     }
392    /// }
393    /// ```
394    #[cfg(not(feature = "dev-remove-slow-accessors"))]
395    pub fn iter_mut(&mut self) -> impl Iterator<Item = (RigidBodyHandle, &mut RigidBody)> {
396        self.modified_bodies.clear();
397        let modified_bodies = &mut self.modified_bodies;
398        self.bodies.iter_mut().map(move |(h, b)| {
399            // NOTE: using `push_unchecked` because we just cleared `modified_bodies`
400            //       before iterating.
401            modified_bodies.push_unchecked(RigidBodyHandle(h), b);
402            (RigidBodyHandle(h), b)
403        })
404    }
405
406    /// Updates the positions of all colliders attached to bodies that have moved.
407    ///
408    /// Normally you don't need to call this - it's automatically handled by [`PhysicsPipeline::step`].
409    /// Only call this manually if you're:
410    /// - Moving bodies yourself outside of `step()`
411    /// - Using `QueryPipeline` for raycasts without running physics simulation
412    /// - Need collider positions to be immediately up-to-date for some custom logic
413    ///
414    /// This synchronizes collider world positions based on their parent bodies' positions.
415    pub fn propagate_modified_body_positions_to_colliders(&self, colliders: &mut ColliderSet) {
416        for body in self.modified_bodies.iter().filter_map(|h| self.get(*h)) {
417            if body.changes.contains(RigidBodyChanges::POSITION) {
418                for handle in body.colliders() {
419                    if let Some(collider) = colliders.get_mut(*handle) {
420                        let new_pos = body.position() * collider.position_wrt_parent().unwrap();
421                        collider.set_position(new_pos);
422                    }
423                }
424            }
425        }
426    }
427}
428
429impl Index<RigidBodyHandle> for RigidBodySet {
430    type Output = RigidBody;
431
432    fn index(&self, index: RigidBodyHandle) -> &RigidBody {
433        &self.bodies[index.0]
434    }
435}
436
437impl Index<crate::data::Index> for RigidBodySet {
438    type Output = RigidBody;
439
440    fn index(&self, index: crate::data::Index) -> &RigidBody {
441        &self.bodies[index]
442    }
443}
444
445#[cfg(not(feature = "dev-remove-slow-accessors"))]
446impl IndexMut<RigidBodyHandle> for RigidBodySet {
447    fn index_mut(&mut self, handle: RigidBodyHandle) -> &mut RigidBody {
448        let rb = &mut self.bodies[handle.0];
449        self.modified_bodies.push_once(handle, rb);
450        rb
451    }
452}