// 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;
}
}
}