spacebox/src/math.hpp

117 lines
5.4 KiB
C++

/* +------------------------------------------------------+
____/ \____ /| - Open source game framework licensed to freely use, |
\ / / | copy, modify and sell without restriction |
+--\ ^__^ /--+ | |
| ~/ \~ | | - created for <https://foam.shampoo.ooo> |
| ~~~~~~~~~~~~ | +------------------------------------------------------+
| SPACE ~~~~~ | /
| ~~~~~~~ BOX |/
+--------------+
[math.hpp]
For math helper functions that require only GLM primitives, especially trigonometric functions.
Angle values are in radians. 0 is directly up on the screen in GL coordinates, and the angle increases
clockwise.
This test of points on a square and one point below the square should print the output below.
glm::vec2 a {5.0f, 5.0f}, b {1.0f, 1.0f}, c {1.0f, 5.0f}, d {5.0f, 1.0f}, e {5.0f, -1.0f};
std::cout << glm::degrees(sb::angle_between(a, b)) << " " << glm::degrees(sb::angle_between(b, a)) << " " <<
glm::degrees(sb::angle_between(a, c)) << " " << glm::degrees(sb::angle_between(c, a)) << " " <<
glm::degrees(sb::angle_between(b, e)) << " " << glm::degrees(sb::angle_between(e, b)) << std::endl <<
sb::velocity_to_delta(sb::angle_between(a, b), 4.0f * glm::sqrt(2.0f)) << " " <<
sb::velocity_to_delta(sb::angle_between(b, a), 4.0f * glm::sqrt(2.0f)) << " " <<
sb::velocity_to_delta(sb::angle_between(d, a), 4.0f) << " " <<
sb::velocity_to_delta(sb::angle_between(b, e), 1.0f) << std::endl;
Should print,
-135 45 -90 90 116.565 -63.435
{-4, -4} {4, 4} {0, 4} {0.894427, -0.447214}
This test of angle differences should print the output below.
float a = 0.0f, b = glm::pi<float>(), c = glm::half_pi<float>(), d = 0.5f, e = glm::pi<float>() * 4;
std::cout << sb::angle_difference(a, b) << " " << sb::angle_difference(a, c) << " " << sb::angle_difference(b, c) << " " <<
sb::angle_difference(a, d) << " " << sb::angle_difference(c, d) << " " << sb::angle_difference(a, e) << " " <<
sb::angle_difference(c, e) << " " << sb::angle_difference(d, e) << " " << sb::angle_difference(c, c) << std::endl <<
sb::angle_ratio(a, b) << " " << sb::angle_ratio(a, c) << " " << sb::angle_ratio(b, c) << " " << sb::angle_ratio(a, d) << " " <<
sb::angle_ratio(c, d) << " " << sb::angle_ratio(a, e) << " " << sb::angle_ratio(c, e) << " " << sb::angle_ratio(d, e) << " " <<
sb::angle_ratio(c, c) << std::endl;
Should print,
-3.14159 1.5708 -1.5708 0.5 -1.0708 3.49691e-07 -1.5708 -0.5 0
-1 0.5 -0.5 0.159155 -0.340845 1.1131e-07 -0.5 -0.159155 0
*/
#pragma once
#include <vector>
/* GLM */
#define GLM_ENABLE_EXPERIMENTAL
#include <glm/glm.hpp>
#include <glm/gtx/compatibility.hpp>
namespace sb
{
static inline const glm::vec3 ZAXIS {0.0f, 0.0f, 1.0f};
/*!
* Convert a vector described by the given angle and magnitude to an X and Y offset vector.
*
* @param angle a float representing the angle of velocity in radians, with 0 being up on the screen and increasing
* values going clockwise
* @param magnitude a float representing the speed, or the magnitude of the input vector in the X/Y plane
* @return a glm::vec2 of the change in X and Y for the given velocity vector
*/
glm::vec2 velocity_to_delta(float angle, float magnitude);
/*!
* @overload glm::vec2 velocity_to_delta(float angle, float magnitude)
*/
glm::vec2 velocity_to_delta(glm::vec2 velocity);
/*!
* Get the angle between two vectors, or the angle the first would rotate to to point toward the second.
*
* @param start X/Y coordinates
* @param end X/Y coordinates
* @return an angle in radians
*/
float angle_between(glm::vec2 start, glm::vec2 end);
/*!
* Get the signed shortest angle difference between two angles, or how much the first angle would have to rotate
* to be equivalent to the second angle. Negative is counter-clockwise, positive clockwise.
*
* @param start X/Y coordinates of the angle which the difference will be relative to
* @param end X/Y coordinates of the angle which the difference will be rotated to
* @return angle difference relative to the start parameter in radians
*/
float angle_difference(float start, float end);
/*!
* Get the angle difference between two angles as a signed ratio of how much of a 180 degree turn it is. Negative
* is counter-clockwise, positive clockwise.
*
* @param start X/Y coordinates of the angle which the difference will be relative to
* @param end X/Y coordinates of the angle which the difference will be rotated to
* @return angle difference relative to the start parameter as a signed ratio of how much of a 180 degree
* turn it is.
*/
float angle_ratio(float start, float end);
/*!
* Calculate a 2D bezier curve from four 2D control points.
*
* Adapted from public domain released code, 2007 Victor Blomqvist, originally at https://www.pygame.org/wiki/BezierCurve.
*
* @param vertices four 2D control points
* @param resolution number of points that will be in the computed curve
*/
std::vector<glm::vec2> bezier(const std::vector<glm::vec2>& vertices, int resolution = 30);
}