// Copyright (c) 2012-2022 Wojciech Figat. All rights reserved. #pragma once #include "Types/BaseTypes.h" #include "Math/Vector3.h" #include "Math/Math.h" #include /// /// Very basic pseudo numbers generator. /// class FLAXENGINE_API RandomStream { private: /// /// Holds the initial seed. /// int32 _initialSeed; /// /// Holds the current seed. /// mutable int32 _seed; public: /// /// Init /// RandomStream() : _initialSeed(0) , _seed(0) { } /// /// Creates and initializes a new random stream from the specified seed value. /// /// The seed value. RandomStream(int32 seed) : _initialSeed(seed) , _seed(seed) { } public: /// /// Gets initial seed value /// int32 GetInitialSeed() const { return _initialSeed; } public: /// /// Gets the current seed. /// int32 GetCurrentSeed() const { return _seed; } /// /// Initializes this random stream with the specified seed value. /// /// The seed value. void Initialize(int32 seed) { _initialSeed = seed; _seed = seed; } /// /// Resets this random stream to the initial seed value. /// void Reset() const { _seed = _initialSeed; } /// /// Generates a new random seed. /// void GenerateNewSeed() { Initialize(rand()); } public: /// /// Returns a random boolean. /// bool GetBool() const { MutateSeed(); return *(uint32*)&_seed < (MAX_uint32 / 2); } /// /// Returns a random number between 0 and MAX_uint32. /// uint32 GetUnsignedInt() const { MutateSeed(); return *(uint32*)&_seed; } /// /// Returns a random number between 0 and 1. /// float GetFraction() const { MutateSeed(); const float temp = 1.0f; float result; *(int32*)&result = (*(int32*)&temp & 0xff800000) | (_seed & 0x007fffff); return Math::Fractional(result); } /// /// Returns a random number between 0 and 1. /// FORCE_INLINE float Rand() const { return GetFraction(); } /// /// Returns a random vector of unit size. /// Float3 GetUnitVector() const { 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 < ZeroTolerance); return Float3::Normalize(result); } /// /// Gets a random with components in a range between [0;1]. /// Vector3 GetVector3() const { return Vector3(GetFraction(), GetFraction(), GetFraction()); } /// /// Helper function for rand implementations. /// /// Top border /// A random number in [0..A) FORCE_INLINE int32 RandHelper(int32 a) const { return a > 0 ? Math::TruncToInt(GetFraction() * ((float)a - ZeroTolerance)) : 0; } /// /// Helper function for rand implementations /// /// Minimum value /// Maximum value /// A random number in [min; max] range FORCE_INLINE int32 RandRange(int32 min, int32 max) const { const int32 range = max - min + 1; return min + RandHelper(range); } /// /// Helper function for rand implementations /// /// Minimum value /// Maximum value /// A random number in [min; max] range FORCE_INLINE float RandRange(float min, float max) const { return min + (max - min) * Rand(); } protected: /// /// Mutates the current seed into the next seed. /// void MutateSeed() const { // This can be modified to provide better randomization _seed = _seed * 196314165 + 907633515; } };