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>
66 lines
1.7 KiB
C#
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);
|
|
}
|