diff options
| author | Sébastien Crozet <developer@crozet.re> | 2021-03-08 10:38:31 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2021-03-08 10:38:31 +0100 |
| commit | 808ea026720d61b28cefa02563ae95ee07318fc8 (patch) | |
| tree | 2291a8b8cfed7d0888a996ab0a8382daebab076f | |
| parent | beaddea6f2596dce936355940fd98ca90945cb65 (diff) | |
| parent | 0370e7e37d2ed298561d7b9aa36ed2cbe651ea9d (diff) | |
| download | rapier-808ea026720d61b28cefa02563ae95ee07318fc8.tar.gz rapier-808ea026720d61b28cefa02563ae95ee07318fc8.tar.bz2 rapier-808ea026720d61b28cefa02563ae95ee07318fc8.zip | |
Merge pull request #141 from EmbarkStudios/per-collider-mass-props
Per collider mass props
| -rw-r--r-- | src/geometry/collider.rs | 64 |
1 files changed, 49 insertions, 15 deletions
diff --git a/src/geometry/collider.rs b/src/geometry/collider.rs index b006f9e..593c53c 100644 --- a/src/geometry/collider.rs +++ b/src/geometry/collider.rs @@ -41,6 +41,14 @@ impl ColliderFlags { } } +#[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>), +} + #[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. @@ -48,7 +56,7 @@ impl ColliderFlags { /// To build a new collider, use the `ColliderBuilder` structure. pub struct Collider { shape: SharedShape, - density: Real, + mass_info: MassInfo, pub(crate) flags: ColliderFlags, pub(crate) solver_flags: SolverFlags, pub(crate) parent: RigidBodyHandle, @@ -113,9 +121,12 @@ impl Collider { self.solver_groups } - /// The density of this collider. - pub fn density(&self) -> Real { - self.density + /// 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, + } } /// The geometric shape of this collider. @@ -136,7 +147,10 @@ impl Collider { /// Compute the local-space mass properties of this collider. pub fn mass_properties(&self) -> MassProperties { - self.shape.mass_properties(self.density) + match &self.mass_info { + MassInfo::Density(density) => self.shape.mass_properties(*density), + MassInfo::MassProperties(mass_properties) => **mass_properties, + } } } @@ -146,8 +160,11 @@ impl Collider { pub struct ColliderBuilder { /// The shape of the collider to be built. pub shape: SharedShape, - /// The density of the collider to be built. + /// The uniform density of the collider to be built. density: Option<Real>, + /// Overrides automatic computation of `MassProperties`. + /// If None, it will be computed based on shape and density. + mass_properties: Option<MassProperties>, /// The friction coefficient of the collider to be built. pub friction: Real, /// The rule used to combine two friction coefficients. @@ -177,6 +194,7 @@ impl ColliderBuilder { Self { shape, density: None, + mass_properties: None, friction: Self::default_friction(), restitution: 0.0, delta: Isometry::identity(), @@ -190,12 +208,6 @@ impl ColliderBuilder { } } - /// The density of the collider being built. - pub fn get_density(&self) -> Real { - let default_density = if self.is_sensor { 0.0 } else { 1.0 }; - self.density.unwrap_or(default_density) - } - /// Initialize a new collider builder with a compound shape. pub fn compound(shapes: Vec<(Isometry<Real>, SharedShape)>) -> Self { Self::new(SharedShape::compound(shapes)) @@ -456,6 +468,9 @@ impl ColliderBuilder { } /// Sets whether or not the collider built by this builder is a sensor. + /// + /// Sensors will have a default density of zero, + /// but if you call [`Self::mass_properties`] you can assign a mass to a sensor. pub fn sensor(mut self, is_sensor: bool) -> Self { self.is_sensor = is_sensor; self @@ -492,12 +507,24 @@ impl ColliderBuilder { self } - /// Sets the density of the collider this builder will build. + /// Sets the uniform density of the collider this builder will build. + /// + /// This will be overridden by a call to [`Self::mass_properties`] so it only makes sense to call + /// either [`Self::density`] or [`Self::mass_properties`]. pub fn density(mut self, density: Real) -> Self { self.density = Some(density); self } + /// Sets the mass properties of the collider this builder will build. + /// + /// If this is set, [`Self::density`] will be ignored, so it only makes sense to call + /// either [`Self::density`] or [`Self::mass_properties`]. + pub fn mass_properties(mut self, mass_properties: MassProperties) -> Self { + self.mass_properties = Some(mass_properties); + self + } + /// Sets the initial translation of the collider to be created, /// relative to the rigid-body it is attached to. #[cfg(feature = "dim2")] @@ -540,7 +567,14 @@ impl ColliderBuilder { /// Builds a new collider attached to the given rigid-body. pub fn build(&self) -> Collider { - let density = self.get_density(); + let mass_info = if let Some(mp) = self.mass_properties { + MassInfo::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) + }; + let mut flags = ColliderFlags::empty(); flags.set(ColliderFlags::SENSOR, self.is_sensor); flags = flags @@ -554,7 +588,7 @@ impl ColliderBuilder { Collider { shape: self.shape.clone(), - density, + mass_info, friction: self.friction, restitution: self.restitution, delta: self.delta, |
