use core::marker::PhantomData;
use bevy_math::{IVec2, IVec3, IVec4, UVec2, UVec3, UVec4, Vec2, Vec3, Vec3A, Vec4};
use crate::NoiseFunction;
#[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 NoiseRng(pub u32);
pub trait NoiseRngInput {
fn collapse_for_rng(self) -> u32;
}
impl NoiseRng {
const KEY: u32 = 249_222_277;
#[inline(always)]
pub fn re_seed(&mut self) {
self.0 = Self::KEY.wrapping_mul(self.0 ^ Self::KEY);
}
#[inline(always)]
pub fn rand_u32(&self, input: impl NoiseRngInput) -> u32 {
let i = input.collapse_for_rng();
let mut x = i;
x ^= x.rotate_right(17);
x = x.wrapping_mul(Self::KEY);
x ^= x.rotate_right(11) ^ self.0;
x = x.wrapping_mul(!Self::KEY);
x
}
}
mod float_rng {
#![expect(
clippy::unusual_byte_groupings,
reason = "In float rng, we do bit tricks and want to show what each part does."
)]
#[inline(always)]
pub fn any_rng_float_32(bits: u32) -> f32 {
const BASE_VALUE: u32 = 0b_0_01111111_00000000_00000000_0111111;
const BIT_MASK: u32 = (u16::MAX as u32) << 7;
let result = BASE_VALUE | (bits & BIT_MASK);
f32::from_bits(result)
}
#[inline(always)]
pub fn any_rng_float_16(bits: u16) -> f32 {
const BASE_VALUE: u32 = 0b_0_01111111_00000000_00000000_0111111;
let bits = bits as u32;
let result = BASE_VALUE | (bits << 7);
f32::from_bits(result)
}
#[inline(always)]
pub fn any_rng_float_8(bits: u8) -> f32 {
const BASE_VALUE: u32 = 0b_0_01111111_00000000_011111111111111;
let bits = bits as u32;
let result = BASE_VALUE | (bits << 15);
f32::from_bits(result)
}
#[inline(always)]
pub fn any_signed_rng_float_32(bits: u32) -> f32 {
const BASE_VALUE: u32 = 0b0_01111111_00000000_0000000_01111111;
const BIT_MASK: u32 = (u16::MAX as u32 & !1) << 7;
let result = BASE_VALUE | (bits & BIT_MASK) | (bits << 31);
f32::from_bits(result)
}
#[inline(always)]
pub fn any_signed_rng_float_16(bits: u16) -> f32 {
const BASE_VALUE: u32 = 0b0_01111111_00000000_0000000_01111111;
let bits = bits as u32;
let result = BASE_VALUE | ((bits & !1) << 7) | (bits << 31);
f32::from_bits(result)
}
#[inline(always)]
pub fn any_signed_rng_float_8(bits: u8) -> f32 {
const BASE_VALUE: u32 = 0b0_01111111_00000000_01111111_11111111;
let bits = bits as u32;
let result = BASE_VALUE | ((bits & !1) << 15) | (bits << 31);
f32::from_bits(result)
}
#[inline(always)]
pub fn any_half_rng_float_32(bits: u32) -> f32 {
const BASE_VALUE: u32 = 0b_0_01111111_0_00000000_00000000_011111;
const BIT_MASK: u32 = (u16::MAX as u32) << 6;
let result = BASE_VALUE | (bits & BIT_MASK);
f32::from_bits(result)
}
#[inline(always)]
pub fn any_half_rng_float_16(bits: u16) -> f32 {
const BASE_VALUE: u32 = 0b_0_01111111_0_00000000_00000000_011111;
let bits = bits as u32;
let result = BASE_VALUE | (bits << 6);
f32::from_bits(result)
}
#[inline(always)]
pub fn any_half_rng_float_8(bits: u8) -> f32 {
const BASE_VALUE: u32 = 0b_0_01111111_0_00000000_01111111111111;
let bits = bits as u32;
let result = BASE_VALUE | (bits << 14);
f32::from_bits(result)
}
}
pub use float_rng::*;
#[inline(always)]
pub fn force_float_non_zero(f: f32) -> f32 {
f32::from_bits(f.to_bits() | 0b1111)
}
impl NoiseRngInput for u32 {
#[inline(always)]
fn collapse_for_rng(self) -> u32 {
self
}
}
impl NoiseRngInput for UVec2 {
#[inline(always)]
fn collapse_for_rng(self) -> u32 {
(self.x ^ 983742189).wrapping_add((self.y ^ 102983473).rotate_left(8))
}
}
impl NoiseRngInput for UVec3 {
#[inline(always)]
fn collapse_for_rng(self) -> u32 {
(self.x ^ 983742189)
.wrapping_add((self.y ^ 102983473).rotate_left(8))
.wrapping_add((self.z ^ 189203473).rotate_left(16))
}
}
impl NoiseRngInput for UVec4 {
#[inline(always)]
fn collapse_for_rng(self) -> u32 {
(self.x ^ 983742189)
.wrapping_add((self.y ^ 102983473).rotate_left(8))
.wrapping_add((self.z ^ 189203473).rotate_left(16))
.wrapping_add((self.w ^ 137920743).rotate_left(24))
}
}
impl NoiseRngInput for IVec2 {
#[inline(always)]
fn collapse_for_rng(self) -> u32 {
self.as_uvec2().collapse_for_rng()
}
}
impl NoiseRngInput for IVec3 {
#[inline(always)]
fn collapse_for_rng(self) -> u32 {
self.as_uvec3().collapse_for_rng()
}
}
impl NoiseRngInput for IVec4 {
#[inline(always)]
fn collapse_for_rng(self) -> u32 {
self.as_uvec4().collapse_for_rng()
}
}
pub trait AnyValueFromBits<T> {
fn linear_equivalent_value(&self, bits: u32) -> T;
fn finish_linear_equivalent_value(&self, value: T) -> T;
fn finishing_derivative(&self) -> f32;
#[inline]
fn any_value(&self, bits: u32) -> T {
self.finish_linear_equivalent_value(self.linear_equivalent_value(bits))
}
}
pub trait ConcreteAnyValueFromBits: AnyValueFromBits<Self::Concrete> {
type Concrete;
}
#[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 Random<R, T>(pub R, pub PhantomData<T>);
impl<O, R: AnyValueFromBits<O>> AnyValueFromBits<O> for Random<R, O> {
#[inline(always)]
fn linear_equivalent_value(&self, bits: u32) -> O {
self.0.linear_equivalent_value(bits)
}
#[inline(always)]
fn finish_linear_equivalent_value(&self, value: O) -> O {
self.0.finish_linear_equivalent_value(value)
}
#[inline(always)]
fn finishing_derivative(&self) -> f32 {
self.0.finishing_derivative()
}
#[inline(always)]
fn any_value(&self, bits: u32) -> O {
self.0.any_value(bits)
}
}
impl<O, R: AnyValueFromBits<O>> ConcreteAnyValueFromBits for Random<R, O> {
type Concrete = O;
}
impl<I: NoiseRngInput, O, R: AnyValueFromBits<O>> NoiseFunction<I> for Random<R, O> {
type Output = O;
#[inline]
fn evaluate(&self, input: I, seeds: &mut NoiseRng) -> Self::Output {
let bits = seeds.rand_u32(input);
self.0.any_value(bits)
}
}
#[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 UNorm;
#[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 UNormHalf;
#[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 SNorm;
#[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 SNormSplit;
macro_rules! impl_norms {
($t:ty, $builder:expr, $split_builder:expr, $half_builder:expr) => {
impl AnyValueFromBits<$t> for UNorm {
#[inline]
fn linear_equivalent_value(&self, bits: u32) -> $t {
$builder(bits)
}
#[inline(always)]
fn finish_linear_equivalent_value(&self, value: $t) -> $t {
value - 1.0
}
#[inline(always)]
fn finishing_derivative(&self) -> f32 {
1.0
}
}
impl AnyValueFromBits<$t> for UNormHalf {
#[inline]
fn linear_equivalent_value(&self, bits: u32) -> $t {
$half_builder(bits)
}
#[inline(always)]
fn finish_linear_equivalent_value(&self, value: $t) -> $t {
value - 1.0
}
#[inline(always)]
fn finishing_derivative(&self) -> f32 {
1.0
}
}
impl AnyValueFromBits<$t> for SNorm {
#[inline]
fn linear_equivalent_value(&self, bits: u32) -> $t {
$builder(bits)
}
#[inline(always)]
fn finish_linear_equivalent_value(&self, value: $t) -> $t {
value * 2.0 - 3.0
}
#[inline(always)]
fn finishing_derivative(&self) -> f32 {
2.0
}
}
impl AnyValueFromBits<$t> for SNormSplit {
#[inline]
fn linear_equivalent_value(&self, bits: u32) -> $t {
$split_builder(bits)
}
#[inline(always)]
fn finish_linear_equivalent_value(&self, value: $t) -> $t {
value * -value.signum()
}
#[inline(always)]
fn finishing_derivative(&self) -> f32 {
1.0
}
}
};
}
impl_norms!(
f32,
any_rng_float_32,
any_signed_rng_float_32,
any_half_rng_float_32
);
impl_norms!(
Vec2,
|bits| Vec2::new(
any_rng_float_16((bits >> 16) as u16),
any_rng_float_16(bits as u16),
),
|bits| Vec2::new(
any_signed_rng_float_16((bits >> 16) as u16),
any_signed_rng_float_16(bits as u16),
),
|bits| Vec2::new(
any_half_rng_float_16((bits >> 16) as u16),
any_half_rng_float_16(bits as u16),
)
);
impl_norms!(
Vec3,
|bits| Vec3::new(
any_rng_float_8((bits >> 24) as u8),
any_rng_float_8((bits >> 16) as u8),
any_rng_float_8((bits >> 8) as u8),
),
|bits| Vec3::new(
any_signed_rng_float_8((bits >> 24) as u8),
any_signed_rng_float_8((bits >> 16) as u8),
any_signed_rng_float_8((bits >> 8) as u8),
),
|bits| Vec3::new(
any_half_rng_float_8((bits >> 24) as u8),
any_half_rng_float_8((bits >> 16) as u8),
any_half_rng_float_8((bits >> 8) as u8),
)
);
impl_norms!(
Vec3A,
|bits| Vec3A::new(
any_rng_float_8((bits >> 24) as u8),
any_rng_float_8((bits >> 16) as u8),
any_rng_float_8((bits >> 8) as u8),
),
|bits| Vec3A::new(
any_signed_rng_float_8((bits >> 24) as u8),
any_signed_rng_float_8((bits >> 16) as u8),
any_signed_rng_float_8((bits >> 8) as u8),
),
|bits| Vec3A::new(
any_half_rng_float_8((bits >> 24) as u8),
any_half_rng_float_8((bits >> 16) as u8),
any_half_rng_float_8((bits >> 8) as u8),
)
);
impl_norms!(
Vec4,
|bits| Vec4::new(
any_rng_float_8((bits >> 24) as u8),
any_rng_float_8((bits >> 16) as u8),
any_rng_float_8((bits >> 8) as u8),
any_rng_float_8(bits as u8),
),
|bits| Vec4::new(
any_signed_rng_float_8((bits >> 24) as u8),
any_signed_rng_float_8((bits >> 16) as u8),
any_signed_rng_float_8((bits >> 8) as u8),
any_signed_rng_float_8(bits as u8),
),
|bits| Vec4::new(
any_half_rng_float_8((bits >> 24) as u8),
any_half_rng_float_8((bits >> 16) as u8),
any_half_rng_float_8((bits >> 8) as u8),
any_half_rng_float_8(bits as u8),
)
);