1#![cfg_attr(feature = "2d", doc = "# use avian2d::prelude::*;")]
42#![cfg_attr(feature = "3d", doc = "# use avian3d::prelude::*;")]
43#![cfg_attr(feature = "2d", doc = "# use avian2d::prelude::*;")]
60#![cfg_attr(feature = "3d", doc = "# use avian3d::prelude::*;")]
61#![cfg_attr(feature = "2d", doc = " CenterOfMass::new(0.0, -0.5),")]
70#![cfg_attr(feature = "3d", doc = " CenterOfMass::new(0.0, -0.5, 0.0),")]
71#![cfg_attr(feature = "2d", doc = "# use avian2d::prelude::*;")]
80#![cfg_attr(feature = "3d", doc = "# use avian3d::prelude::*;")]
81#![cfg_attr(
86 feature = "2d",
87 doc = "// Total center of mass: (10.0 * [0.0, -0.5] + 5.0 * [0.0, 4.0]) / (10.0 + 5.0) = [0.0, 1.0]"
88)]
89#![cfg_attr(
90 feature = "3d",
91 doc = "// Total center of mass: (10.0 * [0.0, -0.5, 0.0] + 5.0 * [0.0, 4.0, 0.0]) / (10.0 + 5.0) = [0.0, 1.0, 0.0]"
92)]
93#![cfg_attr(feature = "2d", doc = " CenterOfMass::new(0.0, -0.5),")]
98#![cfg_attr(feature = "3d", doc = " CenterOfMass::new(0.0, -0.5, 0.0),")]
99#![cfg_attr(feature = "2d", doc = " Collider::circle(1.0),")]
103#![cfg_attr(feature = "3d", doc = " Collider::sphere(1.0),")]
104#![cfg_attr(feature = "2d", doc = "# use avian2d::prelude::*;")]
115#![cfg_attr(feature = "3d", doc = "# use avian3d::prelude::*;")]
116#![cfg_attr(feature = "2d", doc = "// Total center of mass: [0.0, -0.5]")]
121#![cfg_attr(feature = "3d", doc = "// Total center of mass: [0.0, -0.5, 0.0]")]
122#![cfg_attr(feature = "2d", doc = " CenterOfMass::new(0.0, -0.5),")]
127#![cfg_attr(feature = "3d", doc = " CenterOfMass::new(0.0, -0.5, 0.0),")]
128#![cfg_attr(feature = "2d", doc = " Collider::circle(1.0),")]
134#![cfg_attr(feature = "3d", doc = " Collider::sphere(1.0),")]
135#![cfg_attr(feature = "2d", doc = "# use avian2d::prelude::*;")]
148#![cfg_attr(feature = "3d", doc = "# use avian3d::prelude::*;")]
149#![cfg_attr(feature = "2d", doc = "# use avian2d::prelude::*;")]
168#![cfg_attr(feature = "3d", doc = "# use avian3d::prelude::*;")]
169#![cfg_attr(feature = "2d", doc = "let shape = Collider::circle(0.5);")]
174#![cfg_attr(feature = "3d", doc = "let shape = Collider::sphere(0.5);")]
175#![cfg_attr(feature = "2d", doc = "let shape = Circle::new(0.5);")]
184#![cfg_attr(feature = "3d", doc = "let shape = Sphere::new(0.5);")]
185use crate::{prelude::*, prepare::PrepareSet};
200#[cfg(feature = "3d")]
201use bevy::ecs::query::QueryFilter;
202use bevy::{
203 ecs::{intern::Interned, schedule::ScheduleLabel},
204 prelude::*,
205};
206
207pub mod components;
208use components::RecomputeMassProperties;
209
210mod system_param;
211pub use system_param::MassPropertyHelper;
212
213pub use bevy_heavy;
215
216#[cfg(feature = "2d")]
217pub(crate) use bevy_heavy::{
218 ComputeMassProperties2d as ComputeMassProperties, MassProperties2d as MassProperties,
219};
220#[cfg(feature = "3d")]
221pub(crate) use bevy_heavy::{
222 ComputeMassProperties3d as ComputeMassProperties, MassProperties3d as MassProperties,
223};
224
225pub trait MassPropertiesExt {
227 fn to_bundle(&self) -> MassPropertiesBundle;
230}
231
232impl MassPropertiesExt for MassProperties {
233 fn to_bundle(&self) -> MassPropertiesBundle {
234 #[cfg(feature = "2d")]
235 let angular_inertia = AngularInertia(self.angular_inertia);
236 #[cfg(feature = "3d")]
237 let angular_inertia = AngularInertia::new_with_local_frame(
238 self.principal_angular_inertia.f32(),
239 self.local_inertial_frame.f32(),
240 );
241
242 MassPropertiesBundle {
243 mass: Mass(self.mass),
244 angular_inertia,
245 center_of_mass: CenterOfMass(self.center_of_mass),
246 }
247 }
248}
249
250pub struct MassPropertyPlugin {
258 schedule: Interned<dyn ScheduleLabel>,
259}
260
261impl MassPropertyPlugin {
262 pub fn new(schedule: impl ScheduleLabel) -> Self {
266 Self {
267 schedule: schedule.intern(),
268 }
269 }
270}
271
272impl Default for MassPropertyPlugin {
273 fn default() -> Self {
274 Self::new(FixedPostUpdate)
275 }
276}
277
278impl Plugin for MassPropertyPlugin {
279 fn build(&self, app: &mut App) {
280 app.register_type::<(
281 Mass,
282 AngularInertia,
283 CenterOfMass,
284 ComputedMass,
285 ComputedAngularInertia,
286 ComputedCenterOfMass,
287 ColliderDensity,
288 ColliderMassProperties,
289 NoAutoMass,
290 NoAutoAngularInertia,
291 NoAutoCenterOfMass,
292 )>();
293
294 app.register_required_components::<RigidBody, RecomputeMassProperties>();
296
297 app.configure_sets(
299 self.schedule,
300 (
301 MassPropertySystems::UpdateColliderMassProperties,
302 MassPropertySystems::QueueRecomputation,
303 MassPropertySystems::UpdateComputedMassProperties,
304 )
305 .chain()
306 .in_set(PrepareSet::Finalize),
307 );
308
309 app.add_systems(
311 self.schedule,
312 (
313 queue_mass_recomputation_on_mass_change,
314 queue_mass_recomputation_on_collider_mass_change,
315 )
316 .in_set(MassPropertySystems::QueueRecomputation),
317 );
318
319 app.add_systems(
321 self.schedule,
322 (
323 update_mass_properties,
324 #[cfg(feature = "3d")]
325 update_global_angular_inertia::<Added<RigidBody>>,
326 warn_missing_mass,
327 )
328 .chain()
329 .in_set(MassPropertySystems::UpdateComputedMassProperties),
330 );
331 }
332}
333
334#[derive(SystemSet, Clone, Copy, Debug, PartialEq, Eq, Hash)]
336pub enum MassPropertySystems {
337 UpdateColliderMassProperties,
339 QueueRecomputation,
341 UpdateComputedMassProperties,
344}
345
346pub type WithComputedMassProperty = Or<(
348 With<ComputedMass>,
349 With<ComputedAngularInertia>,
350 With<ComputedCenterOfMass>,
351)>;
352
353pub type MassPropertyChanged = Or<(
355 Changed<Mass>,
356 Changed<AngularInertia>,
357 Changed<CenterOfMass>,
358)>;
359
360fn queue_mass_recomputation_on_mass_change(
366 mut commands: Commands,
367 mut query: Query<
368 Entity,
369 (
370 WithComputedMassProperty,
371 Without<ColliderOf>,
372 MassPropertyChanged,
373 ),
374 >,
375) {
376 for entity in &mut query {
377 commands.entity(entity).insert(RecomputeMassProperties);
378 }
379}
380
381fn queue_mass_recomputation_on_collider_mass_change(
384 mut commands: Commands,
385 mut query: Query<
386 &ColliderOf,
387 Or<(
388 Changed<ColliderMassProperties>,
389 Changed<ColliderTransform>,
390 MassPropertyChanged,
391 )>,
392 >,
393) {
394 for &ColliderOf { body } in &mut query {
395 if let Ok(mut entity_commands) = commands.get_entity(body) {
396 entity_commands.insert(RecomputeMassProperties);
397 }
398 }
399}
400
401fn update_mass_properties(
402 mut commands: Commands,
403 query: Query<Entity, With<RecomputeMassProperties>>,
404 mut mass_helper: MassPropertyHelper,
405) {
406 for entity in query.iter() {
408 mass_helper.update_mass_properties(entity);
409 commands.entity(entity).remove::<RecomputeMassProperties>();
410 }
411}
412
413#[cfg(feature = "3d")]
415pub(crate) fn update_global_angular_inertia<F: QueryFilter>(
416 mut query: Populated<
417 (
418 &Rotation,
419 &ComputedAngularInertia,
420 &mut GlobalAngularInertia,
421 ),
422 (Or<(Changed<ComputedAngularInertia>, Changed<Rotation>)>, F),
423 >,
424) {
425 query
426 .par_iter_mut()
427 .for_each(|(rotation, angular_inertia, mut global_angular_inertia)| {
428 global_angular_inertia.update(*angular_inertia, rotation.0);
429 });
430}
431
432fn warn_missing_mass(
434 mut bodies: Query<
435 (
436 Entity,
437 &RigidBody,
438 Ref<ComputedMass>,
439 Ref<ComputedAngularInertia>,
440 ),
441 Or<(Changed<ComputedMass>, Changed<ComputedAngularInertia>)>,
442 >,
443) {
444 for (entity, rb, mass, inertia) in &mut bodies {
445 let is_mass_valid = mass.value().is_finite();
446 #[cfg(feature = "2d")]
447 let is_inertia_valid = inertia.value().is_finite();
448 #[cfg(feature = "3d")]
449 let is_inertia_valid = inertia.value().is_finite();
450
451 if rb.is_dynamic() && !(is_mass_valid && is_inertia_valid) {
453 warn!(
454 "Dynamic rigid body {:?} has no mass or inertia. This can cause NaN values. Consider adding a `MassPropertiesBundle` or a `Collider` with mass.",
455 entity
456 );
457 }
458 }
459}
460
461#[cfg(test)]
462#[cfg(feature = "2d")]
463#[expect(clippy::unnecessary_cast)]
464mod tests {
465 use approx::assert_relative_eq;
466
467 use super::*;
468
469 fn create_app() -> App {
470 let mut app = App::new();
471 app.add_plugins((MinimalPlugins, PhysicsPlugins::default(), TransformPlugin));
472 app
473 }
474
475 fn get_computed_mass_properties(
476 world: &mut World,
477 entity: Entity,
478 ) -> (
479 &ComputedMass,
480 &ComputedAngularInertia,
481 &ComputedCenterOfMass,
482 ) {
483 let mut query = world.query::<(
484 &ComputedMass,
485 &ComputedAngularInertia,
486 &ComputedCenterOfMass,
487 )>();
488 query.get(world, entity).unwrap()
489 }
490
491 #[test]
492 fn mass_properties_zero_by_default() {
493 let mut app = create_app();
496
497 let body_entity = app.world_mut().spawn(RigidBody::Dynamic).id();
498
499 app.world_mut().run_schedule(FixedPostUpdate);
500
501 let (mass, angular_inertia, center_of_mass) =
502 get_computed_mass_properties(app.world_mut(), body_entity);
503
504 assert_eq!(*mass, ComputedMass::default());
505 assert_eq!(*angular_inertia, ComputedAngularInertia::default());
506 assert_eq!(*center_of_mass, ComputedCenterOfMass::default());
507 }
508
509 #[test]
510 fn mass_properties_rb_collider() {
511 let mut app = create_app();
514
515 let collider = Collider::circle(1.0);
516 let collider_mass_props = collider.mass_properties(1.0);
517
518 let body_entity = app.world_mut().spawn((RigidBody::Dynamic, collider)).id();
519
520 app.world_mut().run_schedule(FixedPostUpdate);
521
522 let (mass, angular_inertia, center_of_mass) =
523 get_computed_mass_properties(app.world_mut(), body_entity);
524
525 assert_eq!(mass.value() as f32, collider_mass_props.mass);
526 assert_eq!(
527 angular_inertia.value() as f32,
528 collider_mass_props.angular_inertia
529 );
530 assert_eq!(*center_of_mass, ComputedCenterOfMass::default());
531 }
532
533 #[test]
534 fn mass_properties_rb_collider_with_set_mass() {
535 let mut app = create_app();
538
539 let collider = Collider::circle(1.0);
540 let collider_mass_props = collider.mass_properties(1.0);
541
542 let body_entity = app
543 .world_mut()
544 .spawn((RigidBody::Dynamic, collider, Mass(5.0)))
545 .id();
546
547 app.world_mut().run_schedule(FixedPostUpdate);
548
549 let (mass, angular_inertia, center_of_mass) =
550 get_computed_mass_properties(app.world_mut(), body_entity);
551
552 assert_eq!(mass.value() as f32, 5.0);
553 assert_eq!(
554 angular_inertia.value() as f32,
555 mass.value() as f32 * collider_mass_props.unit_angular_inertia()
556 );
557 assert_eq!(*center_of_mass, ComputedCenterOfMass::default());
558 }
559
560 #[test]
561 fn mass_properties_rb_collider_with_set_mass_and_angular_inertia() {
562 let mut app = create_app();
565
566 let collider = Collider::circle(1.0);
567
568 let body_entity = app
569 .world_mut()
570 .spawn((
571 RigidBody::Dynamic,
572 collider,
573 Mass(5.0),
574 AngularInertia(10.0),
575 ))
576 .id();
577
578 app.world_mut().run_schedule(FixedPostUpdate);
579
580 let (mass, angular_inertia, center_of_mass) =
581 get_computed_mass_properties(app.world_mut(), body_entity);
582
583 assert_eq!(mass.value() as f32, 5.0);
584 assert_eq!(angular_inertia.value() as f32, 10.0);
585 assert_eq!(*center_of_mass, ComputedCenterOfMass::default());
586 }
587
588 #[test]
589 fn mass_properties_rb_collider_with_set_mass_and_child_collider() {
590 let mut app = create_app();
594
595 let collider = Collider::circle(1.0);
596 let collider_mass_props = collider.mass_properties(2.0);
597
598 let body_entity = app
599 .world_mut()
600 .spawn((RigidBody::Dynamic, collider.clone(), Mass(5.0)))
601 .with_child((collider, ColliderDensity(2.0)))
602 .id();
603
604 app.world_mut().run_schedule(FixedPostUpdate);
605
606 let (mass, angular_inertia, center_of_mass) =
607 get_computed_mass_properties(app.world_mut(), body_entity);
608
609 assert_eq!(mass.value() as f32, 5.0 + collider_mass_props.mass);
610 assert_eq!(
611 angular_inertia.value() as f32,
612 5.0 * collider_mass_props.unit_angular_inertia() + collider_mass_props.angular_inertia
613 );
614 assert_eq!(*center_of_mass, ComputedCenterOfMass::default());
615 }
616
617 #[test]
618 fn mass_properties_rb_collider_with_set_mass_and_child_collider_with_set_mass() {
619 let mut app = create_app();
623
624 let collider = Collider::circle(1.0);
625 let collider_mass_props = collider.mass_properties(1.0);
626
627 let body_entity = app
628 .world_mut()
629 .spawn((RigidBody::Dynamic, collider.clone(), Mass(5.0)))
630 .with_child((collider, ColliderDensity(2.0), Mass(10.0)))
631 .id();
632
633 app.world_mut().run_schedule(FixedPostUpdate);
634
635 let (mass, angular_inertia, center_of_mass) =
636 get_computed_mass_properties(app.world_mut(), body_entity);
637
638 assert_eq!(mass.value() as f32, 5.0 + 10.0);
639 assert_eq!(
640 angular_inertia.value() as f32,
641 5.0 * collider_mass_props.unit_angular_inertia()
642 + 10.0 * collider_mass_props.unit_angular_inertia()
643 );
644 assert_eq!(*center_of_mass, ComputedCenterOfMass::default());
645 }
646
647 #[test]
648 fn mass_properties_no_auto_mass_collider_no_set_mass() {
649 let mut app = create_app();
654
655 let body_entity = app
656 .world_mut()
657 .spawn((RigidBody::Dynamic, Collider::circle(1.0), NoAutoMass))
658 .id();
659
660 app.world_mut().run_schedule(FixedPostUpdate);
661
662 let (mass, angular_inertia, center_of_mass) =
663 get_computed_mass_properties(app.world_mut(), body_entity);
664
665 assert_eq!(*mass, ComputedMass::default());
666 assert_eq!(*angular_inertia, ComputedAngularInertia::default());
667 assert_eq!(*center_of_mass, ComputedCenterOfMass::default());
668 }
669
670 #[test]
671 fn mass_properties_no_auto_mass_hierarchy() {
672 let mut app = create_app();
676
677 let collider = Collider::circle(1.0);
678 let collider_mass_props = collider.mass_properties(1.0);
679
680 let body_entity = app
681 .world_mut()
682 .spawn((RigidBody::Dynamic, collider.clone(), Mass(5.0), NoAutoMass))
683 .with_child((collider, ColliderDensity(2.0), Mass(10.0)))
684 .id();
685
686 app.world_mut().run_schedule(FixedPostUpdate);
687
688 let (mass, angular_inertia, center_of_mass) =
689 get_computed_mass_properties(app.world_mut(), body_entity);
690
691 assert_eq!(mass.value() as f32, 5.0);
692 assert_eq!(
693 angular_inertia.value() as f32,
694 mass.value() as f32
695 * (5.0 * collider_mass_props.unit_angular_inertia()
696 + 10.0 * collider_mass_props.unit_angular_inertia())
697 / 15.0
698 );
699 assert_eq!(*center_of_mass, ComputedCenterOfMass::default());
700 }
701
702 #[test]
703 fn mass_properties_add_remove_collider() {
704 let mut app = create_app();
713
714 let collider = Collider::circle(1.0);
715 let collider_mass_props = collider.mass_properties(1.0);
716
717 let body_entity = app.world_mut().spawn((RigidBody::Dynamic, collider)).id();
718
719 app.world_mut().run_schedule(FixedPostUpdate);
720
721 let (mass, angular_inertia, center_of_mass) =
722 get_computed_mass_properties(app.world_mut(), body_entity);
723
724 assert_eq!(mass.value() as f32, collider_mass_props.mass);
725 assert_eq!(
726 angular_inertia.value() as f32,
727 collider_mass_props.angular_inertia
728 );
729 assert_eq!(*center_of_mass, ComputedCenterOfMass::default());
730
731 let child_collider = Collider::circle(2.0);
733 let child_collider_mass_props = child_collider.mass_properties(1.0);
734
735 let child_entity = app
736 .world_mut()
737 .spawn((ChildOf(body_entity), child_collider, ColliderDensity(1.0)))
738 .id();
739
740 app.world_mut().run_schedule(FixedPostUpdate);
741
742 let (mass, angular_inertia, center_of_mass) =
743 get_computed_mass_properties(app.world_mut(), body_entity);
744
745 assert_eq!(
746 mass.value() as f32,
747 collider_mass_props.mass + child_collider_mass_props.mass
748 );
749 assert_eq!(
750 angular_inertia.value() as f32,
751 collider_mass_props.angular_inertia + child_collider_mass_props.angular_inertia
752 );
753 assert_eq!(*center_of_mass, ComputedCenterOfMass::default());
754
755 app.world_mut().entity_mut(child_entity).despawn();
757
758 app.world_mut().run_schedule(FixedPostUpdate);
759
760 let (mass, angular_inertia, center_of_mass) =
761 get_computed_mass_properties(app.world_mut(), body_entity);
762
763 assert_eq!(mass.value() as f32, collider_mass_props.mass);
764 assert_eq!(
765 angular_inertia.value() as f32,
766 collider_mass_props.angular_inertia
767 );
768 assert_eq!(*center_of_mass, ComputedCenterOfMass::default());
769 }
770
771 #[test]
772 fn mass_properties_change_mass() {
773 let mut app = create_app();
780
781 let collider = Collider::circle(1.0);
782 let collider_mass_props = collider.mass_properties(1.0);
783
784 let body_entity = app
785 .world_mut()
786 .spawn((RigidBody::Dynamic, collider, Mass(5.0)))
787 .id();
788
789 app.world_mut().run_schedule(FixedPostUpdate);
790
791 let (mass, angular_inertia, center_of_mass) =
792 get_computed_mass_properties(app.world_mut(), body_entity);
793
794 assert_eq!(mass.value() as f32, 5.0);
795 assert_eq!(
796 angular_inertia.value() as f32,
797 mass.value() as f32 * collider_mass_props.unit_angular_inertia()
798 );
799 assert_eq!(*center_of_mass, ComputedCenterOfMass::default());
800
801 app.world_mut().entity_mut(body_entity).insert(Mass(10.0));
803
804 app.world_mut().run_schedule(FixedPostUpdate);
805
806 let (mass, angular_inertia, center_of_mass) =
807 get_computed_mass_properties(app.world_mut(), body_entity);
808
809 assert_eq!(mass.value() as f32, 10.0);
810 assert_eq!(
811 angular_inertia.value() as f32,
812 mass.value() as f32 * collider_mass_props.unit_angular_inertia()
813 );
814 assert_eq!(*center_of_mass, ComputedCenterOfMass::default());
815 }
816
817 #[test]
818 fn mass_properties_move_child_collider() {
819 let mut app = create_app();
827
828 let body_entity = app
829 .world_mut()
830 .spawn((
831 RigidBody::Dynamic,
832 Mass(10.0),
833 CenterOfMass::new(0.0, -0.5),
834 Transform::default(),
835 ))
836 .id();
837
838 let child_entity = app
839 .world_mut()
840 .spawn((
841 ChildOf(body_entity),
842 Collider::circle(1.0),
843 Mass(5.0),
844 Transform::default(),
845 ))
846 .id();
847
848 app.world_mut().run_schedule(FixedPostUpdate);
849
850 let (mass, _, center_of_mass) = get_computed_mass_properties(app.world_mut(), body_entity);
851
852 assert_eq!(mass.value() as f32, 10.0 + 5.0);
853 assert_relative_eq!(
854 center_of_mass.0,
855 Vector::new(0.0, -1.0 / 3.0),
856 epsilon = 1.0e-6
857 );
858
859 app.world_mut()
861 .entity_mut(child_entity)
862 .insert(Transform::from_xyz(0.0, 4.0, 0.0));
863
864 app.world_mut().run_schedule(FixedPostUpdate);
865
866 let (mass, _, center_of_mass) = get_computed_mass_properties(app.world_mut(), body_entity);
867
868 assert_eq!(mass.value(), 10.0 + 5.0);
869 assert_relative_eq!(center_of_mass.0, Vector::new(0.0, 1.0));
870 }
871
872 #[test]
873 fn mass_properties_no_auto_mass_add_remove() {
874 let mut app = create_app();
884
885 let collider = Collider::circle(1.0);
886 let collider_mass_props = collider.mass_properties(1.0);
887
888 let body_entity = app
889 .world_mut()
890 .spawn((RigidBody::Dynamic, collider.clone(), Mass(5.0)))
891 .with_child((collider, Mass(10.0)))
892 .id();
893
894 app.world_mut().run_schedule(FixedPostUpdate);
895
896 let (mass, angular_inertia, center_of_mass) =
897 get_computed_mass_properties(app.world_mut(), body_entity);
898
899 assert_eq!(mass.value() as f32, 5.0 + 10.0);
900 assert_eq!(
901 angular_inertia.value() as f32,
902 5.0 * collider_mass_props.unit_angular_inertia()
903 + 10.0 * collider_mass_props.unit_angular_inertia()
904 );
905 assert_eq!(*center_of_mass, ComputedCenterOfMass::default());
906
907 app.world_mut().entity_mut(body_entity).insert(NoAutoMass);
909
910 app.world_mut().run_schedule(FixedPostUpdate);
911
912 let (mass, angular_inertia, center_of_mass) =
913 get_computed_mass_properties(app.world_mut(), body_entity);
914
915 assert_eq!(mass.value() as f32, 5.0);
916 assert_eq!(
917 angular_inertia.value() as f32,
918 5.0 * (5.0 * collider_mass_props.unit_angular_inertia()
919 + 10.0 * collider_mass_props.unit_angular_inertia())
920 / 15.0
921 );
922 assert_eq!(*center_of_mass, ComputedCenterOfMass::default());
923
924 app.world_mut()
926 .entity_mut(body_entity)
927 .remove::<NoAutoMass>();
928
929 app.world_mut().run_schedule(FixedPostUpdate);
930
931 let (mass, angular_inertia, center_of_mass) =
932 get_computed_mass_properties(app.world_mut(), body_entity);
933
934 assert_eq!(mass.value() as f32, 5.0 + 10.0);
935 assert_eq!(
936 angular_inertia.value() as f32,
937 5.0 * collider_mass_props.unit_angular_inertia()
938 + 10.0 * collider_mass_props.unit_angular_inertia()
939 );
940 assert_eq!(*center_of_mass, ComputedCenterOfMass::default());
941 }
942}