1 /// Custom templated math 2 module sily.math; 3 4 import std.math; 5 import std.random; 6 import std.algorithm.comparison; 7 import std.conv; 8 import std.traits; 9 import std.datetime: Clock; 10 11 // https://github.com/godotengine/godot/blob/master/core/math/math_funcs.cpp 12 13 // float degToRad(float deg) { 14 // return deg * (PI / 180.0f); 15 // } 16 17 // float radToDeg(float rad) { 18 // return rad * (180.0f / PI); 19 // } 20 21 // alias deg2rad = degToRad; 22 // alias rad2deg = radToDeg; 23 24 /// Typed lerp alias 25 alias lerp = lerpT!float; 26 /// Ditto 27 alias lerp = lerpT!real; 28 /// Ditto 29 alias lerp = lerpT!double; 30 31 /// Template lerp 32 T lerpT(T: float)(T from, T to, T weight) { 33 from += (weight * (to - from)); 34 return from; 35 } 36 37 /// Typed snap alias 38 alias snap = snapT!float; 39 /// Ditto 40 alias snap = snapT!real; 41 /// Ditto 42 alias snap = snapT!double; 43 44 /// Template snap 45 T snapT(T: float)(T p_val, T p_step) { 46 if (p_step != 0) { 47 p_val = floor(p_val / p_step + 0.5) * p_step; 48 } 49 return p_val; 50 } 51 52 /// std.random wrapper 53 struct RNG { 54 private uint _seed = defaultSeed; 55 private Random _rnd; 56 private ulong _calls; 57 58 /// Creates RNG struct with set seed 59 this(uint p_seed) { 60 _seed = p_seed; 61 _rnd = Random(_seed); 62 } 63 64 /// Randomizes seed 65 public void randomize() { 66 _seed = randomSeed; 67 setSeed(_seed); 68 } 69 /// Ditto 70 alias randomise = randomize; 71 72 /// Sets custom seed `p_seed` 73 public void setSeed(uint p_seed) { 74 _seed = p_seed; 75 _rnd.seed(_seed); 76 } 77 78 /// Returns current seed 79 public uint seed() { return _seed; } 80 81 /// Alias to default seed 82 public static alias defaultSeed = Random.defaultSeed; 83 /// Alias to unpredictable seed 84 public static alias randomSeed = unpredictableSeed; 85 86 /// Typed alias to get random value 87 alias randf = randT!float; 88 /// Ditto 89 alias randr = randT!real; 90 /// Ditto 91 alias randd = randT!double; 92 /// Ditto 93 alias randi = randT!int; 94 /// Ditto 95 alias randl = randT!long; 96 97 98 template randT(T: float) { 99 static if(isFloatingPoint!T) { 100 /// Returns random value between 0 and T.max or custom min and max 101 T randT() { 102 return random / _rnd.max.to!T; 103 } 104 105 /// Ditto 106 T randT(T min, T max) { 107 return min + (randT!T * (max - min)); 108 } 109 } else { 110 /// Ditto 111 T randT() { 112 return (randr * T.max).to!T; 113 } 114 115 /// Ditto 116 T randT(T min, T max) { 117 return round(min + (randr * (max - min))).to!T; 118 } 119 } 120 } 121 122 /// Returns random uint 123 public uint random() { 124 uint r = _rnd.front; 125 skip(); 126 return r; 127 } 128 129 /// Skips current random value 130 public void skip() { 131 _rnd.popFront(); 132 _calls ++; 133 } 134 135 /// Skips N amount of random values 136 public void skipTo(ulong numCalls) { 137 while(_calls < numCalls) { 138 skip(); 139 } 140 } 141 } 142 143 // FIXME cubic_interpolate 144 /* 145 static _ALWAYS_INLINE_ float cubic_interpolate(float p_from, float p_to, float p_pre, float p_post, float p_weight) { 146 return 0.5f * 147 ((p_from * 2.0f) + 148 (-p_pre + p_to) * p_weight + 149 (2.0f * p_pre - 5.0f * p_from + 4.0f * p_to - p_post) * (p_weight * p_weight) + 150 (-p_pre + 3.0f * p_from - 3.0f * p_to + p_post) * (p_weight * p_weight * p_weight)); 151 } 152 153 static _ALWAYS_INLINE_ float lerp_angle(float p_from, float p_to, float p_weight) { 154 float difference = fmod(p_to - p_from, (float)Math_TAU); 155 float distance = fmod(2.0f * difference, (float)Math_TAU) - difference; 156 return p_from + distance * p_weight; 157 } 158 159 static _ALWAYS_INLINE_ float smoothstep(float p_from, float p_to, float p_s) { 160 if (is_equal_approx(p_from, p_to)) { 161 return p_from; 162 } 163 float s = CLAMP((p_s - p_from) / (p_to - p_from), 0.0f, 1.0f); 164 return s * s * (3.0f - 2.0f * s); 165 } 166 static _ALWAYS_INLINE_ double wrapf(double value, double min, double max) { 167 double range = max - min; 168 return is_zero_approx(range) ? min : value - (range * Math::floor((value - min) / range)); 169 } 170 */