Aetheria/Assets/Plugins/Celestial Body/Scripts/Script Utilities/PRNG.cs
Reinier Vens 53a91351b7 Procedural Planets
Integrated Sebastian Lague's Planet Generator
Created Tour function in SectorRenderer which makes the camera follow each terrestrial planet in turn
2020-12-05 23:43:02 +00:00

231 lines
No EOL
6.2 KiB
C#

using System;
using System.Collections.Generic;
using UnityEngine;
public class PRNG {
public enum Weight { None, Lower, Upper, Centre, Ends }
System.Random prng;
int seed;
public int Seed {
get {
return seed;
}
}
public PRNG (int seed) {
this.seed = seed;
prng = new System.Random (this.seed);
}
public PRNG (string seed) {
this.seed = seed.GetHashCode ();
prng = new System.Random (this.seed);
}
public PRNG () {
prng = new System.Random ();
}
/// Returns a random integer value [min, max)
public int Range (int min, int max) {
return prng.Next (min, max);
}
/// Returns a random float value [min, max)
public float Range (float min, float max) {
return Mathf.Lerp (min, max, (float) prng.NextDouble ());
}
// Returns a vector4 where each component is a random number in range [min, max)
public Vector4 RangeVector4 (float minInclusive, float maxExclusive) {
Vector4 vector = Vector4.zero;
for (int i = 0; i < 4; i++) {
vector[i] = Range (minInclusive, maxExclusive);
}
return vector;
}
/// Random value [0, 1]
public float Value () {
// According to stackoverflow this should technically allow the random value to equal 1
const double maxExclusive = 1.0000000004656612875245796924106;
return (float) (prng.NextDouble () * maxExclusive);
}
/// Random value [0, 1]
/// Output is increasingly biased toward 1 as biasStrength goes from 0 to 1
public float ValueBiasUpper (float biasStrength) {
return 1 - ValueBiasLower (biasStrength);
}
/// Random value [0, 1]
/// Output is increasingly biased toward 0 as biasStrength goes from 0 to 1
public float ValueBiasLower (float biasStrength) {
float t = Value ();
// Avoid possible division by zero
if (biasStrength == 1) {
return 0;
}
// Remap strength for nicer input -> output relationship
float k = Mathf.Clamp01 (1 - biasStrength);
k = k * k * k - 1;
// Thanks to www.shadertoy.com/view/Xd2yRd
return Mathf.Clamp01 ((t + t * k) / (t * k + 1));
}
/// Random value [0, 1]
/// Output is increasingly biased toward the extremes (0 or 1) as biasStrength goes from 0 to 1
public float ValueBiasExtremes (float biasStrength) {
float t = ValueBiasLower (biasStrength);
return (Value () < 0.5f) ? t : 1 - t;
}
/// Random value [0, 1]
/// Output is increasingly biased toward 0.5 as biasStrength goes from 0 to 1
public float ValueBiasCentre (float biasStrength) {
float t = ValueBiasLower (biasStrength);
return 0.5f + t * 0.5f * Sign ();
}
// ---- Signed versions [-1, 1] ---
/// Random value [-1, 1]
public float SignedValue () {
return Value () * 2 - 1;
}
/// Random value [-1, 1]
/// Output is increasingly biased toward the extremes (-1 or 1) as biasStrength goes from 0 to 1
public float SignedValueBiasExtremes (float biasStrength) {
return ValueBiasExtremes (biasStrength) * 2 - 1;
}
/// Random value [-1, 1]
/// Output is increasingly biased toward 0 as biasStrength goes from 0 to 1
public float SignedValueBiasCentre (float biasStrength) {
return ValueBiasCentre (biasStrength) * 2 - 1;
}
// Returns a weighted value in range [min, max)
public float WeightedRange (float min, float max, Weight weight, int weightStrength = 4) {
float value01 = WeightedValue (weight, weightStrength);
return Mathf.Lerp (min, max, value01);
}
// Returns a weighted value in range [-1, 1)
public float WeightedSignedValue (Weight weight, int weightStrength = 4) {
return WeightedValue (weight, weightStrength) * 2 - 1;
}
// Returns a weighted value in range [0, 1)
public float WeightedValue (Weight weight, int weightStrength = 4) {
if (weight == Weight.None) {
return Value ();
}
float smallestValue = Value ();
for (int i = 0; i < weightStrength; i++) {
smallestValue = Mathf.Min (smallestValue, Value ());
}
switch (weight) {
case Weight.Lower: // Bias towards smaller values
return smallestValue;
case Weight.Upper: // Bias towards larger values
return 1 - smallestValue;
case Weight.Centre: // Bias towards middle values
return 0.5f + smallestValue * 0.5f * Sign ();
case Weight.Ends: // Bias towards smaller and larger values
return (Value () < 0.5f) ? smallestValue : 1 - smallestValue;
default:
Debug.LogError ("Missing weight implementation");
return 0;
}
}
// Returns the smallest of n random numbers between 0 and 1
public float SmallestRandom01 (int n) {
float smallest = 1;
for (int i = 0; i < n; i++) {
smallest = Mathf.Min (smallest, Value ());
}
return smallest;
}
// Returns the largest of n random numbers between 0 and 1
public float LargestRandom01 (int n) {
float largest = 0;
for (int i = 0; i < n; i++) {
largest = Mathf.Max (largest, Value ());
}
return largest;
}
// Returns the value closest to 0.5 out of n random numbers between 0 and 1
public float CentredRandom01 (int n) {
float mostCentredValue = 0;
for (int i = 0; i < n; i++) {
float value = Value ();
if (Mathf.Abs (value - 0.5f) < Mathf.Abs (mostCentredValue - 0.5f)) {
mostCentredValue = value;
}
}
return mostCentredValue;
}
public int Sign () {
return (prng.NextDouble () > 0.5) ? 1 : -1;
}
public int NextInt () {
return prng.Next ();
}
public Vector3 JiggleVector3 (float weightX, float weightY, float weightZ) {
return new Vector3 (SignedValue () * weightX, SignedValue () * weightY, SignedValue () * weightZ);
}
// Colours
public Color ColorHSV (float saturationMin, float saturationMax, float valueMin, float valueMax) {
float hue = Value ();
float saturation = Range (saturationMin, saturationMax);
float value = Range (valueMin, valueMax);
return Color.HSVToRGB (hue, saturation, value);
}
public Color ColorGreyscale (float valueMin, float valueMax) {
float value = Range (valueMin, valueMax);
return new Color (value, value, value);
}
// Elements
public T RandomElement<T> (T[] array) {
return array[Range (0, array.Length)];
}
public void Shuffle<T> (T[] array) {
int n = array.Length;
for (int i = 0; i < n - 1; i++) {
int j = prng.Next (i, n);
T temp = array[j];
array[j] = array[i];
array[i] = temp;
}
}
public void Shuffle<T> (List<T> list) {
int n = list.Count;
for (int i = 0; i < n - 1; i++) {
int j = prng.Next (i, n);
T temp = list[j];
list[j] = list[i];
list[i] = temp;
}
}
}