use crate::{ops, DVec2, DVec3, DVec4, Dir2, Dir3, Dir3A, Quat, Rot2, Vec2, Vec3, Vec3A, Vec4};
use core::{
convert::Infallible,
fmt::Debug,
ops::{Add, Div, Mul, Neg, Sub},
};
use thiserror::Error;
use variadics_please::all_tuples_enumerated;
pub trait VectorSpace:
Mul<Self::Scalar, Output = Self>
+ Div<Self::Scalar, Output = Self>
+ Add<Self, Output = Self>
+ Sub<Self, Output = Self>
+ Neg<Output = Self>
+ Default
+ Debug
+ Clone
+ Copy
{
type Scalar: ScalarField;
const ZERO: Self;
#[inline]
fn lerp(self, rhs: Self, t: Self::Scalar) -> Self {
self * (Self::Scalar::ONE - t) + rhs * t
}
}
impl VectorSpace for Vec4 {
type Scalar = f32;
const ZERO: Self = Vec4::ZERO;
}
impl VectorSpace for Vec3 {
type Scalar = f32;
const ZERO: Self = Vec3::ZERO;
}
impl VectorSpace for Vec3A {
type Scalar = f32;
const ZERO: Self = Vec3A::ZERO;
}
impl VectorSpace for Vec2 {
type Scalar = f32;
const ZERO: Self = Vec2::ZERO;
}
impl VectorSpace for DVec4 {
type Scalar = f64;
const ZERO: Self = DVec4::ZERO;
}
impl VectorSpace for DVec3 {
type Scalar = f64;
const ZERO: Self = DVec3::ZERO;
}
impl VectorSpace for DVec2 {
type Scalar = f64;
const ZERO: Self = DVec2::ZERO;
}
impl<T: ScalarField> VectorSpace for T {
type Scalar = Self;
const ZERO: Self = Self::ZERO;
}
pub trait ScalarField:
Mul<Self, Output = Self>
+ Div<Self, Output = Self>
+ Add<Self, Output = Self>
+ Sub<Self, Output = Self>
+ Neg<Output = Self>
+ Default
+ Debug
+ Clone
+ Copy
{
const ZERO: Self;
const ONE: Self;
fn recip(self) -> Self {
Self::ONE / self
}
}
impl ScalarField for f32 {
const ZERO: Self = 0.0;
const ONE: Self = 1.0;
}
impl ScalarField for f64 {
const ZERO: Self = 0.0;
const ONE: Self = 1.0;
}
#[derive(Debug, Clone, Copy)]
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "bevy_reflect", derive(bevy_reflect::Reflect))]
pub struct Sum<V, W>(pub V, pub W);
impl<F: ScalarField, V, W> Mul<F> for Sum<V, W>
where
V: VectorSpace<Scalar = F>,
W: VectorSpace<Scalar = F>,
{
type Output = Self;
fn mul(self, rhs: F) -> Self::Output {
Sum(self.0 * rhs, self.1 * rhs)
}
}
impl<F: ScalarField, V, W> Div<F> for Sum<V, W>
where
V: VectorSpace<Scalar = F>,
W: VectorSpace<Scalar = F>,
{
type Output = Self;
fn div(self, rhs: F) -> Self::Output {
Sum(self.0 / rhs, self.1 / rhs)
}
}
impl<V, W> Add<Self> for Sum<V, W>
where
V: VectorSpace,
W: VectorSpace,
{
type Output = Self;
fn add(self, other: Self) -> Self::Output {
Sum(self.0 + other.0, self.1 + other.1)
}
}
impl<V, W> Sub<Self> for Sum<V, W>
where
V: VectorSpace,
W: VectorSpace,
{
type Output = Self;
fn sub(self, other: Self) -> Self::Output {
Sum(self.0 - other.0, self.1 - other.1)
}
}
impl<V, W> Neg for Sum<V, W>
where
V: VectorSpace,
W: VectorSpace,
{
type Output = Self;
fn neg(self) -> Self::Output {
Sum(-self.0, -self.1)
}
}
impl<V, W> Default for Sum<V, W>
where
V: VectorSpace,
W: VectorSpace,
{
fn default() -> Self {
Sum(V::default(), W::default())
}
}
impl<F: ScalarField, V, W> VectorSpace for Sum<V, W>
where
V: VectorSpace<Scalar = F>,
W: VectorSpace<Scalar = F>,
{
type Scalar = F;
const ZERO: Self = Sum(V::ZERO, W::ZERO);
}
pub trait NormedVectorSpace: VectorSpace {
fn norm(self) -> Self::Scalar;
#[inline]
fn norm_squared(self) -> Self::Scalar {
self.norm() * self.norm()
}
#[inline]
fn distance(self, rhs: Self) -> Self::Scalar {
(rhs - self).norm()
}
#[inline]
fn distance_squared(self, rhs: Self) -> Self::Scalar {
(rhs - self).norm_squared()
}
}
impl NormedVectorSpace for Vec4 {
#[inline]
fn norm(self) -> f32 {
self.length()
}
#[inline]
fn norm_squared(self) -> f32 {
self.length_squared()
}
}
impl NormedVectorSpace for Vec3 {
#[inline]
fn norm(self) -> f32 {
self.length()
}
#[inline]
fn norm_squared(self) -> f32 {
self.length_squared()
}
}
impl NormedVectorSpace for Vec3A {
#[inline]
fn norm(self) -> f32 {
self.length()
}
#[inline]
fn norm_squared(self) -> f32 {
self.length_squared()
}
}
impl NormedVectorSpace for Vec2 {
#[inline]
fn norm(self) -> f32 {
self.length()
}
#[inline]
fn norm_squared(self) -> f32 {
self.length_squared()
}
}
impl NormedVectorSpace for f32 {
#[inline]
fn norm(self) -> f32 {
ops::abs(self)
}
}
impl NormedVectorSpace for DVec4 {
#[inline]
fn norm(self) -> f64 {
self.length()
}
#[inline]
fn norm_squared(self) -> f64 {
self.length_squared()
}
}
impl NormedVectorSpace for DVec3 {
#[inline]
fn norm(self) -> f64 {
self.length()
}
#[inline]
fn norm_squared(self) -> f64 {
self.length_squared()
}
}
impl NormedVectorSpace for DVec2 {
#[inline]
fn norm(self) -> f64 {
self.length()
}
#[inline]
fn norm_squared(self) -> f64 {
self.length_squared()
}
}
impl NormedVectorSpace for f64 {
#[inline]
#[cfg(feature = "std")]
fn norm(self) -> f64 {
f64::abs(self)
}
#[inline]
#[cfg(all(any(feature = "libm", feature = "nostd-libm"), not(feature = "std")))]
fn norm(self) -> f64 {
libm::fabs(self)
}
}
pub trait StableInterpolate: Clone {
fn interpolate_stable(&self, other: &Self, t: f32) -> Self;
fn interpolate_stable_assign(&mut self, other: &Self, t: f32) {
*self = self.interpolate_stable(other, t);
}
fn smooth_nudge(&mut self, target: &Self, decay_rate: f32, delta: f32) {
self.interpolate_stable_assign(target, 1.0 - ops::exp(-decay_rate * delta));
}
}
impl<V> StableInterpolate for V
where
V: NormedVectorSpace<Scalar = f32>,
{
#[inline]
fn interpolate_stable(&self, other: &Self, t: f32) -> Self {
self.lerp(*other, t)
}
}
impl StableInterpolate for Rot2 {
#[inline]
fn interpolate_stable(&self, other: &Self, t: f32) -> Self {
self.slerp(*other, t)
}
}
impl StableInterpolate for Quat {
#[inline]
fn interpolate_stable(&self, other: &Self, t: f32) -> Self {
self.slerp(*other, t)
}
}
impl StableInterpolate for Dir2 {
#[inline]
fn interpolate_stable(&self, other: &Self, t: f32) -> Self {
self.slerp(*other, t)
}
}
impl StableInterpolate for Dir3 {
#[inline]
fn interpolate_stable(&self, other: &Self, t: f32) -> Self {
self.slerp(*other, t)
}
}
impl StableInterpolate for Dir3A {
#[inline]
fn interpolate_stable(&self, other: &Self, t: f32) -> Self {
self.slerp(*other, t)
}
}
macro_rules! impl_stable_interpolate_tuple {
($(#[$meta:meta])* $(($n:tt, $T:ident)),*) => {
$(#[$meta])*
impl<$($T: StableInterpolate),*> StableInterpolate for ($($T,)*) {
fn interpolate_stable(&self, other: &Self, t: f32) -> Self {
(
$(
<$T as StableInterpolate>::interpolate_stable(&self.$n, &other.$n, t),
)*
)
}
}
};
}
all_tuples_enumerated!(
#[doc(fake_variadic)]
impl_stable_interpolate_tuple,
1,
11,
T
);
#[derive(Clone, Debug, Error)]
#[error("cannot interpolate between two values of different units")]
pub struct MismatchedUnitsError;
pub trait TryStableInterpolate: Clone {
type Error;
fn try_interpolate_stable(&self, other: &Self, t: f32) -> Result<Self, Self::Error>;
}
impl<T: StableInterpolate> TryStableInterpolate for T {
type Error = Infallible;
fn try_interpolate_stable(&self, other: &Self, t: f32) -> Result<Self, Self::Error> {
Ok(self.interpolate_stable(other, t))
}
}
pub trait HasTangent {
type Tangent: VectorSpace;
}
#[derive(Debug, Clone, Copy)]
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "bevy_reflect", derive(bevy_reflect::Reflect))]
pub struct WithDerivative<T>
where
T: HasTangent,
{
pub value: T,
pub derivative: T::Tangent,
}
#[derive(Debug, Clone, Copy)]
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "bevy_reflect", derive(bevy_reflect::Reflect))]
pub struct WithTwoDerivatives<T>
where
T: HasTangent,
{
pub value: T,
pub derivative: T::Tangent,
pub second_derivative: <T::Tangent as HasTangent>::Tangent,
}
impl<V: VectorSpace> HasTangent for V {
type Tangent = V;
}
impl<F, U, V, M, N> HasTangent for (M, N)
where
F: ScalarField,
U: VectorSpace<Scalar = F>,
V: VectorSpace<Scalar = F>,
M: HasTangent<Tangent = U>,
N: HasTangent<Tangent = V>,
{
type Tangent = Sum<M::Tangent, N::Tangent>;
}