use crate::prelude::*;
use bevy::prelude::*;
use derive_more::From;
#[cfg(feature = "3d")]
use crate::utils::get_rotated_inertia_tensor;
#[derive(Reflect, Clone, Copy, Component, Debug, Default, Deref, DerefMut, PartialEq, From)]
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "serialize", reflect(Serialize, Deserialize))]
#[reflect(Debug, Component, Default, PartialEq)]
pub struct Mass(pub Scalar);
impl Mass {
pub const ZERO: Self = Self(0.0);
}
#[derive(Reflect, Clone, Copy, Component, Debug, Default, Deref, DerefMut, PartialEq, From)]
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "serialize", reflect(Serialize, Deserialize))]
#[reflect(Debug, Component, Default, PartialEq)]
pub struct InverseMass(pub Scalar);
impl InverseMass {
pub const ZERO: Self = Self(0.0);
}
#[cfg(feature = "2d")]
#[derive(Reflect, Clone, Copy, Component, Debug, Default, Deref, DerefMut, PartialEq, From)]
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "serialize", reflect(Serialize, Deserialize))]
#[reflect(Debug, Component, Default, PartialEq)]
pub struct Inertia(pub Scalar);
#[cfg(feature = "3d")]
#[derive(Reflect, Clone, Copy, Component, Debug, Deref, DerefMut, PartialEq, From)]
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "serialize", reflect(Serialize, Deserialize))]
#[reflect(Debug, Component, PartialEq)]
pub struct Inertia(pub Matrix3);
#[cfg(feature = "3d")]
impl Default for Inertia {
fn default() -> Self {
Self(Matrix3::ZERO)
}
}
impl Inertia {
#[cfg(feature = "2d")]
pub const ZERO: Self = Self(0.0);
#[cfg(feature = "3d")]
pub const ZERO: Self = Self(Matrix3::ZERO);
#[cfg(feature = "2d")]
#[allow(dead_code)]
pub(crate) fn rotated(&self, _rot: &Rotation) -> Self {
*self
}
#[cfg(feature = "3d")]
pub fn rotated(&self, rot: &Rotation) -> Self {
Self(get_rotated_inertia_tensor(self.0, rot.0))
}
#[cfg(feature = "2d")]
pub fn inverse(&self) -> InverseInertia {
InverseInertia(1.0 / self.0)
}
#[cfg(feature = "3d")]
pub fn inverse(&self) -> InverseInertia {
InverseInertia(self.0.inverse())
}
#[cfg(feature = "2d")]
pub fn shifted(&self, mass: Scalar, offset: Vector) -> Scalar {
if mass > 0.0 && mass.is_finite() {
self.0 + offset.length_squared() * mass
} else {
self.0
}
}
#[cfg(feature = "3d")]
pub fn shifted(&self, mass: Scalar, offset: Vector) -> Matrix3 {
if mass > 0.0 && mass.is_finite() {
let diag = offset.length_squared();
let diagm = Matrix3::from_diagonal(Vector::splat(diag));
let offset_outer_product =
Matrix3::from_cols(offset * offset.x, offset * offset.y, offset * offset.z);
self.0 + (diagm + offset_outer_product) * mass
} else {
self.0
}
}
}
#[cfg(feature = "2d")]
#[derive(Reflect, Clone, Copy, Component, Debug, Default, Deref, DerefMut, PartialEq, From)]
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "serialize", reflect(Serialize, Deserialize))]
#[reflect(Debug, Component, Default, PartialEq)]
pub struct InverseInertia(pub Scalar);
#[cfg(feature = "3d")]
#[derive(Reflect, Clone, Copy, Component, Debug, Deref, DerefMut, PartialEq, From)]
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "serialize", reflect(Serialize, Deserialize))]
#[reflect(Debug, Component, PartialEq)]
pub struct InverseInertia(pub Matrix3);
#[cfg(feature = "3d")]
impl Default for InverseInertia {
fn default() -> Self {
InverseInertia(Matrix3::ZERO)
}
}
impl InverseInertia {
#[cfg(feature = "2d")]
pub const ZERO: Self = Self(0.0);
#[cfg(feature = "3d")]
pub const ZERO: Self = Self(Matrix3::ZERO);
#[cfg(feature = "2d")]
pub fn rotated(&self, _rot: &Rotation) -> Self {
*self
}
#[cfg(feature = "3d")]
pub fn rotated(&self, rot: &Rotation) -> Self {
Self(get_rotated_inertia_tensor(self.0, rot.0))
}
#[cfg(feature = "2d")]
pub fn inverse(&self) -> Inertia {
Inertia(1.0 / self.0)
}
#[cfg(feature = "3d")]
pub fn inverse(&self) -> Inertia {
Inertia(self.0.inverse())
}
}
impl From<Inertia> for InverseInertia {
fn from(inertia: Inertia) -> Self {
inertia.inverse()
}
}
#[derive(Reflect, Clone, Copy, Component, Debug, Default, Deref, DerefMut, PartialEq, From)]
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "serialize", reflect(Serialize, Deserialize))]
#[reflect(Debug, Component, Default, PartialEq)]
pub struct CenterOfMass(pub Vector);
impl CenterOfMass {
pub const ZERO: Self = Self(Vector::ZERO);
}
#[cfg_attr(feature = "2d", doc = "use avian2d::prelude::*;")]
#[cfg_attr(feature = "3d", doc = "use avian3d::prelude::*;")]
#[cfg_attr(
feature = "2d",
doc = " MassPropertiesBundle::new_computed(&Collider::circle(0.5), 1.0),"
)]
#[cfg_attr(
feature = "3d",
doc = " MassPropertiesBundle::new_computed(&Collider::sphere(0.5), 1.0),"
)]
#[allow(missing_docs)]
#[derive(Bundle, Debug, Default, Clone, PartialEq)]
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
pub struct MassPropertiesBundle {
pub mass: Mass,
pub inverse_mass: InverseMass,
pub inertia: Inertia,
pub inverse_inertia: InverseInertia,
pub center_of_mass: CenterOfMass,
}
impl MassPropertiesBundle {
#[cfg(all(
feature = "default-collider",
any(feature = "parry-f32", feature = "parry-f64")
))]
pub fn new_computed(collider: &Collider, density: Scalar) -> Self {
let ColliderMassProperties {
mass,
inverse_mass,
inertia,
inverse_inertia,
center_of_mass,
..
} = collider.mass_properties(density);
Self {
mass,
inverse_mass,
inertia,
inverse_inertia,
center_of_mass,
}
}
}
#[cfg_attr(feature = "2d", doc = "use avian2d::prelude::*;")]
#[cfg_attr(feature = "3d", doc = "use avian3d::prelude::*;")]
#[cfg_attr(feature = "2d", doc = " Collider::circle(0.5),")]
#[cfg_attr(feature = "3d", doc = " Collider::sphere(0.5),")]
#[derive(Reflect, Clone, Copy, Component, Debug, Deref, DerefMut, PartialEq, PartialOrd)]
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "serialize", reflect(Serialize, Deserialize))]
#[reflect(Debug, Component, PartialEq)]
pub struct ColliderDensity(pub Scalar);
impl ColliderDensity {
pub const ZERO: Self = Self(0.0);
}
impl Default for ColliderDensity {
fn default() -> Self {
Self(1.0)
}
}
impl From<Scalar> for ColliderDensity {
fn from(density: Scalar) -> Self {
Self(density)
}
}
#[cfg_attr(feature = "2d", doc = "use avian2d::prelude::*;")]
#[cfg_attr(feature = "3d", doc = "use avian3d::prelude::*;")]
#[cfg_attr(feature = "2d", doc = " commands.spawn(Collider::circle(0.5));")]
#[cfg_attr(feature = "3d", doc = " commands.spawn(Collider::sphere(0.5));")]
#[derive(Reflect, Clone, Copy, Component, Debug, PartialEq)]
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "serialize", reflect(Serialize, Deserialize))]
#[reflect(Debug, Component, PartialEq)]
pub struct ColliderMassProperties {
pub mass: Mass,
pub inverse_mass: InverseMass,
pub inertia: Inertia,
pub inverse_inertia: InverseInertia,
pub center_of_mass: CenterOfMass,
}
impl ColliderMassProperties {
pub const ZERO: Self = Self {
mass: Mass::ZERO,
inverse_mass: InverseMass(Scalar::INFINITY),
inertia: Inertia::ZERO,
inverse_inertia: InverseInertia::ZERO,
center_of_mass: CenterOfMass::ZERO,
};
pub fn new<C: AnyCollider>(collider: &C, density: Scalar) -> Self {
collider.mass_properties(density)
}
#[inline]
pub fn transformed_by(mut self, transform: &ColliderTransform) -> Self {
self.center_of_mass.0 = transform.transform_point(self.center_of_mass.0);
self
}
}
impl Default for ColliderMassProperties {
fn default() -> Self {
Self::ZERO
}
}