aboutsummaryrefslogtreecommitdiff
path: root/src/geometry
diff options
context:
space:
mode:
authorSébastien Crozet <developer@crozet.re>2021-05-01 10:17:23 +0200
committerGitHub <noreply@github.com>2021-05-01 10:17:23 +0200
commita385efc5582c7918f11c01a2b6bf26a46919d3a0 (patch)
treec5b9c5e6fcb5561421e2b4b9d99f28e4c83c745e /src/geometry
parentaaf80bfa872c6f29b248cab8eb5658ab0d73cb4a (diff)
parent2dfbd9ae92c139e306afc87994adac82489f30eb (diff)
downloadrapier-a385efc5582c7918f11c01a2b6bf26a46919d3a0.tar.gz
rapier-a385efc5582c7918f11c01a2b6bf26a46919d3a0.tar.bz2
rapier-a385efc5582c7918f11c01a2b6bf26a46919d3a0.zip
Merge pull request #183 from dimforge/bundles
Make Rapier accept any kind of data storage instead of RigidBodySet/ColliderSet
Diffstat (limited to 'src/geometry')
-rw-r--r--src/geometry/broad_phase_multi_sap/broad_phase.rs235
-rw-r--r--src/geometry/broad_phase_multi_sap/sap_layer.rs5
-rw-r--r--src/geometry/collider.rs309
-rw-r--r--src/geometry/collider_components.rs270
-rw-r--r--src/geometry/collider_set.rs281
-rw-r--r--src/geometry/contact_pair.rs22
-rw-r--r--src/geometry/mod.rs19
-rw-r--r--src/geometry/narrow_phase.rs605
8 files changed, 1090 insertions, 656 deletions
diff --git a/src/geometry/broad_phase_multi_sap/broad_phase.rs b/src/geometry/broad_phase_multi_sap/broad_phase.rs
index fc79d6d..230d54d 100644
--- a/src/geometry/broad_phase_multi_sap/broad_phase.rs
+++ b/src/geometry/broad_phase_multi_sap/broad_phase.rs
@@ -1,15 +1,17 @@
use super::{
BroadPhasePairEvent, ColliderPair, SAPLayer, SAPProxies, SAPProxy, SAPProxyData, SAPRegionPool,
};
-use crate::data::pubsub::Subscription;
use crate::geometry::broad_phase_multi_sap::SAPProxyIndex;
-use crate::geometry::collider::ColliderChanges;
-use crate::geometry::{ColliderSet, RemovedCollider};
+use crate::geometry::{
+ ColliderBroadPhaseData, ColliderChanges, ColliderHandle, ColliderPosition, ColliderShape,
+};
use crate::math::Real;
use crate::utils::IndexMut2;
use parry::bounding_volume::BoundingVolume;
use parry::utils::hashmap::HashMap;
+use crate::data::{BundleSet, ComponentSet, ComponentSetMut};
+
/// A broad-phase combining a Hierarchical Grid and Sweep-and-Prune.
///
/// The basic Sweep-and-Prune (SAP) algorithm has one significant flaws:
@@ -78,8 +80,19 @@ pub struct BroadPhase {
layers: Vec<SAPLayer>,
smallest_layer: u8,
largest_layer: u8,
- removed_colliders: Option<Subscription<RemovedCollider>>,
deleted_any: bool,
+ // NOTE: we maintain this hashmap to simplify collider removal.
+ // This information is also present in the ColliderProxyId
+ // component. However if that component is removed, we need
+ // a way to access it to do some cleanup.
+ // Note that we could just remove the ColliderProxyId component
+ // altogether but that would be slow because of the need to
+ // always access this hashmap. Instead, we access this hashmap
+ // only when the collider has been added/removed.
+ // Another alternative would be to remove ColliderProxyId and
+ // just use a Coarena. But this seems like it could use too
+ // much memory.
+ colliders_proxy_ids: HashMap<ColliderHandle, SAPProxyIndex>,
#[cfg_attr(feature = "serde-serialize", serde(skip))]
region_pool: SAPRegionPool, // To avoid repeated allocations.
// We could think serializing this workspace is useless.
@@ -107,13 +120,13 @@ impl BroadPhase {
/// Create a new empty broad-phase.
pub fn new() -> Self {
BroadPhase {
- removed_colliders: None,
proxies: SAPProxies::new(),
layers: Vec::new(),
smallest_layer: 0,
largest_layer: 0,
region_pool: Vec::new(),
reporting: HashMap::default(),
+ colliders_proxy_ids: HashMap::default(),
deleted_any: false,
}
}
@@ -123,26 +136,13 @@ impl BroadPhase {
/// For each colliders marked as removed, we make their containing layer mark
/// its proxy as pre-deleted. The actual proxy removal will happen at the end
/// of the `BroadPhase::update`.
- fn handle_removed_colliders(&mut self, colliders: &mut ColliderSet) {
- // Ensure we already subscribed the collider-removed events.
- if self.removed_colliders.is_none() {
- self.removed_colliders = Some(colliders.removed_colliders.subscribe());
- }
-
- // Extract the cursor to avoid borrowing issues.
- let cursor = self.removed_colliders.take().unwrap();
-
- // Read all the collider-removed events, and remove the corresponding proxy.
- for collider in colliders.removed_colliders.read(&cursor) {
- self.predelete_proxy(collider.proxy_index);
+ fn handle_removed_colliders(&mut self, removed_colliders: &[ColliderHandle]) {
+ // For each removed collider, remove the corresponding proxy.
+ for removed in removed_colliders {
+ if let Some(proxy_id) = self.colliders_proxy_ids.get(removed).copied() {
+ self.predelete_proxy(proxy_id);
+ }
}
-
- // NOTE: We don't acknowledge the cursor just yet because we need
- // to traverse the set of removed colliders one more time after
- // the broad-phase update.
-
- // Re-insert the cursor we extracted to avoid borrowing issues.
- self.removed_colliders = Some(cursor);
}
/// Pre-deletes a proxy from this broad-phase.
@@ -173,7 +173,7 @@ impl BroadPhase {
/// This method will actually remove from the proxy list all the proxies
/// marked as deletable by `self.predelete_proxy`, making their proxy
/// handles re-usable by new proxies.
- fn complete_removals(&mut self, colliders: &mut ColliderSet) {
+ fn complete_removals(&mut self, removed_colliders: &[ColliderHandle]) {
// If there is no layer, there is nothing to remove.
if self.layers.is_empty() {
return;
@@ -215,13 +215,13 @@ impl BroadPhase {
/*
* Actually remove the colliders proxies.
*/
- let cursor = self.removed_colliders.as_ref().unwrap();
- for collider in colliders.removed_colliders.read(&cursor) {
- if collider.proxy_index != crate::INVALID_U32 {
- self.proxies.remove(collider.proxy_index);
+ for removed in removed_colliders {
+ if let Some(proxy_id) = self.colliders_proxy_ids.remove(removed) {
+ if proxy_id != crate::INVALID_U32 {
+ self.proxies.remove(proxy_id);
+ }
}
}
- colliders.removed_colliders.ack(&cursor);
}
/// Finalize the insertion of the layer identified by `layer_id`.
@@ -336,67 +336,127 @@ impl BroadPhase {
}
}
+ fn handle_modified_collider(
+ &mut self,
+ prediction_distance: Real,
+ handle: ColliderHandle,
+ proxy_index: &mut u32,
+ collider: (&ColliderPosition, &ColliderShape, &ColliderChanges),
+ ) -> bool {
+ let (co_pos, co_shape, co_changes) = collider;
+
+ let mut aabb = co_shape
+ .compute_aabb(co_pos)
+ .loosened(prediction_distance / 2.0);
+
+ aabb.mins = super::clamp_point(aabb.mins);
+ aabb.maxs = super::clamp_point(aabb.maxs);
+
+ let layer_id = if let Some(proxy) = self.proxies.get_mut(*proxy_index) {
+ let mut layer_id = proxy.layer_id;
+ proxy.aabb = aabb;
+
+ if co_changes.contains(ColliderChanges::SHAPE) {
+ // If the shape was changed, then we need to see if this proxy should be
+ // migrated to a larger layer. Indeed, if the shape was replaced by
+ // a much larger shape, we need to promote the proxy to a bigger layer
+ // to avoid the O(n²) discretization problem.
+ let new_layer_depth = super::layer_containing_aabb(&aabb);
+ if new_layer_depth > proxy.layer_depth {
+ self.layers[proxy.layer_id as usize]
+ .proper_proxy_moved_to_bigger_layer(&mut self.proxies, *proxy_index);
+
+ // We need to promote the proxy to the bigger layer.
+ layer_id = self.ensure_layer_exists(new_layer_depth);
+ self.proxies[*proxy_index].layer_id = layer_id;
+ }
+ }
+
+ layer_id
+ } else {
+ let layer_depth = super::layer_containing_aabb(&aabb);
+ let layer_id = self.ensure_layer_exists(layer_depth);
+
+ // Create the proxy.
+ let proxy = SAPProxy::collider(handle, aabb, layer_id, layer_depth);
+ *proxy_index = self.proxies.insert(proxy);
+ layer_id
+ };
+
+ let layer = &mut self.layers[layer_id as usize];
+
+ // Preupdate the collider in the layer.
+ layer.preupdate_collider(
+ *proxy_index,
+ &aabb,
+ &mut self.proxies,
+ &mut self.region_pool,
+ );
+ let need_region_propagation = !layer.created_regions.is_empty();
+
+ need_region_propagation
+ }
+
/// Updates the broad-phase, taking into account the new collider positions.
- pub fn update(
+ pub fn update<Colliders>(
&mut self,
prediction_distance: Real,
- colliders: &mut ColliderSet,
+ colliders: &mut Colliders,
+ modified_colliders: &[ColliderHandle],
+ removed_colliders: &[ColliderHandle],
events: &mut Vec<BroadPhasePairEvent>,
- ) {
+ ) where
+ Colliders: ComponentSetMut<ColliderBroadPhaseData>
+ + ComponentSet<ColliderChanges>
+ + ComponentSet<ColliderPosition>
+ + ComponentSet<ColliderShape>,
+ {
// Phase 1: pre-delete the collisions that have been deleted.
- self.handle_removed_colliders(colliders);
+ self.handle_removed_colliders(removed_colliders);
let mut need_region_propagation = false;
// Phase 2: pre-delete the collisions that have been deleted.
- colliders.foreach_modified_colliders_mut_internal(|handle, collider| {
- if !collider.changes.needs_broad_phase_update() {
- return;
- }
-
- let mut aabb = collider.compute_aabb().loosened(prediction_distance / 2.0);
- aabb.mins = super::clamp_point(aabb.mins);
- aabb.maxs = super::clamp_point(aabb.maxs);
-
- let layer_id = if let Some(proxy) = self.proxies.get_mut(collider.proxy_index) {
- let mut layer_id = proxy.layer_id;
- proxy.aabb = aabb;
-
- if collider.changes.contains(ColliderChanges::SHAPE) {
- // If the shape was changed, then we need to see if this proxy should be
- // migrated to a larger layer. Indeed, if the shape was replaced by
- // a much larger shape, we need to promote the proxy to a bigger layer
- // to avoid the O(n²) discretization problem.
- let new_layer_depth = super::layer_containing_aabb(&aabb);
- if new_layer_depth > proxy.layer_depth {
- self.layers[proxy.layer_id as usize].proper_proxy_moved_to_bigger_layer(
- &mut self.proxies,
- collider.proxy_index,
- );
-
- // We need to promote the proxy to the bigger layer.
- layer_id = self.ensure_layer_exists(new_layer_depth);
- self.proxies[collider.proxy_index].layer_id = layer_id;
- }
+ for handle in modified_colliders {
+ // NOTE: we use `get` because the collider may no longer
+ // exist if it has been removed.
+ let co_changes: Option<&ColliderChanges> = colliders.get(handle.0);
+
+ if let Some(co_changes) = co_changes {
+ let (co_bf_data, co_pos, co_shape): (
+ &ColliderBroadPhaseData,
+ &ColliderPosition,
+ &ColliderShape,
+ ) = colliders.index_bundle(handle.0);
+
+ if !co_changes.needs_broad_phase_update() {
+ return;
+ }
+ let mut new_proxy_id = co_bf_data.proxy_index;
+
+ if self.handle_modified_collider(
+ prediction_distance,
+ *handle,
+ &mut new_proxy_id,
+ (co_pos, co_shape, co_changes),
+ ) {
+ need_region_propagation = true;
}
- layer_id
- } else {
- let layer_depth = super::layer_containing_aabb(&aabb);
- let layer_id = self.ensure_layer_exists(layer_depth);
-
- // Create the proxy.
- let proxy = SAPProxy::collider(handle, aabb, layer_id, layer_depth);
- collider.proxy_index = self.proxies.insert(proxy);
- layer_id
- };
-
- let layer = &mut self.layers[layer_id as usize];
+ if co_bf_data.proxy_index != new_proxy_id {
+ self.colliders_proxy_ids.insert(*handle, new_proxy_id);
- // Preupdate the collider in the layer.
- layer.preupdate_collider(collider, &aabb, &mut self.proxies, &mut self.region_pool);
- need_region_propagation = need_region_propagation || !layer.created_regions.is_empty();
- });
+ // Make sure we have the new proxy index in case
+ // the collider was added for the first time.
+ colliders.set_internal(
+ handle.0,
+ ColliderBroadPhaseData {
+ proxy_index: new_proxy_id,
+ },
+ );
+ }
+ }
+ }
// Phase 3: bottom-up pass to propagate new regions from smaller layers to larger layers.
if need_region_propagation {
@@ -408,7 +468,7 @@ impl BroadPhase {
// Phase 5: bottom-up pass to remove proxies, and propagate region removed from smaller
// layers to possible remove regions from larger layers that would become empty that way.
- self.complete_removals(colliders);
+ self.complete_removals(removed_colliders);
}
/// Propagate regions from the smallest layers up to the larger layers.
@@ -523,7 +583,7 @@ impl BroadPhase {
#[cfg(test)]
mod test {
- use crate::dynamics::{JointSet, RigidBodyBuilder, RigidBodySet};
+ use crate::dynamics::{IslandManager, JointSet, RigidBodyBuilder, RigidBodySet};
use crate::geometry::{BroadPhase, ColliderBuilder, ColliderSet};
#[test]
@@ -532,25 +592,26 @@ mod test {
let mut bodies = RigidBodySet::new();
let mut colliders = ColliderSet::new();
let mut joints = JointSet::new();
+ let mut islands = IslandManager::new();
let rb = RigidBodyBuilder::new_dynamic().build();
let co = ColliderBuilder::ball(0.5).build();
let hrb = bodies.insert(rb);
- colliders.insert(co, hrb, &mut bodies);
+ let coh = colliders.insert(co, hrb, &mut bodies);
let mut events = Vec::new();
- broad_phase.update(0.0, &mut colliders, &mut events);
+ broad_phase.update(0.0, &mut colliders, &[coh], &[], &mut events);
- bodies.remove(hrb, &mut colliders, &mut joints);
- broad_phase.update(0.0, &mut colliders, &mut events);
+ bodies.remove(hrb, &mut islands, &mut colliders, &mut joints);
+ broad_phase.update(0.0, &mut colliders, &[], &[coh], &mut events);
// Create another body.
let rb = RigidBodyBuilder::new_dynamic().build();
let co = ColliderBuilder::ball(0.5).build();
let hrb = bodies.insert(rb);
- colliders.insert(co, hrb, &mut bodies);
+ let coh = colliders.insert(co, hrb, &mut bodies);
// Make sure the proxy handles is recycled properly.
- broad_phase.update(0.0, &mut colliders, &mut events);
+ broad_phase.update(0.0, &mut colliders, &[coh], &[], &mut events);
}
}
diff --git a/src/geometry/broad_phase_multi_sap/sap_layer.rs b/src/geometry/broad_phase_multi_sap/sap_layer.rs
index 9a9c296..e4a9f42 100644
--- a/src/geometry/broad_phase_multi_sap/sap_layer.rs
+++ b/src/geometry/broad_phase_multi_sap/sap_layer.rs
@@ -1,6 +1,6 @@
use super::{SAPProxies, SAPProxy, SAPRegion, SAPRegionPool};
use crate::geometry::broad_phase_multi_sap::DELETED_AABB_VALUE;
-use crate::geometry::{Collider, SAPProxyIndex, AABB};
+use crate::geometry::{SAPProxyIndex, AABB};
use crate::math::{Point, Real};
use parry::utils::hashmap::{Entry, HashMap};
@@ -213,12 +213,11 @@ impl SAPLayer {
pub fn preupdate_collider(
&mut self,
- collider: &Collider,
+ proxy_id: u32,
aabb: &AABB,
proxies: &mut SAPProxies,
pool: &mut SAPRegionPool,
) {
- let proxy_id = collider.proxy_index;
let start = super::point_key(aabb.mins, self.region_width);
let end = super::point_key(aabb.maxs, self.region_width);
diff --git a/src/geometry/collider.rs b/src/geometry/collider.rs
index 2b08a96..08295c1 100644
--- a/src/geometry/collider.rs
+++ b/src/geometry/collider.rs
@@ -1,231 +1,160 @@
use crate::dynamics::{CoefficientCombineRule, MassProperties, RigidBodyHandle};
-use crate::geometry::{InteractionGroups, SAPProxyIndex, SharedShape, SolverFlags};
+use crate::geometry::{
+ ColliderBroadPhaseData, ColliderChanges, ColliderGroups, ColliderMassProperties,
+ ColliderMaterial, ColliderParent, ColliderPosition, ColliderShape, ColliderType,
+ InteractionGroups, SharedShape, SolverFlags,
+};
use crate::math::{AngVector, Isometry, Point, Real, Rotation, Vector, DIM};
use crate::parry::transformation::vhacd::VHACDParameters;
use na::Unit;
-use parry::bounding_volume::{BoundingVolume, AABB};
+use parry::bounding_volume::AABB;
use parry::shape::Shape;
-bitflags::bitflags! {
- #[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
- /// Flags affecting the behavior of the constraints solver for a given contact manifold.
- pub(crate) struct ColliderFlags: u8 {
- const SENSOR = 1 << 0;
- const FRICTION_COMBINE_RULE_01 = 1 << 1;
- const FRICTION_COMBINE_RULE_10 = 1 << 2;
- const RESTITUTION_COMBINE_RULE_01 = 1 << 3;
- const RESTITUTION_COMBINE_RULE_10 = 1 << 4;
- }
-}
-
-impl ColliderFlags {
- pub fn is_sensor(self) -> bool {
- self.contains(ColliderFlags::SENSOR)
- }
-
- pub fn friction_combine_rule_value(self) -> u8 {
- (self.bits & 0b0000_0110) >> 1
- }
-
- pub fn restitution_combine_rule_value(self) -> u8 {
- (self.bits & 0b0001_1000) >> 3
- }
-
- pub fn with_friction_combine_rule(mut self, rule: CoefficientCombineRule) -> Self {
- self.bits = (self.bits & !0b0000_0110) | ((rule as u8) << 1);
- self
- }
-
- pub fn with_restitution_combine_rule(mut self, rule: CoefficientCombineRule) -> Self {
- self.bits = (self.bits & !0b0001_1000) | ((rule as u8) << 3);
- self
- }
-}
-
-#[derive(Clone)]
-#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
-enum MassInfo {
- /// `MassProperties` are computed with the help of [`SharedShape::mass_properties`].
- Density(Real),
- MassProperties(Box<MassProperties>),
-}
-
-bitflags::bitflags! {
- #[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
- /// Flags describing how the collider has been modified by the user.
- pub(crate) struct ColliderChanges: u32 {
- const MODIFIED = 1 << 0;
- const POSITION_WRT_PARENT = 1 << 1; // => BF & NF updates.
- const POSITION = 1 << 2; // => BF & NF updates.
- const COLLISION_GROUPS = 1 << 3; // => NF update.
- const SOLVER_GROUPS = 1 << 4; // => NF update.
- const SHAPE = 1 << 5; // => BF & NF update. NF pair workspace invalidation.
- const SENSOR = 1 << 6; // => NF update. NF pair invalidation.
- }
-}
-
-impl ColliderChanges {
- pub fn needs_broad_phase_update(self) -> bool {
- self.intersects(
- ColliderChanges::POSITION_WRT_PARENT
- | ColliderChanges::POSITION
- | ColliderChanges::SHAPE,
- )
- }
-
- pub fn needs_narrow_phase_update(self) -> bool {
- self.bits() > 1
- }
-}
-
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
#[derive(Clone)]
/// A geometric entity that can be attached to a body so it can be affected by contacts and proximity queries.
///
/// To build a new collider, use the `ColliderBuilder` structure.
pub struct Collider {
- shape: SharedShape,
- mass_info: MassInfo,
- pub(crate) flags: ColliderFlags,
- pub(crate) solver_flags: SolverFlags,
- pub(crate) changes: ColliderChanges,
- pub(crate) parent: RigidBodyHandle,
- pub(crate) delta: Isometry<Real>,
- pub(crate) position: Isometry<Real>,
- /// The friction coefficient of this collider.
- pub friction: Real,
- /// The restitution coefficient of this collider.
- pub restitution: Real,
- pub(crate) collision_groups: InteractionGroups,
- pub(crate) solver_groups: InteractionGroups,
- pub(crate) proxy_index: SAPProxyIndex,
+ pub(crate) co_type: ColliderType,
+ pub(crate) co_shape: ColliderShape,
+ pub(crate) co_mprops: ColliderMassProperties,
+ pub(crate) co_changes: ColliderChanges,
+ pub(crate) co_parent: ColliderParent,
+ pub(crate) co_pos: ColliderPosition,
+ pub(crate) co_material: ColliderMaterial,
+ pub(crate) co_groups: ColliderGroups,
+ pub(crate) co_bf_data: ColliderBroadPhaseData,
/// User-defined data associated to this rigid-body.
pub user_data: u128,
}
impl Collider {
pub(crate) fn reset_internal_references(&mut self) {
- self.parent = RigidBodyHandle::invalid();
- self.proxy_index = crate::INVALID_U32;
- self.changes = ColliderChanges::empty();
+ self.co_parent.handle = RigidBodyHandle::invalid();
+ self.co_bf_data.proxy_index = crate::INVALID_U32;
+ self.co_changes = ColliderChanges::all();
}
/// The rigid body this collider is attached to.
pub fn parent(&self) -> RigidBodyHandle {
- self.parent
+ self.co_parent.handle
}
/// Is this collider a sensor?
pub fn is_sensor(&self) -> bool {
- self.flags.is_sensor()
+ self.co_type.is_sensor()
}
/// The combine rule used by this collider to combine its friction
/// coefficient with the friction coefficient of the other collider it
/// is in contact with.
pub fn friction_combine_rule(&self) -> CoefficientCombineRule {
- CoefficientCombineRule::from_value(self.flags.friction_combine_rule_value())
+ self.co_material.friction_combine_rule
}
/// Sets the combine rule used by this collider to combine its friction
/// coefficient with the friction coefficient of the other collider it
/// is in contact with.
pub fn set_friction_combine_rule(&mut self, rule: CoefficientCombineRule) {
- self.flags = self.flags.with_friction_combine_rule(rule);
+ self.co_material.friction_combine_rule = rule;
}
/// The combine rule used by this collider to combine its restitution
/// coefficient with the restitution coefficient of the other collider it
/// is in contact with.
pub fn restitution_combine_rule(&self) -> CoefficientCombineRule {
- CoefficientCombineRule::from_value(self.flags.restitution_combine_rule_value())
+ self.co_material.restitution_combine_rule
}
/// Sets the combine rule used by this collider to combine its restitution
/// coefficient with the restitution coefficient of the other collider it
/// is in contact with.
pub fn set_restitution_combine_rule(&mut self, rule: CoefficientCombineRule) {
- self.flags = self.flags.with_restitution_combine_rule(rule)
+ self.co_material.restitution_combine_rule = rule;
}
/// Sets whether or not this is a sensor collider.
pub fn set_sensor(&mut self, is_sensor: bool) {
if is_sensor != self.is_sensor() {
- self.changes.insert(ColliderChanges::SENSOR);
- self.flags.set(ColliderFlags::SENSOR, is_sensor);
+ self.co_changes.insert(ColliderChanges::TYPE);
+ self.co_type = if is_sensor {
+ ColliderType::Sensor
+ } else {
+ ColliderType::Solid
+ };
}
}
#[doc(hidden)]
pub fn set_position_debug(&mut self, position: Isometry<Real>) {
- self.position = position;
+ self.co_pos.0 = position;
}
/// The position of this collider expressed in the local-space of the rigid-body it is attached to.
#[deprecated(note = "use `.position_wrt_parent()` instead.")]
pub fn delta(&self) -> &Isometry<Real> {
- &self.delta
+ &self.co_parent.pos_wrt_parent
}
/// The world-space position of this collider.
pub fn position(&self) -> &Isometry<Real> {
- &self.position
- }
-
- /// Sets the position of this collider wrt. its parent rigid-body.
- pub(crate) fn set_position(&mut self, position: Isometry<Real>) {
- self.changes.insert(ColliderChanges::POSITION);
- self.position = position;
+ &self.co_pos
}
/// The position of this collider wrt the body it is attached to.
pub fn position_wrt_parent(&self) -> &Isometry<Real> {
- &self.delta
+ &self.co_parent.pos_wrt_parent
}
/// Sets the position of this collider wrt. its parent rigid-body.
pub fn set_position_wrt_parent(&mut self, position: Isometry<Real>) {
- self.changes.insert(ColliderChanges::POSITION_WRT_PARENT);
- self.delta = position;
+ self.co_changes.insert(ColliderChanges::PARENT);
+ self.co_parent.pos_wrt_parent = position;
}
/// The collision groups used by this collider.
pub fn collision_groups(&self) -> InteractionGroups {
- self.collision_groups
+ self.co_groups.collision_groups
}
/// Sets the collision groups of this collider.
pub fn set_collision_groups(&mut self, groups: InteractionGroups) {
- if self.collision_groups != groups {
- self.changes.insert(ColliderChanges::COLLISION_GROUPS);
- self.collision_groups = groups;
+ if self.co_groups.collision_groups != groups {
+ self.co_changes.insert(ColliderChanges::GROUPS);
+ self.co_groups.collision_groups = groups;
}
}
/// The solver groups used by this collider.
pub fn solver_groups(&self) -> InteractionGroups {
- self.solver_groups
+ self.co_groups.solver_groups
}
/// Sets the solver groups of this collider.
pub fn set_solver_groups(&mut self, groups: InteractionGroups) {
- if self.solver_groups != groups {
- self.changes.insert(ColliderChanges::SOLVER_GROUPS);
- self.solver_groups = groups;
+ if self.co_groups.solver_groups != groups {
+ self.co_changes.insert(ColliderChanges::GROUPS);
+ self.co_groups.solver_groups = groups;
}
}
+ /// The material (friction and restitution properties) of this collider.
+ pub fn material(&self) -> &ColliderMaterial {
+ &self.co_material
+ }
+
/// The density of this collider, if set.
pub fn density(&self) -> Option<Real> {
- match &self.mass_info {
- MassInfo::Density(density) => Some(*density),
- MassInfo::MassProperties(_) => None,
+ match &self.co_mprops {
+ ColliderMassProperties::Density(density) => Some(*density),
+ ColliderMassProperties::MassProperties(_) => None,
}
}
/// The geometric shape of this collider.
pub fn shape(&self) -> &dyn Shape {
- &*self.shape.0
+ self.co_shape.as_ref()
}
/// A mutable reference to the geometric shape of this collider.
@@ -234,33 +163,33 @@ impl Collider {
/// cloned first so that `self` contains a unique copy of that
/// shape that you can modify.
pub fn shape_mut(&mut self) -> &mut dyn Shape {
- self.changes.insert(ColliderChanges::SHAPE);
- self.shape.make_mut()
+ self.co_changes.insert(ColliderChanges::SHAPE);
+ self.co_shape.make_mut()
}
/// Sets the shape of this collider.
pub fn set_shape(&mut self, shape: SharedShape) {
- self.changes.insert(ColliderChanges::SHAPE);
- self.shape = shape;
+ self.co_changes.insert(ColliderChanges::SHAPE);
+ self.co_shape = shape;
}
/// Compute the axis-aligned bounding box of this collider.
pub fn compute_aabb(&self) -> AABB {
- self.shape.compute_aabb(&self.position)
+ self.co_shape.compute_aabb(&self.co_pos)
}
- /// Compute the axis-aligned bounding box of this collider.
+ /// Compute the axis-aligned bounding box of this collider moving from its current position
+ /// to the given `next_position`
pub fn compute_swept_aabb(&self, next_position: &Isometry<Real>) -> AABB {
- let aabb1 = self.shape.compute_aabb(&self.position);
- let aabb2 = self.shape.compute_aabb(next_position);
- aabb1.merged(&aabb2)
+ self.co_shape
+ .compute_swept_aabb(&self.co_pos, next_position)
}
/// Compute the local-space mass properties of this collider.
pub fn mass_properties(&self) -> MassProperties {
- match &self.mass_info {
- MassInfo::Density(density) => self.shape.mass_properties(*density),
- MassInfo::MassProperties(mass_properties) => **mass_properties,
+ match &self.co_mprops {
+ ColliderMassProperties::Density(density) => self.co_shape.mass_properties(*density),
+ ColliderMassProperties::MassProperties(mass_properties) => **mass_properties,
}
}
}
@@ -272,10 +201,10 @@ pub struct ColliderBuilder {
/// The shape of the collider to be built.
pub shape: SharedShape,
/// The uniform density of the collider to be built.
- density: Option<Real>,
+ pub density: Option<Real>,
/// Overrides automatic computation of `MassProperties`.
/// If None, it will be computed based on shape and density.
- mass_properties: Option<MassProperties>,
+ pub mass_properties: Option<MassProperties>,
/// The friction coefficient of the collider to be built.
pub friction: Real,
/// The rule used to combine two friction coefficients.
@@ -285,7 +214,7 @@ pub struct ColliderBuilder {
/// The rule used to combine two restitution coefficients.
pub restitution_combine_rule: CoefficientCombineRule,
/// The position of this collider relative to the local frame of the rigid-body it is attached to.
- pub delta: Isometry<Real>,
+ pub pos_wrt_parent: Isometry<Real>,
/// Is this collider a sensor?
pub is_sensor: bool,
/// Do we have to always call the contact modifier
@@ -308,7 +237,7 @@ impl ColliderBuilder {
mass_properties: None,
friction: Self::default_friction(),
restitution: 0.0,
- delta: Isometry::identity(),
+ pos_wrt_parent: Isometry::identity(),
is_sensor: false,
user_data: 0,
collision_groups: InteractionGroups::all(),
@@ -646,8 +575,8 @@ impl ColliderBuilder {
/// relative to the rigid-body it is attached to.
#[cfg(feature = "dim2")]
pub fn translation(mut self, x: Real, y: Real) -> Self {
- self.delta.translation.x = x;
- self.delta.translation.y = y;
+ self.pos_wrt_parent.translation.x = x;
+ self.pos_wrt_parent.translation.y = y;
self
}
@@ -655,23 +584,23 @@ impl ColliderBuilder {
/// relative to the rigid-body it is attached to.
#[cfg(feature = "dim3")]
pub fn translation(mut self, x: Real, y: Real, z: Real) -> Self {
- self.delta.translation.x = x;
- self.delta.translation.y = y;
- self.delta.translation.z = z;
+ self.pos_wrt_parent.translation.x = x;
+ self.pos_wrt_parent.translation.y = y;
+ self.pos_wrt_parent.translation.z = z;
self
}
/// Sets the initial orientation of the collider to be created,
/// relative to the rigid-body it is attached to.
pub fn rotation(mut self, angle: AngVector<Real>) -> Self {
- self.delta.rotation = Rotation::new(angle);
+ self.pos_wrt_parent.rotation = Rotation::new(angle);
self
}
/// Sets the initial position (translation and orientation) of the collider to be created,
/// relative to the rigid-body it is attached to.
pub fn position_wrt_parent(mut self, pos: Isometry<Real>) -> Self {
- self.delta = pos;
+ self.pos_wrt_parent = pos;
self
}
@@ -679,53 +608,97 @@ impl ColliderBuilder {
/// relative to the rigid-body it is attached to.
#[deprecated(note = "Use `.position_wrt_parent` instead.")]
pub fn position(mut self, pos: Isometry<Real>) -> Self {
- self.delta = pos;
+ self.pos_wrt_parent = pos;
self
}
/// Set the position of this collider in the local-space of the rigid-body it is attached to.
- #[deprecated(note = "Use `.position` instead.")]
+ #[deprecated(note = "Use `.position_wrt_parent` instead.")]
pub fn delta(mut self, delta: Isometry<Real>) -> Self {
- self.delta = delta;
+ self.pos_wrt_parent = delta;
self
}
/// Builds a new collider attached to the given rigid-body.
pub fn build(&self) -> Collider {
+ let (co_changes, co_pos, co_bf_data, co_shape, co_type, co_groups, co_material, co_mprops) =
+ self.components();
+ let co_parent = ColliderParent {
+ pos_wrt_parent: co_pos.0,
+ handle: RigidBodyHandle::invalid(),
+ };
+ Collider {
+ co_shape,
+ co_mprops,
+ co_material,
+ co_parent,
+ co_changes,
+ co_pos,
+ co_bf_data,
+ co_groups,
+ co_type,
+ user_data: self.user_data,
+ }
+ }
+
+ /// Builds all the components required by a collider.
+ pub fn components(
+ &self,
+ ) -> (
+ ColliderChanges,
+ ColliderPosition,
+ ColliderBroadPhaseData,
+ ColliderShape,
+ ColliderType,
+ ColliderGroups,
+ ColliderMaterial,
+ ColliderMassProperties,
+ ) {
let mass_info = if let Some(mp) = self.mass_properties {
- MassInfo::MassProperties(Box::new(mp))
+ ColliderMassProperties::MassProperties(Box::new(mp))
} else {
let default_density = if self.is_sensor { 0.0 } else { 1.0 };
let density = self.density.unwrap_or(default_density);
- MassInfo::Density(density)
+ ColliderMassProperties::Density(density)
};