// Copyright (c) Wojciech Figat. All rights reserved. using System.Runtime.CompilerServices; #pragma warning disable 675 namespace FlaxEngine { /// /// Very basic pseudo numbers generator. /// [HideInEditor] public class RandomStream { /// /// Holds the initial seed. /// private int _initialSeed; /// /// Holds the current seed. /// private int _seed; /// /// Init /// public RandomStream() { _initialSeed = 0; _seed = 0; } /// /// Creates and initializes a new random stream from the specified seed value. /// /// The seed value. public RandomStream(int seed) { _initialSeed = seed; _seed = seed; } /// /// Gets initial seed value /// public int GetInitialSeed() { return _initialSeed; } /// /// Gets the current seed. /// public int GetCurrentSeed() { return _seed; } /// /// Initializes this random stream with the specified seed value. /// /// The seed value. public void Initialize(int seed) { _initialSeed = seed; _seed = seed; } /// /// Resets this random stream to the initial seed value. /// public void Reset() { _seed = _initialSeed; } /// /// Generates a new random seed. /// public void GenerateNewSeed() { Initialize(new System.Random().Next()); } /// /// Returns a random boolean. /// public unsafe bool GetBool() { MutateSeed(); fixed (int* seedPtr = &_seed) return *seedPtr < (uint.MaxValue / 2); } /// /// Returns a random number between 0 and uint.MaxValue. /// public unsafe uint GetUnsignedInt() { MutateSeed(); fixed (int* seedPtr = &_seed) return (uint)*seedPtr; } /// /// Returns a random number between 0 and 1. /// public unsafe float GetFraction() { MutateSeed(); float temp = 1.0f; float result = 0.0f; *(int*)&result = (int)((*(int*)&temp & 0xff800000) | (_seed & 0x007fffff)); return Mathf.Frac(result); } /// /// Returns a random number between 0 and 1. /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public float Rand() { return GetFraction(); } /// /// Returns a random vector of unit size. /// public Float3 GetUnitVector() { Float3 result; float l; do { result.X = GetFraction() * 2.0f - 1.0f; result.Y = GetFraction() * 2.0f - 1.0f; result.Z = GetFraction() * 2.0f - 1.0f; l = result.LengthSquared; } while (l > 1.0f || l < Mathf.Epsilon); return Float3.Normalize(result); } /// /// Gets a random with components in a range between [0;1]. /// public Vector3 GetVector3() { return new Vector3(GetFraction(), GetFraction(), GetFraction()); } /// /// Helper function for rand implementations. /// /// Top border /// A random number in [0..A) [MethodImpl(MethodImplOptions.AggressiveInlining)] public int RandHelper(int a) { return a > 0 ? Mathf.FloorToInt(GetFraction() * ((float)a - Mathf.Epsilon)) : 0; } /// /// Helper function for rand implementations /// /// Minimum value /// Maximum value /// A random number in [min; max] range [MethodImpl(MethodImplOptions.AggressiveInlining)] public int RandRange(int min, int max) { int range = max - min + 1; return min + RandHelper(range); } /// /// Helper function for rand implementations /// /// Minimum value /// Maximum value /// A random number in [min; max] range [MethodImpl(MethodImplOptions.AggressiveInlining)] public float RandRange(float min, float max) { return min + (max - min) * Rand(); } /// /// Mutates the current seed into the next seed. /// protected void MutateSeed() { // This can be modified to provide better randomization _seed = _seed * 196314165 + 907633515; } } }