diff options
| author | Emil Ernerfeldt <emil.ernerfeldt@gmail.com> | 2021-03-02 19:55:25 +0100 |
|---|---|---|
| committer | Emil Ernerfeldt <emil.ernerfeldt@gmail.com> | 2021-03-05 11:57:08 +0100 |
| commit | 64af4252273820b0fc3e264fed4747fecff4e368 (patch) | |
| tree | 6d95fca1b03ff474821b77a15344f53204518c92 | |
| parent | e7f805aea45612abb655b3c36a133357fecfcdc4 (diff) | |
| download | rapier-64af4252273820b0fc3e264fed4747fecff4e368.tar.gz rapier-64af4252273820b0fc3e264fed4747fecff4e368.tar.bz2 rapier-64af4252273820b0fc3e264fed4747fecff4e368.zip | |
Add ability to set MassProperties for each ColliderBuilder
Fix https://github.com/dimforge/rapier/issues/132
| -rw-r--r-- | src/geometry/collider.rs | 52 |
1 files changed, 46 insertions, 6 deletions
diff --git a/src/geometry/collider.rs b/src/geometry/collider.rs index b006f9e..68caf42 100644 --- a/src/geometry/collider.rs +++ b/src/geometry/collider.rs @@ -49,6 +49,7 @@ impl ColliderFlags { pub struct Collider { shape: SharedShape, density: Real, + mass_properties: MassProperties, pub(crate) flags: ColliderFlags, pub(crate) solver_flags: SolverFlags, pub(crate) parent: RigidBodyHandle, @@ -134,9 +135,9 @@ impl Collider { // aabb1.merged(&aabb2) // } - /// Compute the local-space mass properties of this collider. - pub fn mass_properties(&self) -> MassProperties { - self.shape.mass_properties(self.density) + /// Read the local-space mass properties of this collider. + pub fn mass_properties(&self) -> &MassProperties { + &self.mass_properties } } @@ -146,8 +147,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 desnity. + 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 +181,7 @@ impl ColliderBuilder { Self { shape, density: None, + mass_properties: None, friction: Self::default_friction(), restitution: 0.0, delta: Isometry::identity(), @@ -456,6 +461,8 @@ 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 assigna a mass to a sensor. pub fn sensor(mut self, is_sensor: bool) -> Self { self.is_sensor = is_sensor; self @@ -492,12 +499,22 @@ 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 +557,21 @@ impl ColliderBuilder { /// Builds a new collider attached to the given rigid-body. pub fn build(&self) -> Collider { - let density = self.get_density(); + let (density, mass_properties); + if let Some(mp) = self.mass_properties { + mass_properties = mp; + + let volume = volume(&self.shape); + density = if volume == 0.0 || mp.inv_mass == 0.0 { + Real::INFINITY + } else { + mass(&mp) / volume + }; + } else { + density = self.get_density(); + mass_properties = self.shape.mass_properties(density); + } + let mut flags = ColliderFlags::empty(); flags.set(ColliderFlags::SENSOR, self.is_sensor); flags = flags @@ -555,6 +586,7 @@ impl ColliderBuilder { Collider { shape: self.shape.clone(), density, + mass_properties, friction: self.friction, restitution: self.restitution, delta: self.delta, @@ -570,3 +602,11 @@ impl ColliderBuilder { } } } + +fn volume(shape: &SharedShape) -> Real { + mass(&shape.mass_properties(1.0)) // TODO: add SharedShape::volume to parry +} + +fn mass(mp: &MassProperties) -> Real { + crate::utils::inv(mp.inv_mass) // TODO: add MassProperties::mass() to parry +} |
