Skip to content
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

Rework Mass and Inertia and add GlobalAngularInertia in 3D #500

Draft
wants to merge 11 commits into
base: main
Choose a base branch
from

Conversation

Jondolf
Copy link
Owner

@Jondolf Jondolf commented Aug 24, 2024

Objective

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);

2D:

#[derive(Component)]
pub struct AngularInertia {
    inverse: Scalar,
}

let mut angular_inertia = AngularInertia::new(5.0);
assert_eq!(angular_inertia.value(), 5.0);

angular_inertia.set(AngularInertia::from_inverse(0.5));
assert_eq!(angular_inertia.value(), 2.0);
assert_eq!(angular_inertia.inverse(), 0.5);

3D:

#[derive(Component)]
pub struct AngularInertia {
    inverse: Matrix,
}

let mut angular_inertia = AngularInertia::new(Matrix::from_diagonal(Vector::splat(2.0)));
assert_eq!(angular_inertia.tensor().diagonal(), Vector::splat(2.0));

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.


Todo

  • Add unit tests for mass property types
  • Benchmark to test if performance has improved

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.
  • RigidBodyQueryItem methods effective_inv_mass and effective_world_inv_inertia have been renamed to effective_inverse_mass and effective_global_inverse_inertia.

@Jondolf Jondolf added C-Enhancement New feature or request A-Dynamics Relates to rigid body dynamics: motion, mass, constraint solving, joints, CCD, and so on labels Aug 24, 2024
@Jondolf Jondolf added this to the 0.2 milestone Aug 24, 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
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant