-
-
Notifications
You must be signed in to change notification settings - Fork 131
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
Mass Property Rework #574
Merged
Merged
Mass Property Rework #574
Conversation
This file contains 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
Jondolf
added
C-Enhancement
New feature or request
A-Dynamics
Relates to rigid body dynamics: motion, mass, constraint solving, joints, CCD, and so on
C-Usability
A quality-of-life improvement that makes Avian easier to use
labels
Dec 4, 2024
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-Enhancement
New feature or request
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
, andCenterOfMass
can 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.Mass
to a lower value at runtime, and then remove a collider, you could end up with negative mass.Mass
,AngularInertia
, andCenterOfMass
do nothing on child colliders.Mass
andInertia
and addGlobalAngularInertia
in 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
Mass
andComputedMass
Using 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
, andComputedCenterOfMass
components. 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
, andCenterOfMass
now 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
, orCenterOfMass
are not set for an entity, the mass properties of its collider will be used instead, if present. Overridding mass withMass
also 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
, andNoAutoCenterOfMass
marker 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
, andNoAutoCenterOfMass
marker 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
, andCenterOfMass
have user-friendly representations with public fields. 3DAngularInertia
differs 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_new
new_with_local_frame
,try_with_local_frame
from_tensor
tensor
AngularInertiaTensor
, which has further methods and operations. More on that in the next section!ComputedMass
,ComputedAngularInertia
, andComputedCenterOfMass
have even more methods in order to help work with the inverse representation efficiently.bevy_heavy
Integrationbevy_heavy
is my new mass property crate for Bevy. It providesMassProperty2d
andMassProperty3d
types, and traits for computing mass properties for all of Bevy's primitive shapes. Avian now takes advantage of this in a few ways.Collider
now implements theComputeMassProperties2d
/ComputeMassProperties3d
trait for mass property computation. Themass_properties
method returnsMassProperty2d
/MassProperty3d
instead ofColliderMassProperties
, and you can also compute mass, angular inertia, and the center of mass individually:Mass
,AngularInertia
,CenterOfMass
, andMassPropertiesBundle
now also have afrom_shape
method that takes a type implementingComputeMassProperties2d
/ComputeMassProperties3d
and 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_heavy
here.Working with 3D angular inertia and converting between different representations can be somewhat complex.
bevy_heavy
has an eigensolver for diagonalizing angular inertia tensors, and provides anAngularInertiaTensor
type 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
, andColliderDensity
now only usef32
types. This is partially to integrate better withbevy_heavy
, but also because I believef64
precision just isn't needed for these user-facing mass property types. The total computed mass properties still supportf64
however.MassPropertyHelper
Sometimes, it might be useful to compute or update mass properties for individual entities or hierarchies manually. There is now a new
MassPropertyHelper
system parameter for this, with the following methods:update_mass_properties
total_mass_properties
(descendants + local)descendants_mass_properties
local_mass_properties
The 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
, andNoAutoCenterOfMass
components. 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 theRecomputeMassProperties
sparse-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
MassPropertyHelper
to get more user-facing utilities in the future as we identify usage patterns and common tasks users need to perform.Other Changes
ColliderMassProperties
storesMassProperties2d
/MassProperties3d
instead of separate properties. This simplifies a lot of internals and provides a richer API.ColliderMassProperties
is now properly read-only, excluding setting the component directly or reinserting it.MassPropertiesSystems
system sets for mass properties, and decoupled theColliderBackendPlugin
further fromMassPropertyPlugin
.Future Work
DynamicBody
,KinematicBody
, andStaticBody
(there are many approaches we could take here).ColliderMassProperties
automatically for colliders that are attached to a (dynamic) rigid body.Migration Guide
Behavior Changes
Mass
,AngularInertia
, andCenterOfMass
are 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'sCollider
andColliderDensity
.ComputedMass
,ComputedAngularInertia
, andComputedCenterOfMass
instead ofMass
,AngularInertia
, andCenterOfMass
. The latter components are now never modified by Avian directly.NoAutoMass
,NoAutoAngularInertia
, andNoAutoCenterOfMass
marker components to the rigid body, giving you full manual control.Mass
at runtime did not affect angular inertia. Now, it is scaled accordingly, unlessNoAutoAngularInertia
is present.CenterOfMass
at spawn did nothing unless an initialMass
was specified, even if the entity had a collider that would give it mass. This has been fixed.Mass
,AngularInertia
, andCenterOfMass
did nothing on child colliders. Now, they effectively overrideColliderMassProperties
when computing the total mass properties for the rigid body.API Changes
Mass
,AngularInertia
,CenterOfMass
,ColliderDensity
, andColliderMassProperties
now always usef32
types, even with thef64
feature. Total mass properties stored inComputedMass
,ComputedAngularInertia
, andComputedCenterOfMass
still supportf64
.AngularInertia
now 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_computed
andColliderMassProperties::from_collider
have been renamed tofrom_shape
.ColliderMassProperties
now stores aMassProperties2d
/MassProperties3d
instead of separate properties.AnyCollider
must now also implement theComputeMassProperties2d
/ComputeMassProperties3d
trait instead of themass_properties
method.