use bevy_math::{
Curve, VectorSpace, WithDerivative,
curve::{Interval, derivatives::SampleDerivative},
};
#[derive(Default, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "bevy_reflect", derive(bevy_reflect::Reflect))]
#[cfg_attr(feature = "serialize", derive(serde::Serialize))]
#[cfg_attr(feature = "debug", derive(Debug))]
pub struct Linear;
impl Curve<f32> for Linear {
#[inline]
fn domain(&self) -> Interval {
Interval::EVERYWHERE
}
#[inline]
fn sample_unchecked(&self, t: f32) -> f32 {
t
}
}
impl SampleDerivative<f32> for Linear {
#[inline]
fn sample_with_derivative_unchecked(&self, t: f32) -> WithDerivative<f32> {
WithDerivative {
value: self.sample_unchecked(t),
derivative: 1.0,
}
}
}
#[derive(Default, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "bevy_reflect", derive(bevy_reflect::Reflect))]
#[cfg_attr(feature = "serialize", derive(serde::Serialize))]
#[cfg_attr(feature = "debug", derive(Debug))]
pub struct Smoothstep;
impl Curve<f32> for Smoothstep {
#[inline]
fn domain(&self) -> Interval {
Interval::UNIT
}
#[inline]
fn sample_unchecked(&self, t: f32) -> f32 {
t * t * (t * (-2.0) + 3.0)
}
}
impl SampleDerivative<f32> for Smoothstep {
#[inline]
fn sample_with_derivative_unchecked(&self, t: f32) -> WithDerivative<f32> {
WithDerivative {
value: self.sample_unchecked(t),
derivative: 6.0 * t - 6.0 * t * t,
}
}
}
#[derive(Default, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "bevy_reflect", derive(bevy_reflect::Reflect))]
#[cfg_attr(feature = "serialize", derive(serde::Serialize))]
#[cfg_attr(feature = "debug", derive(Debug))]
pub struct DoubleSmoothstep;
impl Curve<f32> for DoubleSmoothstep {
#[inline]
fn domain(&self) -> Interval {
Interval::UNIT
}
#[inline]
fn sample_unchecked(&self, t: f32) -> f32 {
Smoothstep.sample_unchecked(Smoothstep.sample_unchecked(t))
}
}
impl SampleDerivative<f32> for DoubleSmoothstep {
#[inline]
fn sample_with_derivative_unchecked(&self, t: f32) -> WithDerivative<f32> {
let first = Smoothstep.sample_with_derivative_unchecked(t);
WithDerivative {
value: Smoothstep.sample_unchecked(first.value),
derivative: first.derivative
* Smoothstep
.sample_with_derivative_unchecked(first.value)
.derivative,
}
}
}
#[derive(Default, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "bevy_reflect", derive(bevy_reflect::Reflect))]
#[cfg_attr(feature = "serialize", derive(serde::Serialize))]
#[cfg_attr(feature = "debug", derive(Debug))]
pub struct TripleSmoothstep;
impl Curve<f32> for TripleSmoothstep {
#[inline]
fn domain(&self) -> Interval {
Interval::UNIT
}
#[inline]
fn sample_unchecked(&self, t: f32) -> f32 {
Smoothstep.sample_unchecked(Smoothstep.sample_unchecked(Smoothstep.sample_unchecked(t)))
}
}
impl SampleDerivative<f32> for TripleSmoothstep {
#[inline]
fn sample_with_derivative_unchecked(&self, t: f32) -> WithDerivative<f32> {
let first = Smoothstep.sample_with_derivative_unchecked(t);
WithDerivative {
value: DoubleSmoothstep.sample_unchecked(first.value),
derivative: first.derivative
* DoubleSmoothstep
.sample_with_derivative_unchecked(first.value)
.derivative,
}
}
}
pub trait SmoothMin {
fn smin_norm(&self, a: f32, b: f32, blend_radius: f32) -> f32;
}
#[derive(Default, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "bevy_reflect", derive(bevy_reflect::Reflect))]
#[cfg_attr(feature = "serialize", derive(serde::Serialize))]
#[cfg_attr(feature = "debug", derive(Debug))]
pub struct CubicSMin;
impl SmoothMin for CubicSMin {
fn smin_norm(&self, a: f32, b: f32, blend_radius: f32) -> f32 {
let k = 4.0 * blend_radius;
let diff = bevy_math::ops::abs(a - b);
let h = 0f32.max(k - diff) / k;
a.min(b) - h * h * blend_radius
}
}
#[derive(Default, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "bevy_reflect", derive(bevy_reflect::Reflect))]
#[cfg_attr(feature = "serialize", derive(serde::Serialize))]
#[cfg_attr(feature = "debug", derive(Debug))]
pub struct Lerped<T> {
pub start: T,
pub end: T,
}
impl<T: VectorSpace<Scalar = f32>> Curve<T> for Lerped<T> {
#[inline]
fn domain(&self) -> Interval {
Interval::EVERYWHERE
}
#[inline]
fn sample_unchecked(&self, t: f32) -> T {
self.start.lerp(self.end, t)
}
}
impl<T: VectorSpace<Scalar = f32>> SampleDerivative<T> for Lerped<T> {
#[inline]
fn sample_with_derivative_unchecked(&self, t: f32) -> WithDerivative<T> {
WithDerivative {
value: self.start.lerp(self.end, t),
derivative: self.end - self.start,
}
}
}