use core::ops::{Mul, Neg};
use bevy_math::{Curve, Vec2, Vec3, Vec3A, Vec4};
use crate::{NoiseFunction, cells::WithGradient, lengths::LengthFunction};
#[derive(Default, PartialEq, Clone, Copy)]
#[cfg_attr(feature = "bevy_reflect", derive(bevy_reflect::Reflect))]
#[cfg_attr(feature = "serialize", derive(serde::Serialize))]
#[cfg_attr(feature = "debug", derive(Debug))]
pub struct SNormToUNorm;
#[derive(Default, PartialEq, Clone, Copy)]
#[cfg_attr(feature = "bevy_reflect", derive(bevy_reflect::Reflect))]
#[cfg_attr(feature = "serialize", derive(serde::Serialize))]
#[cfg_attr(feature = "debug", derive(Debug))]
pub struct UNormToSNorm;
#[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 Pow2;
#[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 Pow3;
#[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 Pow4;
#[derive(Default, Clone, Copy, PartialEq)]
#[cfg_attr(feature = "bevy_reflect", derive(bevy_reflect::Reflect))]
#[cfg_attr(feature = "serialize", derive(serde::Serialize))]
#[cfg_attr(feature = "debug", derive(Debug))]
pub struct PowF(pub f32);
#[derive(Default, Clone, Copy, PartialEq)]
#[cfg_attr(feature = "bevy_reflect", derive(bevy_reflect::Reflect))]
#[cfg_attr(feature = "serialize", derive(serde::Serialize))]
#[cfg_attr(feature = "debug", derive(Debug))]
pub struct PowI(pub i32);
#[derive(Default, Clone, Copy, PartialEq)]
#[cfg_attr(feature = "bevy_reflect", derive(bevy_reflect::Reflect))]
#[cfg_attr(feature = "serialize", derive(serde::Serialize))]
#[cfg_attr(feature = "debug", derive(Debug))]
pub struct Sqrt;
#[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 PositiveApproachZero;
#[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 Abs;
#[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 Inverse;
#[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 ReverseUNorm;
#[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 Negate;
pub type Billow = (Abs, UNormToSNorm);
#[derive(Clone, Copy, PartialEq)]
#[cfg_attr(feature = "bevy_reflect", derive(bevy_reflect::Reflect))]
#[cfg_attr(feature = "serialize", derive(serde::Serialize))]
#[cfg_attr(feature = "debug", derive(Debug))]
pub struct Wrapped(pub f32);
macro_rules! impl_vector_spaces {
(scalar $n:ty) => {
impl_vector_spaces!(both $n);
impl NoiseFunction<$n> for Abs {
type Output = $n;
#[inline]
fn evaluate(&self, input: $n, _seeds: &mut crate::rng::NoiseRng) -> Self::Output {
bevy_math::ops::abs(input)
}
}
impl NoiseFunction<$n> for PowF {
type Output = $n;
#[inline]
fn evaluate(&self, input: $n, _seeds: &mut crate::rng::NoiseRng) -> Self::Output {
bevy_math::ops::powf(input, self.0)
}
}
impl NoiseFunction<$n> for PowI {
type Output = $n;
#[inline]
fn evaluate(&self, input: $n, _seeds: &mut crate::rng::NoiseRng) -> Self::Output {
input.powi(self.0)
}
}
impl NoiseFunction<$n> for Sqrt {
type Output = $n;
#[inline]
fn evaluate(&self, input: $n, _seeds: &mut crate::rng::NoiseRng) -> Self::Output {
bevy_math::ops::sqrt(input)
}
}
};
(vec $n:ty) => {
impl_vector_spaces!(both $n);
impl NoiseFunction<$n> for Abs {
type Output = $n;
#[inline]
fn evaluate(&self, input: $n, _seeds: &mut crate::rng::NoiseRng) -> Self::Output {
input.abs()
}
}
impl NoiseFunction<$n> for PowF {
type Output = $n;
#[inline]
fn evaluate(&self, input: $n, _seeds: &mut crate::rng::NoiseRng) -> Self::Output {
input.powf(self.0)
}
}
impl NoiseFunction<$n> for Sqrt {
type Output = $n;
#[inline]
fn evaluate(&self, input: $n, _seeds: &mut crate::rng::NoiseRng) -> Self::Output {
input.map(bevy_math::ops::sqrt)
}
}
impl NoiseFunction<$n> for PowI {
type Output = $n;
#[inline]
fn evaluate(&self, input: $n, _seeds: &mut crate::rng::NoiseRng) -> Self::Output {
input.map(|v| v.powi(self.0))
}
}
};
(both $n:ty) => {
impl NoiseFunction<$n> for SNormToUNorm {
type Output = $n;
#[inline]
fn evaluate(&self, input: $n, _seeds: &mut crate::rng::NoiseRng) -> Self::Output {
input * 0.5 + 0.5
}
}
impl NoiseFunction<$n> for UNormToSNorm {
type Output = $n;
#[inline]
fn evaluate(&self, input: $n, _seeds: &mut crate::rng::NoiseRng) -> Self::Output {
(input - 0.5) * 2.0
}
}
impl NoiseFunction<$n> for Pow2 {
type Output = $n;
#[inline]
fn evaluate(&self, input: $n, _seeds: &mut crate::rng::NoiseRng) -> Self::Output {
input * input
}
}
impl NoiseFunction<$n> for Pow3 {
type Output = $n;
#[inline]
fn evaluate(&self, input: $n, _seeds: &mut crate::rng::NoiseRng) -> Self::Output {
input * input * input
}
}
impl NoiseFunction<$n> for Pow4 {
type Output = $n;
#[inline]
fn evaluate(&self, input: $n, _seeds: &mut crate::rng::NoiseRng) -> Self::Output {
(input * input) * (input * input)
}
}
impl NoiseFunction<$n> for PositiveApproachZero {
type Output = $n;
#[inline]
fn evaluate(&self, input: $n, _seeds: &mut crate::rng::NoiseRng) -> Self::Output {
1.0 / (input + 1.0)
}
}
impl NoiseFunction<$n> for Inverse {
type Output = $n;
#[inline]
fn evaluate(&self, input: $n, _seeds: &mut crate::rng::NoiseRng) -> Self::Output {
1.0 / input
}
}
impl NoiseFunction<$n> for ReverseUNorm {
type Output = $n;
#[inline]
fn evaluate(&self, input: $n, _seeds: &mut crate::rng::NoiseRng) -> Self::Output {
1.0 - input
}
}
impl NoiseFunction<$n> for Negate {
type Output = $n;
#[inline]
fn evaluate(&self, input: $n, _seeds: &mut crate::rng::NoiseRng) -> Self::Output {
-input
}
}
impl NoiseFunction<$n> for Wrapped {
type Output = $n;
#[inline]
fn evaluate(&self, input: $n, _seeds: &mut crate::rng::NoiseRng) -> Self::Output {
input % self.0
}
}
};
}
impl_vector_spaces!(scalar f32);
impl_vector_spaces!(vec Vec2);
impl_vector_spaces!(vec Vec3);
impl_vector_spaces!(vec Vec3A);
impl_vector_spaces!(vec Vec4);
#[derive(Clone, Copy, PartialEq)]
#[cfg_attr(feature = "bevy_reflect", derive(bevy_reflect::Reflect))]
#[cfg_attr(feature = "serialize", derive(serde::Serialize))]
#[cfg_attr(feature = "debug", derive(Debug))]
pub struct PingPong(pub f32);
impl Default for PingPong {
fn default() -> Self {
Self(1.0)
}
}
impl NoiseFunction<f32> for PingPong {
type Output = f32;
#[inline]
fn evaluate(&self, input: f32, _seeds: &mut crate::rng::NoiseRng) -> Self::Output {
let t = (input + 1.0) * self.0;
let t = t - (t * 0.5).trunc() * 2.;
if t < 1.0 { t } else { 2. - 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 NoiseCurve<C>(pub C);
impl<C: Curve<f32>> NoiseFunction<f32> for NoiseCurve<C> {
type Output = f32;
#[inline]
fn evaluate(&self, input: f32, _seeds: &mut crate::rng::NoiseRng) -> Self::Output {
self.0.sample_unchecked(input)
}
}
#[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 NoiseCurveClamped<C>(pub C);
impl<C: Curve<f32>> NoiseFunction<f32> for NoiseCurveClamped<C> {
type Output = f32;
#[inline]
fn evaluate(&self, input: f32, _seeds: &mut crate::rng::NoiseRng) -> Self::Output {
self.0.sample_clamped(input)
}
}
macro_rules! impl_mapped_vector_spaces {
($n:ty) => {
impl NoiseFunction<$n> for PingPong {
type Output = $n;
#[inline]
fn evaluate(&self, input: $n, _seeds: &mut crate::rng::NoiseRng) -> Self::Output {
input.map(|v| self.evaluate(v, &mut crate::rng::NoiseRng(0)))
}
}
impl<C: Curve<f32>> NoiseFunction<$n> for NoiseCurveClamped<C> {
type Output = $n;
#[inline]
fn evaluate(&self, input: $n, _seeds: &mut crate::rng::NoiseRng) -> Self::Output {
input.map(|v| self.evaluate(v, &mut crate::rng::NoiseRng(0)))
}
}
impl<C: Curve<f32>> NoiseFunction<$n> for NoiseCurve<C> {
type Output = $n;
#[inline]
fn evaluate(&self, input: $n, _seeds: &mut crate::rng::NoiseRng) -> Self::Output {
input.map(|v| self.evaluate(v, &mut crate::rng::NoiseRng(0)))
}
}
};
}
impl_mapped_vector_spaces!(Vec2);
impl_mapped_vector_spaces!(Vec3);
impl_mapped_vector_spaces!(Vec3A);
impl_mapped_vector_spaces!(Vec4);
#[derive(Clone, Copy, PartialEq)]
#[cfg_attr(feature = "bevy_reflect", derive(bevy_reflect::Reflect))]
#[cfg_attr(feature = "serialize", derive(serde::Serialize))]
#[cfg_attr(feature = "debug", derive(Debug))]
pub struct Spiral<L>(pub L, f32);
impl<L: Default> Default for Spiral<L> {
fn default() -> Self {
Self(L::default(), 1.0)
}
}
impl<L: LengthFunction<Vec2>> NoiseFunction<Vec2> for Spiral<L> {
type Output = Vec2;
#[inline]
fn evaluate(&self, input: Vec2, _seeds: &mut crate::rng::NoiseRng) -> Self::Output {
let len = self.0.length_of(input);
let theta = input.to_angle() * core::f32::consts::FRAC_1_PI * self.1;
Vec2::new(theta * len.floor(), len)
}
}
impl<T, G: Mul<f32, Output = G>> NoiseFunction<WithGradient<T, G>> for SNormToUNorm
where
Self: NoiseFunction<T, Output = T>,
{
type Output = WithGradient<T, G>;
#[inline]
fn evaluate(
&self,
input: WithGradient<T, G>,
seeds: &mut crate::rng::NoiseRng,
) -> Self::Output {
WithGradient {
value: self.evaluate(input.value, seeds),
gradient: input.gradient * 0.5,
}
}
}
impl<T, G: Mul<f32, Output = G>> NoiseFunction<WithGradient<T, G>> for UNormToSNorm
where
Self: NoiseFunction<T, Output = T>,
{
type Output = WithGradient<T, G>;
#[inline]
fn evaluate(
&self,
input: WithGradient<T, G>,
seeds: &mut crate::rng::NoiseRng,
) -> Self::Output {
WithGradient {
value: self.evaluate(input.value, seeds),
gradient: input.gradient * 2.0,
}
}
}
impl<T, G> NoiseFunction<WithGradient<T, G>> for Negate
where
Self: NoiseFunction<T> + NoiseFunction<G>,
{
type Output =
WithGradient<<Self as NoiseFunction<T>>::Output, <Self as NoiseFunction<G>>::Output>;
#[inline]
fn evaluate(
&self,
input: WithGradient<T, G>,
seeds: &mut crate::rng::NoiseRng,
) -> Self::Output {
WithGradient {
value: self.evaluate(input.value, seeds),
gradient: self.evaluate(input.gradient, seeds),
}
}
}
impl<G: Neg<Output = G>> NoiseFunction<WithGradient<f32, G>> for Abs {
type Output = WithGradient<f32, G>;
#[inline]
fn evaluate(
&self,
input: WithGradient<f32, G>,
_seeds: &mut crate::rng::NoiseRng,
) -> Self::Output {
if input.value > 0.0 {
input
} else {
WithGradient {
value: -input.value,
gradient: -input.gradient,
}
}
}
}
impl<G: Mul<f32, Output = G>> NoiseFunction<WithGradient<f32, G>> for Inverse {
type Output = WithGradient<f32, G>;
#[inline]
fn evaluate(
&self,
input: WithGradient<f32, G>,
_seeds: &mut crate::rng::NoiseRng,
) -> Self::Output {
WithGradient {
value: 1.0 / input.value,
gradient: input.gradient * (-1.0 / (input.value * input.value)),
}
}
}
impl<G: Mul<f32, Output = G>> NoiseFunction<WithGradient<f32, G>> for Pow2 {
type Output = WithGradient<f32, G>;
#[inline]
fn evaluate(
&self,
input: WithGradient<f32, G>,
_seeds: &mut crate::rng::NoiseRng,
) -> Self::Output {
WithGradient {
value: input.value * input.value,
gradient: input.gradient * (2.0 * input.value),
}
}
}
impl<G: Mul<f32, Output = G>> NoiseFunction<WithGradient<f32, G>> for Pow3 {
type Output = WithGradient<f32, G>;
#[inline]
fn evaluate(
&self,
input: WithGradient<f32, G>,
_seeds: &mut crate::rng::NoiseRng,
) -> Self::Output {
WithGradient {
value: input.value * input.value * input.value,
gradient: input.gradient * (3.0 * input.value * input.value),
}
}
}
impl<G: Mul<f32, Output = G>> NoiseFunction<WithGradient<f32, G>> for Pow4 {
type Output = WithGradient<f32, G>;
#[inline]
fn evaluate(
&self,
input: WithGradient<f32, G>,
_seeds: &mut crate::rng::NoiseRng,
) -> Self::Output {
WithGradient {
value: (input.value * input.value) * (input.value * input.value),
gradient: input.gradient * (4.0 * (input.value * input.value) * input.value),
}
}
}
impl<G: Mul<f32, Output = G>> NoiseFunction<WithGradient<f32, G>> for PowF {
type Output = WithGradient<f32, G>;
#[inline]
fn evaluate(
&self,
input: WithGradient<f32, G>,
_seeds: &mut crate::rng::NoiseRng,
) -> Self::Output {
WithGradient {
value: bevy_math::ops::powf(input.value, self.0),
gradient: input.gradient * (self.0 * bevy_math::ops::powf(input.value, self.0 - 1.0)),
}
}
}
impl<T, G: Neg<Output = G>> NoiseFunction<WithGradient<T, G>> for ReverseUNorm
where
Self: NoiseFunction<T>,
{
type Output = WithGradient<<Self as NoiseFunction<T>>::Output, G>;
#[inline]
fn evaluate(
&self,
input: WithGradient<T, G>,
seeds: &mut crate::rng::NoiseRng,
) -> Self::Output {
WithGradient {
value: self.evaluate(input.value, seeds),
gradient: -input.gradient,
}
}
}