CultLib/packages/cultmath/src/CultMath/Random.cs
Meta Vens d514efebba Make CultMath HLSL-shaped: writable components, bool-vector comparisons
HLSL is now CultMath's semantic authority where it defines one.

- float2/3/4, int2, double2/3, bool2 and quaternion are plain structs with
  public mutable fields instead of record structs. Indexers and swizzles
  (float2.yx; float3 xy xz yx yz zy xyz xzy yzx zyx; float4 xy xyz xyw yzx)
  have setters.
- ==, !=, <, >, <=, >= are component-wise and return bool2/3/4. Equals and
  GetHashCode stay value-based so vectors remain dictionary keys.
  quaternion is not an HLSL type and keeps a bool ==.
- Scalar/vector arithmetic and comparisons get explicit overloads on both
  sides instead of leaning on implicit splat.
- New types: bool3, bool4, int3, int4, float2x2, float3x3 (row-major like
  HLSL, _mRC fields, Rotate / RotateX/Y/Z / Euler with math.RotationOrder).
- New intrinsics: mul (matrix-vector both sides, matrix-matrix), any, all,
  select (HLSL argument order), log, vector pow/sqrt/sin/cos/acos/atan2,
  double min/max, int3/int4/bool3/bool4/float2x2/float3x3 constructor
  functions.
- simplex_noise is renamed snoise and gains the Ashima 3D variant; the HLSL
  mirror follows as cultmath_snoise(float2/float3).
- Random gains NextFloat3() and NextFloat3(float3 max) on the same draw order.

Tests pin snoise(float3), float3x3.Euler and float2x2.Rotate to
Unity.Mathematics reference values, and an HLSL-shaped source block compiles
under using static CultMath.math.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-14 13:29:59 +02:00

66 lines
1.7 KiB
C#

namespace CultMath;
public struct Random
{
private const uint DefaultSeed = 0x6E624EB7u;
public uint state;
public Random(uint seed)
{
state = seed == 0 ? DefaultSeed : seed;
}
public static Random CreateFromIndex(uint index) => new(index + DefaultSeed);
public void InitState(uint seed)
{
state = seed == 0 ? DefaultSeed : seed;
}
public uint NextUInt()
{
var x = state == 0 ? DefaultSeed : state;
x ^= x << 13;
x ^= x >> 17;
x ^= x << 5;
state = x == 0 ? DefaultSeed : x;
return state;
}
public int NextInt(int max) => NextInt(0, max);
public int NextInt(int min, int max)
{
if (max <= min)
{
return min;
}
return min + (int)(NextUInt() % (uint)(max - min));
}
public float NextFloat() => (NextUInt() >> 8) * (1.0f / 16777216.0f);
public float NextFloat(float max) => NextFloat() * max;
public float NextFloat(float min, float max) => min + NextFloat() * (max - min);
public float2 NextFloat2() => new(NextFloat(), NextFloat());
public float2 NextFloat2(float min, float max) => new(NextFloat(min, max), NextFloat(min, max));
public float2 NextFloat2(float2 min, float2 max) => min + NextFloat2() * (max - min);
public float2 NextFloat2Direction()
{
var angle = NextFloat(0.0f, math.TAU);
return new float2(math.cos(angle), math.sin(angle));
}
public float3 NextFloat3() => new(NextFloat(), NextFloat(), NextFloat());
public float3 NextFloat3(float3 max) => NextFloat3() * max;
public float3 NextFloat3(float3 min, float3 max) => min + NextFloat3() * (max - min);
}