Part of the ongoing mass property rework proposed in #499.
Currently, the inverses of Mass and Inertia (poor name, since mass is also inertia) are cached in the InverseMass and InverseInertia components. They are updated automatically.
This dependency is confusing and adds complexity. The physics engine primarily just needs the inverse mass properties, while Mass and Inertia are mainly a user-facing API. In addition, when the Mass or Inertia are changed, their inverses will be out of sync until the systems responsible for updating them run. The components for the inverse and non-inverse versions should be more tightly coupled or combined to reduce complexity and lessen misuse.
In 3D, angular inertia also depends on the orientation of the object. The local angular inertia tensor is stored in Inertia, and the world-space version is currently computed multiple times per substep. This is expensive. The rotation is only changed once per substep, during position/rotation integration, so the world-space angular inertia should be cached in its own read-only component.
Solution
Remove InverseMass and InverseInertia, and instead store the inverses in Mass and AngularInertia directly. This internal representation is abstracted away through constructors and getters.
// Most derives and attributes omitted for brevity
#[derive(Component)]
pub struct Mass {
inverse: Scalar,
}
let mut mass = Mass::new(5.0);
assert_eq!(mass.value(), 5.0);
mass.set(Mass::from_inverse(0.5));
assert_eq!(mass.value(), 2.0);
assert_eq!(mass.inverse(), 0.5);
Notice how Inertia was also renamed to AngularInertia to be more explicit. Mass and AngularInertia also have a lot more helpers and documentation than before.
Secondly, in 3D, the world-space angular inertia is now cached in a GlobalAngularInertia component. It is updated after position/rotation integration and when the local angular inertia is changed.
Discussion
We might still want the non-inverse versions to be stored as well, at least for angular inertia. I'm not sure if it would be worth it though, so it would need benchmarking.
We could also consider storing the world-space angular inertia in AngularInertia directly, and design the API such that the local and global versions are always kept in sync. This would require taking a rotation in constructors though, and make the type less general-purpose, so I don't think it's worth it at this point.
We could also consider caching the effective mass and angular inertia, which takes LockedAxes into account. They are quite cheap to compute though, so I'm not sure if it would be worth it. Needs benchmarking.
Migration Guide
InverseMass and InverseInertia have been removed, and Inertia has been renamed to AngularInertia. Use the methods on Mass and AngularInertia to access the inverse versions.
Mass and AngularInertia can no longer be constructed manually. Use the constructors such as new or from_inverse instead.
ColliderMassProperties now only stores raw mass, angular_inertia, and center_of_mass values.
RigidBodyQueryItem methods effective_inv_mass and effective_world_inv_inertia have been renamed to effective_inverse_mass and effective_global_inverse_inertia.
Objective
Part of the ongoing mass property rework proposed in #499.
Currently, the inverses of
Mass
andInertia
(poor name, since mass is also inertia) are cached in theInverseMass
andInverseInertia
components. They are updated automatically.This dependency is confusing and adds 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. The components for the inverse and non-inverse versions should be more tightly coupled or combined to reduce complexity and lessen misuse.In 3D, angular inertia also depends on the orientation of the object. The local angular inertia tensor is stored in
Inertia
, and the world-space version is currently computed multiple times per substep. This is expensive. The rotation is only changed once per substep, during position/rotation integration, so the world-space angular inertia should be cached in its own read-only component.Solution
Remove
InverseMass
andInverseInertia
, and instead store the inverses inMass
andAngularInertia
directly. This internal representation is abstracted away through constructors and getters.2D:
3D:
Notice how
Inertia
was also renamed toAngularInertia
to be more explicit.Mass
andAngularInertia
also have a lot more helpers and documentation than before.Secondly, in 3D, the world-space angular inertia is now cached in a
GlobalAngularInertia
component. It is updated after position/rotation integration and when the local angular inertia is changed.Discussion
We might still want the non-inverse versions to be stored as well, at least for angular inertia. I'm not sure if it would be worth it though, so it would need benchmarking.
We could also consider storing the world-space angular inertia in
AngularInertia
directly, and design the API such that the local and global versions are always kept in sync. This would require taking a rotation in constructors though, and make the type less general-purpose, so I don't think it's worth it at this point.We could also consider caching the effective mass and angular inertia, which takes
LockedAxes
into account. They are quite cheap to compute though, so I'm not sure if it would be worth it. Needs benchmarking.Migration Guide
InverseMass
andInverseInertia
have been removed, andInertia
has been renamed toAngularInertia
. Use the methods onMass
andAngularInertia
to access the inverse versions.Mass
andAngularInertia
can no longer be constructed manually. Use the constructors such asnew
orfrom_inverse
instead.ColliderMassProperties
now only stores rawmass
,angular_inertia
, andcenter_of_mass
values.RigidBodyQueryItem
methodseffective_inv_mass
andeffective_world_inv_inertia
have been renamed toeffective_inverse_mass
andeffective_global_inverse_inertia
.