Gamedev Framework (gf)  0.4.0
A C++11 framework for 2D games
Math.h
1 /*
2  * Gamedev Framework (gf)
3  * Copyright (C) 2016-2017 Julien Bernard
4  *
5  * This software is provided 'as-is', without any express or implied
6  * warranty. In no event will the authors be held liable for any damages
7  * arising from the use of this software.
8  *
9  * Permission is granted to anyone to use this software for any purpose,
10  * including commercial applications, and to alter it and redistribute it
11  * freely, subject to the following restrictions:
12  *
13  * 1. The origin of this software must not be misrepresented; you must not
14  * claim that you wrote the original software. If you use this software
15  * in a product, an acknowledgment in the product documentation would be
16  * appreciated but is not required.
17  * 2. Altered source versions must be plainly marked as such, and must not be
18  * misrepresented as being the original software.
19  * 3. This notice may not be removed or altered from any source distribution.
20  */
21 #ifndef GF_MATH_H
22 #define GF_MATH_H
23 
24 #include <cmath>
25 #include <limits>
26 
27 #include "Portability.h"
28 
29 namespace gf {
30 #ifndef DOXYGEN_SHOULD_SKIP_THIS
31 inline namespace v1 {
32 #endif
33 
34  /**
35  * @ingroup core
36  * @brief The @f$ \pi @f$ constant
37  */
38  constexpr float Pi = 3.14159265358979323846f;
39 
40  /**
41  * @ingroup core
42  * @brief The @f$ \frac{\pi}{2} @f$ constant
43  */
44  constexpr float Pi2 = Pi / 2;
45 
46  /**
47  * @ingroup core
48  * @brief The @f$ \frac{\pi}{4} @f$ constant
49  */
50  constexpr float Pi4 = Pi / 4;
51 
52  /**
53  * @ingroup core
54  * @brief The @f$ \sqrt{2} @f$ constant
55  */
56  constexpr float Sqrt2 = 1.41421356237309504880f;
57 
58  /**
59  * @ingroup core
60  * @brief The @f$ \frac{1}{\sqrt{2}} @f$ constant
61  */
62  constexpr float InvSqrt2 = 1 / Sqrt2;
63 
64  /**
65  * @ingroup core
66  * @brief The @f$ \sqrt{3} @f$ constant
67  */
68  constexpr float Sqrt3 = 1.7320508075688772935f;
69 
70  /**
71  * @ingroup core
72  * @brief Machine epsilon
73  */
74  constexpr float Epsilon = std::numeric_limits<float>::epsilon();
75 
76  /**
77  * @ingroup core
78  * @brief Compare two floats
79  *
80  * @param a The first float
81  * @param b The second float
82  * @param epsilon A small value that controls the equality comparison
83  *
84  * @sa [Comparison - The Floating-Point Guide](http://floating-point-gui.de/errors/comparison/)
85  */
86  template<typename T>
87  inline
88  bool almostEquals(T a, T b, T epsilon = std::numeric_limits<T>::epsilon()) {
89  if (a == b) {
90  return true;
91  }
92 
93  T diff = std::abs(a - b);
94 
95  if (a == 0 || b == 0 || diff < std::numeric_limits<T>::denorm_min()) {
96  return diff < (epsilon * std::numeric_limits<T>::denorm_min());
97  }
98 
99  T sum = std::abs(a) + std::abs(b);
100  sum = (sum < std::numeric_limits<T>::max()) ? sum : std::numeric_limits<T>::max();
101 
102  return (diff / sum) < epsilon;
103  }
104 
105  /**
106  * @ingroup core
107  * @brief Convert degrees to radians
108  *
109  * @param degrees An angle in degrees
110  * @returns The angle in radians
111  * @sa radiansToDegrees()
112  */
113  constexpr float degreesToRadians(float degrees) {
114  return degrees * Pi / 180.0f;
115  }
116 
117  /**
118  * @ingroup core
119  * @brief Convert radians to degrees
120  *
121  * @param radians An angle in radians
122  * @returns The angle in degrees
123  * @sa degreesToRadians()
124  */
125  constexpr float radiansToDegrees(float radians) {
126  return radians * 180.0f / Pi;
127  }
128 
129  /**
130  * @ingroup core
131  * @brief A step is a function with special features.
132  *
133  * A step @f$ f @f$ is a (mathematical) function which has the following properties:
134  *
135  * - @f$ f(0) = 0 @f$
136  * - @f$ f(1) = 1 @f$
137  *
138  * It can be used to smooth a linear interpolation.
139  *
140  * ~~~{.cc}
141  * gf::Vector2f point1 = ...;
142  * gf::Vector2f point2 = ...;
143  * float t = ...;
144  * gf::Step<float> step = gf::cubicStep<float>;
145  *
146  * gf::Vector2f interpolatedPoint = gf::lerp(point1, point2, t);
147  * gf::Vector2f smoothedInterpolatedPoint = gf::lerp(point1, point2, step(t));
148  * ~~~
149  *
150  * @sa linearStep(), cubicStep(), quinticStep(), cosineStep()
151  */
152  template<typename T>
153  using Step = T (*)(T);
154 
155  /**
156  * @ingroup core
157  * @brief Linear step
158  *
159  * @f[ f(t) = t @f]
160  *
161  * @sa gf::Step
162  */
163  template<typename T>
164  constexpr
165  T linearStep(T t) {
166  return t;
167  }
168 
169  /**
170  * @ingroup core
171  * @brief Cubic step (smoothstep)
172  *
173  * @f[ f(t) = -2 * t^3 + 3 * t^2 @f]
174  *
175  * Compared to a step, it has the following properties:
176  *
177  * - @f$ f'(0) = 0 @f$
178  * - @f$ f'(1) = 0 @f$
179  *
180  * This function is also known as [smoothstep](https://en.wikipedia.org/wiki/Smoothstep)
181  *
182  * @sa gf::Step
183  */
184  template<typename T>
185  constexpr
186  T cubicStep(T t) {
187  return (-2 * t + 3) * t * t;
188  }
189 
190  /**
191  * @ingroup core
192  * @brief Quintic step (smootherstep)
193  *
194  * @f[ f(t) = 6 * t^5 - 15 * t^4 + 10 * t^3 @f]
195  *
196  * Compared to a step, it has the following properties:
197  *
198  * - @f$ f'(0) = 0 @f$
199  * - @f$ f'(1) = 0 @f$
200  * - @f$ f''(0) = 0 @f$
201  * - @f$ f''(1) = 0 @f$
202  *
203  * This function is also known as [smootherstep](https://en.wikipedia.org/wiki/Smoothstep#Variations)
204  *
205  * @sa gf::Step
206  */
207  template<typename T>
208  constexpr
209  T quinticStep(T t) {
210  return ((6 * t - 15) * t + 10) * t * t * t;
211  }
212 
213  /**
214  * @ingroup core
215  * @brief Cosine step
216  *
217  * @f[ f(t) = (1 - \cos(\pi * t)) * 0.5 @f]
218  *
219  * @sa gf::Step
220  */
221  template<typename T>
222  inline
223  T cosineStep(T t) {
224  return (1 - std::cos(Pi * t)) * 0.5;
225  }
226 
227  /**
228  * @ingroup core
229  * @brief Linear interpolation function
230  *
231  * This functions returns an interpolated value between two values `lhs` and
232  * `rhs` according to a parameter @f$ t @f$. When @f$ t = 0 @f$ then `lhs`
233  * is returned, and when @f$ t = 1 @f$ then `rhs` is returned.
234  *
235  * @param lhs The first value
236  * @param rhs The second value
237  * @param t The interpolation parameter, generally in the interval @f$ [0,1] @f$
238  * @returns A value between the first and second value
239  */
240  template<typename T, typename U>
241  inline
242  T lerp(T lhs, T rhs, U t) {
243  return (1 - t) * lhs + t * rhs;
244  }
245 
246  /**
247  * @ingroup core
248  * @brief Clamping function
249  *
250  * This function takes a value and returns it if it is in a specified range.
251  * If not, the returned value is the nearest value in the range.
252  *
253  * @param val The value to clamp
254  * @param lo The minimum accepted value
255  * @param hi The maximum accepted value
256  * @returns The clamped value
257  */
258  template<typename T>
259  constexpr
260  T clamp(T val, T lo, T hi) {
261  return val < lo ? lo : (val > hi ? hi : val);
262  }
263 
264  /**
265  * @ingroup core
266  * @brief Square function
267  *
268  * For a value @f$ x @f$, the square value is @f$ x^2 @f$.
269  *
270  * @param val A value
271  * @returns The square of the value
272  */
273  template<typename T>
274  constexpr
275  T square(T val) {
276  return val * val;
277  }
278 
279  /**
280  * @ingroup core
281  * @brief Sign function
282  *
283  * The sign function of @f$ x @f$ is:
284  *
285  * - @f$ -1 @f$ if @f$ x < 0 @f$
286  * - @f$ 0 @f$ if @f$ x = 0 @f$
287  * - @f$ 1 @f$ if @f$ x > 0 @f$
288  *
289  * @param val A value
290  * @returns The sign of the value
291  * @sa [Sign function](https://en.wikipedia.org/wiki/Sign_function)
292  */
293  template<typename T>
294  constexpr
295  int sign(T val) {
296  return (val > T(0)) - (val < T(0));
297  }
298 
299 #ifndef DOXYGEN_SHOULD_SKIP_THIS
300 }
301 #endif
302 }
303 
304 #endif // GF_MATH_H
constexpr float Pi2
The constant.
Definition: Math.h:44
constexpr float Epsilon
Machine epsilon.
Definition: Math.h:74
constexpr float radiansToDegrees(float radians)
Convert radians to degrees.
Definition: Math.h:125
constexpr float InvSqrt2
The constant.
Definition: Math.h:62
constexpr float degreesToRadians(float degrees)
Convert degrees to radians.
Definition: Math.h:113
T lerp(T lhs, T rhs, U t)
Linear interpolation function.
Definition: Math.h:242
constexpr T square(T val)
Square function.
Definition: Math.h:275
constexpr T clamp(T val, T lo, T hi)
Clamping function.
Definition: Math.h:260
bool almostEquals(T a, T b, T epsilon=std::numeric_limits< T >::epsilon())
Compare two floats.
Definition: Math.h:88
constexpr float Sqrt2
The constant.
Definition: Math.h:56
constexpr T cubicStep(T t)
Cubic step (smoothstep)
Definition: Math.h:186
The namespace for gf classes.
Definition: Action.h:34
T cosineStep(T t)
Cosine step.
Definition: Math.h:223
constexpr float Pi
The constant.
Definition: Math.h:38
constexpr T linearStep(T t)
Linear step.
Definition: Math.h:165
constexpr float Sqrt3
The constant.
Definition: Math.h:68
constexpr int sign(T val)
Sign function.
Definition: Math.h:295
constexpr T quinticStep(T t)
Quintic step (smootherstep)
Definition: Math.h:209
constexpr float Pi4
The constant.
Definition: Math.h:50