1 /// Custom templated math
2 module sily.math;
3 
4 import std.math;
5 import std.traits: isFloatingPoint;
6 
7 // https://github.com/godotengine/godot/blob/master/core/math/math_funcs.cpp
8 
9 const double degtorad = PI / 180.0; 
10 const double radtodeg = 180.0 / PI; 
11 
12 alias deg2rad = degtorad;
13 alias rad2deg = radtodeg;
14 
15 /// Linearly interpolates value
16 T lerp(T)(T from, T to, T weight) if (isFloatingPoint!T) {
17     from += (weight * (to - from));
18     return from;
19 }
20 
21 /// Snaps value to step
22 T snap(T)(T p_val, T p_step) if (isFloatingPoint!T) {
23     if (p_step != 0) {
24         p_val = floor(p_val / p_step + 0.5) * p_step;
25     }
26     return p_val;
27 }
28 
29 /// Snaps value to step, if T is not float, then explicit casts are used
30 /// and it may cause data loss
31 T snap(T)(T p_val, T p_step) if (!isFloatingPoint!T) {
32     if (p_step != 0) {
33         p_val = cast(T) (floor(cast(double) p_val / cast(double) p_step + 0.5) * cast(double) p_step);
34     }
35     return p_val;
36 }
37 
38 // FIXME: cubic_interpolate
39 /*
40 static _ALWAYS_INLINE_ float cubic_interpolate(float p_from, float p_to, float p_pre, float p_post, float p_weight) {
41     return 0.5f *
42             ((p_from * 2.0f) +
43                     (-p_pre + p_to) * p_weight +
44                     (2.0f * p_pre - 5.0f * p_from + 4.0f * p_to - p_post) * (p_weight * p_weight) +
45                     (-p_pre + 3.0f * p_from - 3.0f * p_to + p_post) * (p_weight * p_weight * p_weight));
46 }
47 
48 static _ALWAYS_INLINE_ float lerp_angle(float p_from, float p_to, float p_weight) {
49     float difference = fmod(p_to - p_from, (float)Math_TAU);
50     float distance = fmod(2.0f * difference, (float)Math_TAU) - difference;
51     return p_from + distance * p_weight;
52 }
53 
54 static _ALWAYS_INLINE_ float smoothstep(float p_from, float p_to, float p_s) {
55     if (is_equal_approx(p_from, p_to)) {
56         return p_from;
57     }
58     float s = CLAMP((p_s - p_from) / (p_to - p_from), 0.0f, 1.0f);
59     return s * s * (3.0f - 2.0f * s);
60 }
61 static _ALWAYS_INLINE_ double wrapf(double value, double min, double max) {
62     double range = max - min;
63     return is_zero_approx(range) ? min : value - (range * Math::floor((value - min) / range));
64 }
65 */