1 /**
2     Useful functions
3 
4     Copyright: (c) Enalye 2017
5     License: Zlib
6     Authors: Enalye
7 */
8 
9 module atelier.core.util;
10 
11 public import std.math;
12 public import std.algorithm.comparison : clamp, min, max;
13 
14 import atelier.core.vec2;
15 
16 /// The square root of 2, then divided by 2.
17 enum sqrt2_2 = std.math.sqrt(2.0) / 2.0;
18 /// 2 times PI.
19 enum pi2 = PI * 2f;
20 
21 /// Interpolation, returns a value between a and b. \
22 /// If t = 0, returns a. \
23 /// If t = 1, returns b.
24 T lerp(T)(T a, T b, float t) {
25     return t * b + (1f - t) * a;
26 }
27 
28 /// Reverse lerp, returns a value between 0 and 1. \
29 /// 0 if v = a. \
30 /// 1 if v = b.
31 float rlerp(float a, float b, float v) {
32     return (v - a) / (b - a);
33 }
34 
35 /// The minimal angle (in degrees) between 2 other angles.
36 float angleBetween(float a, float b) {
37     const float delta = (b - a) % 360f;
38     return ((2f * delta) % 360f) - delta;
39 }
40 
41 /// Interpolation between an angle a and b. \
42 /// If t = 0, returns a. \
43 /// If t = 1, returns b.
44 float angleLerp(float a, float b, float t) {
45     return a + angleBetween(a, b) * t;
46 }
47 
48 /// Scale a vector to fit the specified vector while keeping its ratio.
49 Vec2f scaleToFit(Vec2f src, Vec2f dst) {
50     float scale;
51     if (dst.x / dst.y > src.x / src.y)
52         scale = dst.y / src.y;
53     else
54         scale = dst.x / src.x;
55     return src * scale;
56 }
57 
58 /// Linear interpolation to approach a target
59 float approach(float value, float target, float step) {
60     return value > target ? max(value - step, target) : min(value + step, target);
61 }