Improve the API for initializing/setting mass-properties
This commit is contained in:
@@ -241,10 +241,54 @@ impl Collider {
|
||||
pub fn density(&self) -> Option<Real> {
|
||||
match &self.mprops {
|
||||
ColliderMassProps::Density(density) => Some(*density),
|
||||
ColliderMassProps::Mass(_) => None,
|
||||
ColliderMassProps::MassProperties(_) => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Sets the uniform density of this collider.
|
||||
///
|
||||
/// This will override any previous mass-properties set by [`Self::set_density`],
|
||||
/// [`Self::set_mass`], [`Self::set_mass_properties`], [`ColliderBuilder::density`],
|
||||
/// [`ColliderBuilder::mass`], or [`ColliderBuilder::mass_properties`]
|
||||
/// for this collider.
|
||||
///
|
||||
/// The mass and angular inertia of this collider will be computed automatically based on its
|
||||
/// shape.
|
||||
pub fn set_density(&mut self, density: Real) {
|
||||
self.do_set_mass_properties(ColliderMassProps::Density(density));
|
||||
}
|
||||
|
||||
/// Sets the mass of this collider.
|
||||
///
|
||||
/// This will override any previous mass-properties set by [`Self::set_density`],
|
||||
/// [`Self::set_mass`], [`Self::set_mass_properties`], [`ColliderBuilder::density`],
|
||||
/// [`ColliderBuilder::mass`], or [`ColliderBuilder::mass_properties`]
|
||||
/// for this collider.
|
||||
///
|
||||
/// The angular inertia of this collider will be computed automatically based on its shape
|
||||
/// and this mass value.
|
||||
pub fn set_mass(&mut self, mass: Real) {
|
||||
self.do_set_mass_properties(ColliderMassProps::Mass(mass));
|
||||
}
|
||||
|
||||
/// Sets the mass properties of this collider.
|
||||
///
|
||||
/// This will override any previous mass-properties set by [`Self::set_density`],
|
||||
/// [`Self::set_mass`], [`Self::set_mass_properties`], [`ColliderBuilder::density`],
|
||||
/// [`ColliderBuilder::mass`], or [`ColliderBuilder::mass_properties`]
|
||||
/// for this collider.
|
||||
pub fn set_mass_properties(&mut self, mass_properties: MassProperties) {
|
||||
self.do_set_mass_properties(ColliderMassProps::MassProperties(Box::new(mass_properties)))
|
||||
}
|
||||
|
||||
fn do_set_mass_properties(&mut self, mprops: ColliderMassProps) {
|
||||
if mprops != self.mprops {
|
||||
self.changes |= ColliderChanges::LOCAL_MASS_PROPERTIES;
|
||||
self.mprops = mprops;
|
||||
}
|
||||
}
|
||||
|
||||
/// The geometric shape of this collider.
|
||||
pub fn shape(&self) -> &dyn Shape {
|
||||
self.shape.as_ref()
|
||||
@@ -284,10 +328,7 @@ impl Collider {
|
||||
|
||||
/// Compute the local-space mass properties of this collider.
|
||||
pub fn mass_properties(&self) -> MassProperties {
|
||||
match &self.mprops {
|
||||
ColliderMassProps::Density(density) => self.shape.mass_properties(*density),
|
||||
ColliderMassProps::MassProperties(mass_properties) => **mass_properties,
|
||||
}
|
||||
self.mprops.mass_properties(&*self.shape)
|
||||
}
|
||||
|
||||
/// The total force magnitude beyond which a contact force event can be emitted.
|
||||
@@ -303,11 +344,8 @@ impl Collider {
|
||||
pub struct ColliderBuilder {
|
||||
/// The shape of the collider to be built.
|
||||
pub shape: SharedShape,
|
||||
/// The uniform density of the collider to be built.
|
||||
pub density: Option<Real>,
|
||||
/// Overrides automatic computation of `MassProperties`.
|
||||
/// If None, it will be computed based on shape and density.
|
||||
pub mass_properties: Option<MassProperties>,
|
||||
/// Controls the way the collider’s mass-properties are computed.
|
||||
pub mass_properties: ColliderMassProps,
|
||||
/// The friction coefficient of the collider to be built.
|
||||
pub friction: Real,
|
||||
/// The rule used to combine two friction coefficients.
|
||||
@@ -341,8 +379,7 @@ impl ColliderBuilder {
|
||||
pub fn new(shape: SharedShape) -> Self {
|
||||
Self {
|
||||
shape,
|
||||
density: None,
|
||||
mass_properties: None,
|
||||
mass_properties: ColliderMassProps::default(),
|
||||
friction: Self::default_friction(),
|
||||
restitution: 0.0,
|
||||
position: Isometry::identity(),
|
||||
@@ -627,9 +664,6 @@ 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
|
||||
@@ -679,19 +713,34 @@ impl ColliderBuilder {
|
||||
|
||||
/// 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`].
|
||||
/// This will be overridden by a call to [`Self::mass`] or [`Self::mass_properties`] so it only
|
||||
/// makes sense to call either [`Self::density`] or [`Self::mass`] or [`Self::mass_properties`].
|
||||
///
|
||||
/// The mass and angular inertia of this collider will be computed automatically based on its
|
||||
/// shape.
|
||||
pub fn density(mut self, density: Real) -> Self {
|
||||
self.density = Some(density);
|
||||
self.mass_properties = ColliderMassProps::Density(density);
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the mass of the collider this builder will build.
|
||||
///
|
||||
/// This will be overridden by a call to [`Self::density`] or [`Self::mass_properties`] so it only
|
||||
/// makes sense to call either [`Self::density`] or [`Self::mass`] or [`Self::mass_properties`].
|
||||
///
|
||||
/// The angular inertia of this collider will be computed automatically based on its shape
|
||||
/// and this mass value.
|
||||
pub fn mass(mut self, mass: Real) -> Self {
|
||||
self.mass_properties = ColliderMassProps::Mass(mass);
|
||||
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`].
|
||||
/// This will be overridden by a call to [`Self::density`] or [`Self::mass`] so it only
|
||||
/// makes sense to call either [`Self::density`] or [`Self::mass`] or [`Self::mass_properties`].
|
||||
pub fn mass_properties(mut self, mass_properties: MassProperties) -> Self {
|
||||
self.mass_properties = Some(mass_properties);
|
||||
self.mass_properties = ColliderMassProps::MassProperties(Box::new(mass_properties));
|
||||
self
|
||||
}
|
||||
|
||||
@@ -745,16 +794,7 @@ impl ColliderBuilder {
|
||||
|
||||
/// Builds a new collider attached to the given rigid-body.
|
||||
pub fn build(&self) -> Collider {
|
||||
let mass_info = if let Some(mp) = self.mass_properties {
|
||||
ColliderMassProps::MassProperties(Box::new(mp))
|
||||
} else {
|
||||
let default_density = Self::default_density();
|
||||
let density = self.density.unwrap_or(default_density);
|
||||
ColliderMassProps::Density(density)
|
||||
};
|
||||
|
||||
let shape = self.shape.clone();
|
||||
let mprops = mass_info;
|
||||
let material = ColliderMaterial {
|
||||
friction: self.friction,
|
||||
restitution: self.restitution,
|
||||
@@ -779,7 +819,7 @@ impl ColliderBuilder {
|
||||
|
||||
Collider {
|
||||
shape,
|
||||
mprops,
|
||||
mprops: self.mass_properties.clone(),
|
||||
material,
|
||||
parent: None,
|
||||
changes,
|
||||
|
||||
@@ -47,21 +47,23 @@ bitflags::bitflags! {
|
||||
pub struct ColliderChanges: u32 {
|
||||
/// Flag indicating that any component of the collider has been modified.
|
||||
const MODIFIED = 1 << 0;
|
||||
/// Flag indicating that the density or mass-properties of this collider was changed.
|
||||
const LOCAL_MASS_PROPERTIES = 1 << 1; // => RigidBody local mass-properties update.
|
||||
/// Flag indicating that the `ColliderParent` component of the collider has been modified.
|
||||
const PARENT = 1 << 1; // => BF & NF updates.
|
||||
const PARENT = 1 << 2; // => BF & NF updates.
|
||||
/// Flag indicating that the `ColliderPosition` component of the collider has been modified.
|
||||
const POSITION = 1 << 2; // => BF & NF updates.
|
||||
const POSITION = 1 << 3; // => BF & NF updates.
|
||||
/// Flag indicating that the collision groups of the collider have been modified.
|
||||
const GROUPS = 1 << 3; // => NF update.
|
||||
const GROUPS = 1 << 4; // => NF update.
|
||||
/// Flag indicating that the `ColliderShape` component of the collider has been modified.
|
||||
const SHAPE = 1 << 4; // => BF & NF update. NF pair workspace invalidation.
|
||||
const SHAPE = 1 << 5; // => BF & NF update. NF pair workspace invalidation.
|
||||
/// Flag indicating that the `ColliderType` component of the collider has been modified.
|
||||
const TYPE = 1 << 5; // => NF update. NF pair invalidation.
|
||||
const TYPE = 1 << 6; // => NF update. NF pair invalidation.
|
||||
/// Flag indicating that the dominance groups of the parent of this collider have been modified.
|
||||
///
|
||||
/// This flags is automatically set by the `PhysicsPipeline` when the `RigidBodyChanges::DOMINANCE`
|
||||
/// or `RigidBodyChanges::TYPE` of the parent rigid-body of this collider is detected.
|
||||
const PARENT_EFFECTIVE_DOMINANCE = 1 << 6; // NF update.
|
||||
const PARENT_EFFECTIVE_DOMINANCE = 1 << 7; // NF update.
|
||||
}
|
||||
}
|
||||
|
||||
@@ -86,7 +88,7 @@ impl ColliderChanges {
|
||||
// bottleneck at some point in the future (which is very unlikely)
|
||||
// we could do a special-case for dominance-only change (so that
|
||||
// we only update the relative_dominance of the pre-existing contact.
|
||||
self.bits() > 1
|
||||
self.bits() > 2
|
||||
}
|
||||
}
|
||||
|
||||
@@ -134,6 +136,10 @@ pub enum ColliderMassProps {
|
||||
/// Its actual `MassProperties` are computed automatically with
|
||||
/// the help of [`SharedShape::mass_properties`].
|
||||
Density(Real),
|
||||
/// The collider is given a mass.
|
||||
///
|
||||
/// Its angular inertia will be computed automatically based on this mass.
|
||||
Mass(Real),
|
||||
/// The collider is given explicit mass-properties.
|
||||
MassProperties(Box<MassProperties>),
|
||||
}
|
||||
@@ -159,8 +165,23 @@ impl ColliderMassProps {
|
||||
/// If `self` is the `MassProperties` variant, then this returns the stored mass-properties.
|
||||
pub fn mass_properties(&self, shape: &dyn Shape) -> MassProperties {
|
||||
match self {
|
||||
Self::Density(density) => shape.mass_properties(*density),
|
||||
Self::MassProperties(mprops) => **mprops,
|
||||
ColliderMassProps::Density(density) => {
|
||||
if *density != 0.0 {
|
||||
shape.mass_properties(*density)
|
||||
} else {
|
||||
MassProperties::default()
|
||||
}
|
||||
}
|
||||
ColliderMassProps::Mass(mass) => {
|
||||
if *mass != 0.0 {
|
||||
let mut mprops = shape.mass_properties(1.0);
|
||||
mprops.set_mass(*mass, true);
|
||||
mprops
|
||||
} else {
|
||||
MassProperties::default()
|
||||
}
|
||||
}
|
||||
ColliderMassProps::MassProperties(mass_properties) => **mass_properties,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user