aboutsummaryrefslogtreecommitdiff
path: root/src/geometry/collider_set.rs
diff options
context:
space:
mode:
authorCrozet Sébastien <developer@crozet.re>2021-03-29 14:54:54 +0200
committerCrozet Sébastien <developer@crozet.re>2021-03-29 14:54:54 +0200
commit8173e7ada2e3f5c99de53b532adc085a26c1cefd (patch)
treefbee80982c2245c3e97036b683b00678e6d14a33 /src/geometry/collider_set.rs
parentdec3e4197f3f8b47baedb28ddec976a846e7d099 (diff)
downloadrapier-8173e7ada2e3f5c99de53b532adc085a26c1cefd.tar.gz
rapier-8173e7ada2e3f5c99de53b532adc085a26c1cefd.tar.bz2
rapier-8173e7ada2e3f5c99de53b532adc085a26c1cefd.zip
Allow collider modification after its insersion to the ColliderSet.
Diffstat (limited to 'src/geometry/collider_set.rs')
-rw-r--r--src/geometry/collider_set.rs174
1 files changed, 146 insertions, 28 deletions
diff --git a/src/geometry/collider_set.rs b/src/geometry/collider_set.rs
index d84639c..a68aac7 100644
--- a/src/geometry/collider_set.rs
+++ b/src/geometry/collider_set.rs
@@ -1,6 +1,7 @@
use crate::data::arena::Arena;
use crate::data::pubsub::PubSub;
use crate::dynamics::{RigidBodyHandle, RigidBodySet};
+use crate::geometry::collider::ColliderChanges;
use crate::geometry::{Collider, SAPProxyIndex};
use parry::partitioning::IndexedData;
use std::ops::{Index, IndexMut};
@@ -54,6 +55,8 @@ pub(crate) struct RemovedCollider {
pub struct ColliderSet {
pub(crate) removed_colliders: PubSub<RemovedCollider>,
pub(crate) colliders: Arena<Collider>,
+ pub(crate) modified_colliders: Vec<ColliderHandle>,
+ pub(crate) modified_all_colliders: bool,
}
impl ColliderSet {
@@ -62,6 +65,8 @@ impl ColliderSet {
ColliderSet {
removed_colliders: PubSub::new(),
colliders: Arena::new(),
+ modified_colliders: Vec::new(),
+ modified_all_colliders: false,
}
}
@@ -75,6 +80,37 @@ impl ColliderSet {
self.colliders.iter().map(|(h, c)| (ColliderHandle(h), c))
}
+ /// Iterates mutably through all the colliders on this set.
+ #[cfg(not(feature = "dev-remove-slow-accessors"))]
+ pub fn iter_mut(&mut self) -> impl Iterator<Item = (ColliderHandle, &mut Collider)> {
+ self.modified_colliders.clear();
+ self.modified_all_colliders = true;
+ self.colliders
+ .iter_mut()
+ .map(|(h, b)| (ColliderHandle(h), b))
+ }
+
+ #[inline(always)]
+ pub(crate) fn foreach_modified_colliders(&self, mut f: impl FnMut(ColliderHandle, &Collider)) {
+ for handle in &self.modified_colliders {
+ if let Some(rb) = self.colliders.get(handle.0) {
+ f(*handle, rb)
+ }
+ }
+ }
+
+ #[inline(always)]
+ pub(crate) fn foreach_modified_colliders_mut_internal(
+ &mut self,
+ mut f: impl FnMut(ColliderHandle, &mut Collider),
+ ) {
+ for handle in &self.modified_colliders {
+ if let Some(rb) = self.colliders.get_mut(handle.0) {
+ f(*handle, rb)
+ }
+ }
+ }
+
/// The number of colliders on this set.
pub fn len(&self) -> usize {
self.colliders.len()
@@ -90,6 +126,24 @@ impl ColliderSet {
self.colliders.contains(handle.0)
}
+ pub(crate) fn contains_any_modified_collider(&self) -> bool {
+ self.modified_all_colliders || !self.modified_colliders.is_empty()
+ }
+
+ pub(crate) fn clear_modified_colliders(&mut self) {
+ if self.modified_all_colliders {
+ for collider in self.colliders.iter_mut() {
+ collider.1.changes = ColliderChanges::empty();
+ }
+ self.modified_colliders.clear();
+ self.modified_all_colliders = false;
+ } else {
+ for handle in self.modified_colliders.drain(..) {
+ self.colliders[handle.0].changes = ColliderChanges::empty();
+ }
+ }
+ }
+
/// Inserts a new collider to this set and retrieve its handle.
pub fn insert(
&mut self,
@@ -106,11 +160,12 @@ impl ColliderSet {
// NOTE: we use `get_mut` instead of `get_mut_internal` so that the
// modification flag is updated properly.
let parent = bodies
- .get_mut(parent_handle)
+ .get_mut_internal_with_modification_tracking(parent_handle)
.expect("Parent rigid body not found.");
- coll.prev_position = parent.position * coll.delta;
coll.position = parent.position * coll.delta;
let handle = ColliderHandle(self.colliders.insert(coll));
+ self.modified_colliders.push(handle);
+
let coll = self.colliders.get(handle.0).unwrap();
parent.add_collider(handle, &coll);
handle
@@ -133,7 +188,7 @@ impl ColliderSet {
*/
// NOTE: we use `get_mut` instead of `get_mut_internal` so that the
// modification flag is updated properly.
- if let Some(parent) = bodies.get_mut(collider.parent) {
+ if let Some(parent) = bodies.get_mut_internal_with_modification_tracking(collider.parent) {
parent.remove_collider_internal(handle, &collider);
if wake_up {
@@ -178,10 +233,17 @@ impl ColliderSet {
///
/// Using this is discouraged in favor of `self.get_mut(handle)` which does not
/// suffer form the ABA problem.
+ #[cfg(not(feature = "dev-remove-slow-accessors"))]
pub fn get_unknown_gen_mut(&mut self, i: usize) -> Option<(&mut Collider, ColliderHandle)> {
- self.colliders
- .get_unknown_gen_mut(i)
- .map(|(c, h)| (c, ColliderHandle(h)))
+ let (collider, handle) = self.colliders.get_unknown_gen_mut(i)?;
+ let handle = ColliderHandle(handle);
+ Self::mark_as_modified(
+ handle,
+ collider,
+ &mut self.modified_colliders,
+ self.modified_all_colliders,
+ );
+ Some((collider, handle))
}
/// Get the collider with the given handle.
@@ -189,31 +251,79 @@ impl ColliderSet {
self.colliders.get(handle.0)
}
+ fn mark_as_modified(
+ handle: ColliderHandle,
+ collider: &mut Collider,
+ modified_colliders: &mut Vec<ColliderHandle>,
+ modified_all_colliders: bool,
+ ) {
+ if !modified_all_colliders && !collider.changes.contains(ColliderChanges::MODIFIED) {
+ collider.changes = ColliderChanges::MODIFIED;
+ modified_colliders.push(handle);
+ }
+ }
+
/// Gets a mutable reference to the collider with the given handle.
+ #[cfg(not(feature = "dev-remove-slow-accessors"))]
pub fn get_mut(&mut self, handle: ColliderHandle) -> Option<&mut Collider> {
+ let result = self.colliders.get_mut(handle.0)?;
+ Self::mark_as_modified(
+ handle,
+ result,
+ &mut self.modified_colliders,
+ self.modified_all_colliders,
+ );
+ Some(result)
+ }
+
+ pub(crate) fn get_mut_internal(&mut self, handle: ColliderHandle) -> Option<&mut Collider> {
self.colliders.get_mut(handle.0)
}
- // pub(crate) fn get2_mut_internal(
- // &mut self,
- // h1: ColliderHandle,
- // h2: ColliderHandle,
- // ) -> (Option<&mut Collider>, Option<&mut Collider>) {
- // self.colliders.get2_mut(h1, h2)
- // }
-
- // pub fn iter_mut(&mut self) -> impl Iterator<Item = (ColliderHandle, ColliderMut)> {
- // // let sender = &self.activation_channel_sender;
- // self.colliders.iter_mut().map(move |(h, rb)| {
- // (h, ColliderMut::new(h, rb /*sender.clone()*/))
- // })
- // }
-
- // pub(crate) fn iter_mut_internal(
- // &mut self,
- // ) -> impl Iterator<Item = (ColliderHandle, &mut Collider)> {
- // self.colliders.iter_mut()
- // }
+ // Just a very long name instead of `.get_mut` to make sure
+ // this is really the method we wanted to use instead of `get_mut_internal`.
+ pub(crate) fn get_mut_internal_with_modification_tracking(
+ &mut self,
+ handle: ColliderHandle,
+ ) -> Option<&mut Collider> {
+ let result = self.colliders.get_mut(handle.0)?;
+ Self::mark_as_modified(
+ handle,
+ result,
+ &mut self.modified_colliders,
+ self.modified_all_colliders,
+ );
+ Some(result)
+ }
+
+ // Utility function to avoid some borrowing issue in the `maintain` method.
+ fn maintain_one(bodies: &mut RigidBodySet, collider: &mut Collider) {
+ if collider
+ .changes
+ .contains(ColliderChanges::POSITION_WRT_PARENT)
+ {
+ if let Some(parent) = bodies.get_mut_internal(collider.parent()) {
+ let position = parent.position * collider.position_wrt_parent();
+ // NOTE: the set_position method will add the ColliderChanges::POSITION flag,
+ // which is needed for the broad-phase/narrow-phase to detect the change.
+ collider.set_position(position);
+ }
+ }
+ }
+
+ pub(crate) fn handle_user_changes(&mut self, bodies: &mut RigidBodySet) {
+ if self.modified_all_colliders {
+ for (_, rb) in self.colliders.iter_mut() {
+ Self::maintain_one(bodies, rb)
+ }
+ } else {
+ for handle in self.modified_colliders.drain(..) {
+ if let Some(rb) = self.colliders.get_mut(handle.0) {
+ Self::maintain_one(bodies, rb)
+ }
+ }
+ }
+ }
}
impl Index<ColliderHandle> for ColliderSet {
@@ -224,8 +334,16 @@ impl Index<ColliderHandle> for ColliderSet {
}
}
+#[cfg(not(feature = "dev-remove-slow-accessors"))]
impl IndexMut<ColliderHandle> for ColliderSet {
- fn index_mut(&mut self, index: ColliderHandle) -> &mut Collider {
- &mut self.colliders[index.0]
+ fn index_mut(&mut self, handle: ColliderHandle) -> &mut Collider {
+ let collider = &mut self.colliders[handle.0];
+ Self::mark_as_modified(
+ handle,
+ collider,
+ &mut self.modified_colliders,
+ self.modified_all_colliders,
+ );
+ collider
}
}