Replies: 4 comments 3 replies
-
just some thoughts ive been having while working on my simulation project related too mass properties one of the things thats pretty common when working with physics engines is tuning parameters like mass/velocity trying too get stable/ 'good' feeling physics. im not sure how the CustomAngularInertia component might react too changes of CustomMass or CustomCenterOfMass |
Beta Was this translation helpful? Give feedback.
-
Finally got around to reading this! This all sounds really well thought out and actionable. Some thoughts:
I have two open questions:
|
Beta Was this translation helpful? Give feedback.
-
I really like this. In particular I'm very happy about the This is not something I'd expect a physics engine to support really (too much complexity for limited gain), but one question I'd have is whether you've given any thought for being able to override the mass for a "subtree" of a collider hierarchy for a particular rigid body. I found it pretty common to have deep collider hierarchies when working with a benvy-like workflow (multiple blenvy-created scenes with colliders as children for a particular rigid body) and sometimes I'd have wished I could override the mass for some of these scenes separately. Kind of similar to overriding rigid body mass properties, but only for some part of the collider hierarchy. |
Beta Was this translation helpful? Give feedback.
-
So there have been a lot of ideas for the API, both here and on Discord, as well as many open questions: should we separate computed mass and "custom mass", should we support "additional mass", what does all of that look like, should we use enums or many smaller components, what components should be required... A lot of these designs ultimately have quite a bit of complexity and somewhat confusing semantics. I took a step back to consider simpler options, and to try and reduce the API to a minimum: Just have
Additionally, there would be a Compared to previous proposals, this would have benefits like:
This is also quite similar to Box2D, where mass properties are computed automatically when shapes are added, but you can manually set or adjust it at runtime, and use |
Beta Was this translation helpful? Give feedback.
-
Mass properties in Avian are currently inefficient and unergonomic.
Mass
andInverseMass
as well asInertia
andInverseInertia
are stored separately, even though they are tightly coupled.ColliderMassProperties
looks like a component that can be configured, even though it is automatically updated and intended as read-only.This is a proposal for overhauling how mass properties are handled in Avian.
At a high level, my proposal consists of the following:
InverseMass
andInverseInertia
. Store the inverses inMass
andAngularInertia
directly, but expose an ergonomic API that abstracts away the complexity.Component
derive fromMass
,AngularInertia
, andCenterOfMass
. Add wrappers likeReadOnlyMass
,ReadOnlyAngularInertia
, andReadOnlyCenterOfMass
to make it clear that they should not be set directly.ColliderMassProperties
toReadOnlyColliderMassProperties
, and make the fields only accessible through getters.CustomMass
,CustomAngularInertia
, andCustomCenterOfMass
components for explicitly setting mass properties for rigid bodies or colliders, also making editor workflows like Blenvy nicer.GlobalAngularInertia
component, and only update it when theRotation
is changed.I will go into a bit more detail in the following sections, along with actual code examples. Keep in mind that this is just a draft, and details may change. My plan is to implement this over multiple PRs.
Remove
InverseMass
andInverseInertia
in favor ofMass
andAngularInertia
Currently, the inverses of
Mass
andInertia
(poor name, since mass is also inertia) are cached in theInverseMass
andInverseInertia
components. They are updated automatically.These relationships are confusing and add complexity. The physics engine primarily just needs the inverse mass properties, while
Mass
andInertia
are mainly a user-facing API. In addition, when theMass
orInertia
are changed, their inverses will be out of sync until the systems responsible for updating them run.I propose storing the inverses in
Mass
andAngularInertia
directly. This is abstracted away through constructors and getters, so you don't need to deal with the inverse unless you want to.2D:
3D:
Store
Mass
,AngularInertia
, andCenterOfMass
in Read-Only ComponentsIn the previous section,
Mass
,AngularInertia
, andCenterOfMass
were still components. However, they are automatically updated by the physics engine, and are generally not intended to be modified directly. You can modify them manually, but the mass properties of colliders are always added on top. This adds a lot of complexity and has led to lots of confusion.In addition, they're not used just as components, as they are also stored in e.g.
ColliderMassProperties
.I propose removing the
Component
derive fromMass
,AngularInertia
, andCenterOfMass
, and adding read-only wrappersReadOnlyMass
,ReadOnlyAngularInertia
, andReadOnlyCenterOfMass
. The physics engine uses these internally, and manages them in the background.ColliderMassProperties
should also be renamed toReadOnlyColliderMassProperties
and properly made read-only to avoid misuse.With
Mass
,AngularInertia
, andCenterOfMass
being their own types that don't assume ECS usage, we could even have them in a general 3rd party mass property computation crate. In fact, I have that already:bevy_heavy
! We can start by having the types in Avian directly though.Now, if the mass properties are read-only, how do you configure them? See the next section!
Add
CustomMass
,CustomAngularInertia
, andCustomCenterOfMass
Currently, the only way to explicitly set the mass properties for an object is to set the
ColliderDensity
of each of its colliders to zero and to then set theMass
,Inertia
, and (optionally)CenterOfMass
manually. You can also add more mass by modifyingMass
directly, but the collider's mass properties are still added on top. This is confusing, not very flexible, and likely has bugs and weird edge cases.In the previous sections, we also made the mass properties read-only. Additionally, the internal representation (multiplicative inverse) isn't very user-friendly, which makes working with editors, inspectors, and scene workflows like Blenvy painful.
I propose fixing all of the above issues by adding
CustomMass
,CustomAngularInertia
, andCustomCenterOfMass
components. They can be used to explicitly specify mass properties. If the components don't exist, the corresponding mass properties are automatically derived from colliders by default.On a
RigidBody
entity, the components affect the entire body's mass property computation. Otherwise, each attached collider can specify its own mass properties.Make Mass Properties For Non-Dynamic Objects and Standalone Colliders Optional
Currently, mass property components are inserted automatically for all rigid bodies and colliders. However, only dynamic rigid bodies and colliders attached to them really need mass.
Mass properties should only be inserted for dynamic rigid bodies and colliders attached to them. However, if other physics entities have mass property components anyway (e.g. added manually by the user), they should probably still get updated automatically.
This will require changes to the solver to make mass optional. Eventually, we should have one-body constraints (e.g. specialized dynamic-static constraints) for optimization purposes as well, but for now, we can probably just assume default mass properties when the components are missing.
Cache World-Space Angular Inertia in
GlobalAngularInertia
(3D)In 3D, angular inertia depends on the orientation of the object. The local angular inertia tensor is stored in
ReadOnlyAngularInertia
, and the world-space version is currently computed multiple times per substep. This is expensive.The world-space angular inertia only needs to be recomputed when the local angular inertia or rotation changes. The rotation is only changed once per substep, during position/rotation integration. The world-space angular inertia should be cached in its own read-only component.
Alternatively, we could store it in
ReadOnlyAngularInertia
directly, and design the API such that the world-space version is always updated whenever the local version is changed.Extra:
EffectiveMass
andEffectiveAngularInertia
Most of the physics engine actually uses the effective mass and effective angular inertia, which take the
LockedAxes
component into account. We could cache these as well, either in their own components, or inReadOnlyMass
andReadOnlyAngularInertia
directly.The effective versions are quite cheap to compute though, so it isn't immediately clear if caching would be worth it. This needs benchmarking.
Extra: Make Mass Properties Optional Conditionally
There are some special scenarios where we could technically omit mass property components.
ReadOnlyMass
.ReadOnlyAngularInertia
.Vector::ZERO
, we could omitReadOnlyCenterOfMass
.However, I don't think it's really worth it to special-case these scenarios. It adds complexity for minimal performance gains (if any) and may be unexpected for users.
Beta Was this translation helpful? Give feedback.
All reactions