-
-
Notifications
You must be signed in to change notification settings - Fork 208
Mass Property Rework #574
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Mass Property Rework #574
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Labels
A-Dynamics
Relates to rigid body dynamics: motion, mass, constraint solving, joints, CCD, and so on
C-Feature
A new feature, making something new possible
C-Usability
A quality-of-life improvement that makes Avian easier to use
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Objective
Closes #443.
Implements the rest of #499, continuing the work done in #500 and #532.
The current mass property functionality is very limited, confusing, and footgunny.
Mass,AngularInertia, andCenterOfMasscan be added to a rigid body to specify its initial mass properties. However, the mass properties of colliders and descendants are always added on top, to the same components. From the user's perspective, the initial mass information is lost, and there is no way to fully override mass properties on spawn.Massto a lower value at runtime, and then remove a collider, you could end up with negative mass.Mass,AngularInertia, andCenterOfMassdo nothing on child colliders.MassandInertiaand addGlobalAngularInertiain 3D #500, mass and angular inertia store inverses, and 3D angular inertia in particular stores a 3x3 matrix. These representations aren't very user-friendly, and may not be ideal for scene and editor workflows.We need a mass property system that is simple, understandable, and lightweight, while being flexible enough to support more advanced use cases. Some high-level goals here are:
Solution
MassandComputedMassUsing the same component for the user-specified mass and the total mass (that takes all attached colliders into account) was problematic.
The total mass properties of rigid bodies are now stored in the new
ComputedMass,ComputedAngularInertia, andComputedCenterOfMasscomponents. By default, these are updated automatically when mass properties are changed, or when colliders are added or removed. Computed mass properties are required components forRigidBody.Mass,AngularInertia, andCenterOfMassnow instead represent the mass properties associated with a specific entity. These are optional and never modified by Avian directly. If a rigid body entity hasMass(10.0), and its child collider hasMass(5.0), their mass properties will be combined asComputedMass(15.0).If
Mass,AngularInertia, orCenterOfMassare not set for an entity, the mass properties of its collider will be used instead, if present. Overridding mass withMassalso scales angular inertia accordingly, unless it is also overriden withAngularInertia.Sometimes, you might not want child entities or colliders to contribute to the total mass properties. This can be done by adding the
NoAutoMass,NoAutoAngularInertia, andNoAutoCenterOfMassmarker components, giving you full manual control.That's pretty much it! To recap, the core API has been distilled into:
ColliderDensity.Mass,AngularInertia, andCenterOfMass.ComputedMass,ComputedAngularInertia, andComputedCenterOfMass.NoAutoMass,NoAutoAngularInertia, andNoAutoCenterOfMassmarker components.This is much more predictable and flexible than the old system.
This isn't all that has changed though. I have implemented many more improvements here.
API Improvements
Representation
Unlike the computed mass property components,
Mass,AngularInertia, andCenterOfMasshave user-friendly representations with public fields. 3DAngularInertiadiffers the most, as it now stores a principal angular inertia (Vec3) and the orientation of the local inertial frame (Quat) instead of an inertia tensor (Mat3). This is more memory efficient and more intuitive to tune by hand.Helpers and Constructors
There are now a ton more helpers and constructors, especially for 3D
AngularInertia. It has methods like:new,try_newnew_with_local_frame,try_with_local_framefrom_tensortensorAngularInertiaTensor, which has further methods and operations. More on that in the next section!ComputedMass,ComputedAngularInertia, andComputedCenterOfMasshave even more methods in order to help work with the inverse representation efficiently.bevy_heavyIntegrationbevy_heavyis my new mass property crate for Bevy. It providesMassProperty2dandMassProperty3dtypes, and traits for computing mass properties for all of Bevy's primitive shapes. Avian now takes advantage of this in a few ways.Collidernow implements theComputeMassProperties2d/ComputeMassProperties3dtrait for mass property computation. Themass_propertiesmethod returnsMassProperty2d/MassProperty3dinstead ofColliderMassProperties, and you can also compute mass, angular inertia, and the center of mass individually:Mass,AngularInertia,CenterOfMass, andMassPropertiesBundlenow also have afrom_shapemethod that takes a type implementingComputeMassProperties2d/ComputeMassProperties3dand a density. The nice part here is that you can also use Bevy's primitive shapes:Note
For now, mass properties for actual colliders still use Parry's mass computation methods, which are less flexible. If we eventually manage to replace Parry with an alternative using Bevy's geometric primitives though, we could transition to only using
bevy_heavyhere.Working with 3D angular inertia and converting between different representations can be somewhat complex.
bevy_heavyhas an eigensolver for diagonalizing angular inertia tensors, and provides anAngularInertiaTensortype to wrap this in a nice API. This is used a bit internally, and also returned by methods likeAngularInertia::tensor.As you might have noticed earlier,
Mass,AngularInertia,CenterOfMass, andColliderDensitynow only usef32types. This is partially to integrate better withbevy_heavy, but also because I believef64precision just isn't needed for these user-facing mass property types. The total computed mass properties still supportf64however.MassPropertyHelperSometimes, it might be useful to compute or update mass properties for individual entities or hierarchies manually. There is now a new
MassPropertyHelpersystem parameter for this, with the following methods:update_mass_propertiestotal_mass_properties(descendants + local)descendants_mass_propertieslocal_mass_propertiesThe old internal logic for mass property updates relied on storing previous and current collider transforms, subtracting old mass properties if present, and adding the new mass properties. This was very error-prone, probably buggy, had bookkeeping overhead, and was somewhat expensive, since it used observers to trigger recomputation.
Now, mass properties are always just recomputed "from scratch" with
update_mass_properties, which recomputes the total mass properties, taking into account descendants, colliders, and theNoAutoMass,NoAutoAngularInertia, andNoAutoCenterOfMasscomponents. Mass properties are combined usingIterator::sum, which is more efficient than the old approach of adding every collider's mass properties individually. Updates are triggered by adding theRecomputeMassPropertiessparse-set component when mass properties are detected to have changed, avoiding duplicate computation and using standard query iteration instead of observer triggers. I expect this to have much less overhead, and it at least reduces a lot of internal complexity.I expect the
MassPropertyHelperto get more user-facing utilities in the future as we identify usage patterns and common tasks users need to perform.Other Changes
ColliderMassPropertiesstoresMassProperties2d/MassProperties3dinstead of separate properties. This simplifies a lot of internals and provides a richer API.ColliderMassPropertiesis now properly read-only, excluding setting the component directly or reinserting it.MassPropertiesSystemssystem sets for mass properties, and decoupled theColliderBackendPluginfurther fromMassPropertyPlugin.Future Work
DynamicBody,KinematicBody, andStaticBody(there are many approaches we could take here).ColliderMassPropertiesautomatically for colliders that are attached to a (dynamic) rigid body.Migration Guide
Behavior Changes
Mass,AngularInertia, andCenterOfMassare now optional, and can be used to override the mass properties of an entity if present, ignoring the entity's collider. Mass properties that are not set are still computed from the entity'sColliderandColliderDensity.ComputedMass,ComputedAngularInertia, andComputedCenterOfMassinstead ofMass,AngularInertia, andCenterOfMass. The latter components are now never modified by Avian directly.NoAutoMass,NoAutoAngularInertia, andNoAutoCenterOfMassmarker components to the rigid body, giving you full manual control.Massat runtime did not affect angular inertia. Now, it is scaled accordingly, unlessNoAutoAngularInertiais present.CenterOfMassat spawn did nothing unless an initialMasswas specified, even if the entity had a collider that would give it mass. This has been fixed.Mass,AngularInertia, andCenterOfMassdid nothing on child colliders. Now, they effectively overrideColliderMassPropertieswhen computing the total mass properties for the rigid body.API Changes
Mass,AngularInertia,CenterOfMass,ColliderDensity, andColliderMassPropertiesnow always usef32types, even with thef64feature. Total mass properties stored inComputedMass,ComputedAngularInertia, andComputedCenterOfMassstill supportf64.AngularInertianow stores a principal angular inertia (Vec3) and the orientation of the local inertial frame (Quat) instead of an inertia tensor (Mat3). However, several different constructors are provided, includingfrom_tensor.MassPropertiesBundle::new_computedandColliderMassProperties::from_colliderhave been renamed tofrom_shape.ColliderMassPropertiesnow stores aMassProperties2d/MassProperties3dinstead of separate properties.AnyCollidermust now also implement theComputeMassProperties2d/ComputeMassProperties3dtrait instead of themass_propertiesmethod.