#[cfg(feature = "f32")]
mod single;
#[cfg(feature = "f32")]
pub use single::*;
#[cfg(feature = "f64")]
mod double;
#[cfg(feature = "f64")]
pub use double::*;
use bevy_math::{prelude::*, *};
#[cfg(feature = "2d")]
pub const DIM: usize = 2;
#[cfg(feature = "3d")]
pub const DIM: usize = 3;
#[cfg(feature = "2d")]
pub(crate) use bevy_math::Vec2 as VectorF32;
#[cfg(feature = "3d")]
pub(crate) use bevy_math::Vec3 as VectorF32;
#[cfg(feature = "2d")]
pub(crate) type Ray = Ray2d;
#[cfg(feature = "3d")]
pub(crate) type Ray = Ray3d;
#[cfg(feature = "2d")]
pub(crate) type Dir = Dir2;
#[cfg(feature = "3d")]
pub(crate) type Dir = Dir3;
pub trait AdjustPrecision {
type Adjusted;
fn adjust_precision(&self) -> Self::Adjusted;
}
pub trait AsF32 {
type F32;
fn f32(&self) -> Self::F32;
}
impl AsF32 for DVec3 {
type F32 = Vec3;
fn f32(&self) -> Self::F32 {
self.as_vec3()
}
}
impl AsF32 for Vec3 {
type F32 = Self;
fn f32(&self) -> Self::F32 {
*self
}
}
impl AsF32 for DVec2 {
type F32 = Vec2;
fn f32(&self) -> Self::F32 {
self.as_vec2()
}
}
impl AsF32 for Vec2 {
type F32 = Self;
fn f32(&self) -> Self::F32 {
*self
}
}
impl AsF32 for Vec4 {
type F32 = Self;
fn f32(&self) -> Self::F32 {
*self
}
}
impl AsF32 for DQuat {
type F32 = Quat;
fn f32(&self) -> Self::F32 {
self.as_quat()
}
}
impl AsF32 for Quat {
type F32 = Self;
fn f32(&self) -> Self::F32 {
*self
}
}
impl AsF32 for DMat2 {
type F32 = Mat2;
fn f32(&self) -> Self::F32 {
self.as_mat2()
}
}
impl AsF32 for Mat2 {
type F32 = Self;
fn f32(&self) -> Self::F32 {
*self
}
}
impl AsF32 for DMat3 {
type F32 = Mat3;
fn f32(&self) -> Self::F32 {
self.as_mat3()
}
}
impl AsF32 for Mat3 {
type F32 = Self;
fn f32(&self) -> Self::F32 {
*self
}
}
#[cfg(feature = "2d")]
pub(crate) fn cross(a: Vector, b: Vector) -> Scalar {
a.perp_dot(b)
}
#[cfg(feature = "3d")]
pub(crate) fn cross(a: Vector, b: Vector) -> Vector {
a.cross(b)
}
pub trait RecipOrZero {
fn recip_or_zero(self) -> Self;
}
impl RecipOrZero for f32 {
#[inline]
fn recip_or_zero(self) -> Self {
if self != 0.0 && self.is_finite() {
self.recip()
} else {
0.0
}
}
}
impl RecipOrZero for f64 {
#[inline]
fn recip_or_zero(self) -> Self {
if self != 0.0 && self.is_finite() {
self.recip()
} else {
0.0
}
}
}
impl RecipOrZero for Vec2 {
#[inline]
fn recip_or_zero(self) -> Self {
Self::new(self.x.recip_or_zero(), self.y.recip_or_zero())
}
}
impl RecipOrZero for Vec3 {
#[inline]
fn recip_or_zero(self) -> Self {
Self::new(
self.x.recip_or_zero(),
self.y.recip_or_zero(),
self.z.recip_or_zero(),
)
}
}
impl RecipOrZero for DVec2 {
#[inline]
fn recip_or_zero(self) -> Self {
Self::new(self.x.recip_or_zero(), self.y.recip_or_zero())
}
}
impl RecipOrZero for DVec3 {
#[inline]
fn recip_or_zero(self) -> Self {
Self::new(
self.x.recip_or_zero(),
self.y.recip_or_zero(),
self.z.recip_or_zero(),
)
}
}
pub trait MatExt {
fn inverse_or_zero(self) -> Self;
}
impl MatExt for Mat2 {
#[inline]
fn inverse_or_zero(self) -> Self {
if self.determinant() == 0.0 {
Self::ZERO
} else {
self.inverse()
}
}
}
impl MatExt for DMat2 {
#[inline]
fn inverse_or_zero(self) -> Self {
if self.determinant() == 0.0 {
Self::ZERO
} else {
self.inverse()
}
}
}
impl MatExt for Mat3 {
#[inline]
fn inverse_or_zero(self) -> Self {
if self.determinant() == 0.0 {
Self::ZERO
} else {
self.inverse()
}
}
}
impl MatExt for DMat3 {
#[inline]
fn inverse_or_zero(self) -> Self {
if self.determinant() == 0.0 {
Self::ZERO
} else {
self.inverse()
}
}
}
#[expect(clippy::unnecessary_cast)]
#[cfg(all(feature = "2d", any(feature = "parry-f32", feature = "parry-f64")))]
pub(crate) fn na_iso_to_iso(isometry: &parry::math::Isometry<Scalar>) -> Isometry2d {
Isometry2d::new(
Vector::from(isometry.translation).f32(),
Rot2::from_sin_cos(isometry.rotation.im as f32, isometry.rotation.re as f32),
)
}
#[cfg(all(
feature = "default-collider",
any(feature = "parry-f32", feature = "parry-f64")
))]
use crate::prelude::*;
#[cfg(all(
feature = "default-collider",
any(feature = "parry-f32", feature = "parry-f64")
))]
use parry::math::Isometry;
#[cfg(all(
feature = "2d",
feature = "default-collider",
any(feature = "parry-f32", feature = "parry-f64")
))]
pub(crate) fn make_isometry(
position: impl Into<Position>,
rotation: impl Into<Rotation>,
) -> Isometry<Scalar> {
let position: Position = position.into();
let rotation: Rotation = rotation.into();
Isometry::<Scalar>::new(position.0.into(), rotation.into())
}
#[cfg(all(
feature = "3d",
feature = "default-collider",
any(feature = "parry-f32", feature = "parry-f64")
))]
pub(crate) fn make_isometry(
position: impl Into<Position>,
rotation: impl Into<Rotation>,
) -> Isometry<Scalar> {
let position: Position = position.into();
let rotation: Rotation = rotation.into();
Isometry::<Scalar>::new(position.0.into(), rotation.to_scaled_axis().into())
}
#[inline]
#[must_use]
#[cfg(feature = "3d")]
pub fn skew_symmetric_mat3(v: Vector3) -> Matrix3 {
Matrix3::from_cols_array(&[0.0, v.z, -v.y, -v.z, 0.0, v.x, v.y, -v.x, 0.0])
}