aboutsummaryrefslogtreecommitdiff
path: root/src/dynamics/island_set2.rs
diff options
context:
space:
mode:
authorCrozet Sébastien <developer@crozet.re>2021-02-04 18:04:50 +0100
committerCrozet Sébastien <developer@crozet.re>2021-02-04 18:04:50 +0100
commite585e262c468646e681aa1aec38d45cb7df2c082 (patch)
tree50ffe3f943061bbfcb8000f5f92d797dc52f0d35 /src/dynamics/island_set2.rs
parent09b867d0be5378f249a3dc4722527ed2e0233645 (diff)
downloadrapier-perf_experiments.tar.gz
rapier-perf_experiments.tar.bz2
rapier-perf_experiments.zip
Rename island_set2 -> island_setperf_experiments
Diffstat (limited to 'src/dynamics/island_set2.rs')
-rw-r--r--src/dynamics/island_set2.rs332
1 files changed, 0 insertions, 332 deletions
diff --git a/src/dynamics/island_set2.rs b/src/dynamics/island_set2.rs
deleted file mode 100644
index 098171a..0000000
--- a/src/dynamics/island_set2.rs
+++ /dev/null
@@ -1,332 +0,0 @@
-use crate::data::Coarena;
-use crate::dynamics::{RigidBody, RigidBodyHandle, RigidBodySet};
-use crate::geometry::{ColliderSet, NarrowPhase};
-use crate::utils;
-use std::collections::VecDeque;
-
-#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
-#[derive(Clone)]
-pub struct Island {
- bodies: Vec<RigidBodyHandle>,
-}
-
-impl Island {
- pub fn new() -> Self {
- Self { bodies: vec![] }
- }
-
- pub fn len(&self) -> usize {
- self.bodies.len()
- }
-
- pub fn is_sleeping(&self) -> bool {
- false // FIXME: should be true
- }
-
- pub fn bodies(&self) -> &[RigidBodyHandle] {
- &self.bodies
- }
-}
-
-#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
-#[derive(Clone)]
-pub struct IslandSet {
- // We can't store this in the rigid-bodies because that would
- // cause borrowing issues during the traversal.
- traversal_body_timestamps: Coarena<u64>,
- islands: Vec<Island>,
- active_island: usize,
- islands_to_extract: VecDeque<RigidBodyHandle>,
- islands_extraction_queue: Vec<RigidBodyHandle>,
- // NOTE: this value must never be 0, otherwise some
- // invariants used during the traversal can break.
- traversal_timestamp: u64,
-}
-
-impl IslandSet {
- pub fn new() -> Self {
- IslandSet {
- traversal_body_timestamps: Coarena::new(),
- islands: vec![Island::new()],
- active_island: 0,
- islands_to_extract: VecDeque::new(),
- islands_extraction_queue: vec![],
- traversal_timestamp: 1,
- }
- }
-
- pub fn num_active_islands(&self) -> usize {
- 1
- }
-
- pub fn is_island_sleeping(&self, island_id: usize) -> bool {
- island_id != self.active_island
- }
-
- pub fn active_bodies(&self) -> &[RigidBodyHandle] {
- &self.islands[self.active_island].bodies
- }
-
- pub fn incremental_update(&mut self, narrow_phase: &NarrowPhase) {}
-
- pub fn add_rigid_body(&mut self, handle: RigidBodyHandle, body: &mut RigidBody) {
- assert_eq!(body.island_id, crate::INVALID_USIZE);
-
- if !body.is_dynamic() {
- return;
- }
-
- self.traversal_body_timestamps
- .ensure_element_exists(handle.0, 0);
-
- if body.can_sleep() {
- body.island_id = self.islands.len();
- body.island_offset = 0;
- self.islands.push(Island {
- bodies: vec![handle],
- })
- } else {
- let mut active_island = &mut self.islands[self.active_island];
- body.island_id = self.active_island;
- body.island_offset = active_island.bodies.len();
- active_island.bodies.push(handle);
- }
- }
-
- pub fn contact_started(
- &mut self,
- bodies: &mut RigidBodySet,
- mut h1: RigidBodyHandle,
- mut h2: RigidBodyHandle,
- ) {
- let island1 = bodies[h1].island_id;
- let island2 = bodies[h2].island_id;
-
- self.wake_up_island(bodies, island1);
- self.wake_up_island(bodies, island2);
- }
-
- pub fn body_sleep_state_changed(&mut self, bodies: &mut RigidBodySet, handle: RigidBodyHandle) {
- let body = &mut bodies[handle];
- let island_id = body.island_id;
-
- if island_id == crate::INVALID_USIZE {
- self.add_rigid_body(handle, body);
- } else if island_id == self.active_island && body.can_sleep() {
- // The body is sleeping now.
- self.islands_to_extract.push_back(handle);
- } else if island_id != self.active_island && !body.can_sleep() {
- // The body is awake now.
- self.wake_up_island(bodies, island_id);
- }
- }
-
- #[inline(always)]
- fn push_contacting_bodies(
- handle: RigidBodyHandle,
- bodies: &mut RigidBodySet,
- colliders: &ColliderSet,
- narrow_phase: &NarrowPhase,
- queue: &mut Vec<RigidBodyHandle>,
- traversal_body_timestamps: &mut Coarena<u64>,
- first_traversal_timestamp: u64,
- traversal_timestamp: u64,
- ) -> bool {
- for collider_handle in &bodies[handle].colliders {
- if let Some(contacts) = narrow_phase.contacts_with(*collider_handle) {
- for inter in contacts {
- let other = crate::utils::select_other((inter.0, inter.1), *collider_handle);
- let other_body_handle = colliders[other].parent;
- let other_body = &bodies[other_body_handle];
-
- if other_body.is_dynamic() {
- if !other_body.can_sleep() {
- return false;
- }
-
- let other_body_timestamp =
- &mut traversal_body_timestamps[other_body_handle.0];
-
- if *other_body_timestamp >= first_traversal_timestamp
- && *other_body_timestamp < traversal_timestamp
- {
- // We already saw this body during another traversal this frame.
- // So we don't need to continue any further.
- return false;
- }
-
- if *other_body_timestamp != traversal_timestamp {
- *other_body_timestamp = traversal_timestamp;
- queue.push(other_body_handle);
- }
- }
- }
- }
- }
-
- true
- }
-
- pub fn update_sleeping_islands(
- &mut self,
- bodies: &mut RigidBodySet,
- colliders: &mut ColliderSet,
- narrow_phase: &NarrowPhase,
- ) {
- let first_traversal_timestamp = self.traversal_timestamp + 1;
- let mut island_found = false;
-
- while let Some(handle) = self.islands_to_extract.pop_front() {
- self.traversal_timestamp += 1;
- island_found = self.extract_sleeping_island(
- bodies,
- colliders,
- narrow_phase,
- handle,
- first_traversal_timestamp,
- ) || island_found;
-
- // Make sure our `traversal_timestamp` remains correct
- // even if it overflows (can happen in very long-running
- // simulations).
- if self.traversal_timestamp == u64::MAX - 1 {
- // Stop the work now because the overflowing timestamp
- // will cause issues with the traversal. Forcibly reset all
- // the timestamps and continue next frame.
- for body in bodies.iter_mut_internal() {
- body.1.traversal_timestamp = 0;
- }
- self.traversal_timestamp = 1;
- break;
- }
- }
-
- if island_found {
- // Now we need to remove from the active set all the bodies
- // we moved to a sleeping island.
- let mut i = 0;
- let mut new_len = 0;
- let active_island = &mut self.islands[self.active_island];
-
- while i < active_island.bodies.len() {
- let handle = active_island.bodies[i];
- let body = &mut bodies[handle];
-
- if body.island_id == self.active_island {
- // This body still belongs to this island.
- // Update its offset.
- body.island_offset = new_len;
- active_island.bodies[new_len] = handle;
- new_len += 1;
- }
-
- i += 1;
- }
-
- active_island.bodies.truncate(new_len);
- }
- }
-
- fn extract_sleeping_island(
- &mut self,
- bodies: &mut RigidBodySet,
- colliders: &mut ColliderSet,
- narrow_phase: &NarrowPhase,
- handle: RigidBodyHandle,
- first_traversal_timestamp: u64,
- ) -> bool {
- // Attempt to extract a sleeping island by traversing the
- // contact graph starting with the given rigid-body.
- if let Some(body) = bodies.get(handle) {
- if body.is_dynamic() && body.can_sleep() {
- // Perform a breadth-first search of the contact graph starting
- // with this body. We stop the search when an active body is
- // found (meaning that the island cannot sleep), or if we
- // extracted the whole island.
- // We do a breadth-first search in order to increase our chances
- // to find a non-sleeping body quickly: if this body just started
- // sleeping, chances are that a non-sleeping body is close.
- self.islands_extraction_queue.clear();
- self.islands_extraction_queue.push(handle);
- self.traversal_body_timestamps[handle.0] = self.traversal_timestamp;
- let mut i = 0;
-
- while i < self.islands_extraction_queue.len() {
- let handle = self.islands_extraction_queue[i];
-
- let continue_traversal = Self::push_contacting_bodies(
- handle,
- bodies,
- colliders,
- narrow_phase,
- &mut self.islands_extraction_queue,
- &mut self.traversal_body_timestamps,
- first_traversal_timestamp,
- self.traversal_timestamp,
- );
-
- if !continue_traversal {
- // This island cannot sleep yet.
- return false;
- }
-
- i += 1;
- }
-
- // If we reached this point, then we successfully found a sleeping island.
- for (k, handle) in self.islands_extraction_queue.iter().enumerate() {
- let body = &mut bodies[*handle];
- body.island_id = self.islands.len();
- body.island_offset = k;
- }
-
- // FIXME: recycle old islands.
- self.islands.push(Island {
- bodies: std::mem::replace(&mut self.islands_extraction_queue, Vec::new()),
- });
-
- return true;
- }
- }
-
- false
- }
-
- pub fn wake_up_island(&mut self, bodies: &mut RigidBodySet, island_id: usize) {
- if island_id == crate::INVALID_USIZE {
- return;
- }
-
- let mut island_id1 = self.active_island;
- let mut island_id2 = island_id;
-
- if island_id1 != island_id2 {
- let (mut island1, mut island2) =
- utils::get2_mut(&mut self.islands, island_id1, island_id2);
-
- // Make sure island1 points to the biggest island.
- // The typical scenario is that only a few object are awaking
- // one big island. So in this typical scenario, we actually want
- // to merge the active island into the sleeping island, and then
- // mark the sleeping island as active.
- if island2.len() > island1.len() {
- std::mem::swap(&mut island1, &mut island2);
- std::mem::swap(&mut island_id1, &mut island_id2);
- }
-
- // Now merge island2 (the smallest island) into island1 (the bigger one).
- island1.bodies.reserve(island2.len());
-
- for handle in island2.bodies.drain(..) {
- let body = &mut bodies[handle];
- body.island_id = island_id1;
- body.island_offset = island1.len();
- island1.bodies.push(handle);
- }
-
- // Islands can get big so let's save some memory.
- island2.bodies = vec![];
- self.active_island = island_id1;
- }
- }
-}