138 lines
4.2 KiB
C++
138 lines
4.2 KiB
C++
/* +=======================================================+
|
|
____/ \____ /: Open source game framework licensed to freely use, :
|
|
\ / / : copy, and modify - created for dank.game :
|
|
+==\ ^__^ /==+ : :
|
|
: ~/ \~ : : Download at https://open.shampoo.ooo/shampoo/spacebox :
|
|
: ~~~~~~~~~~~~ : +=======================================================+
|
|
: SPACE ~~~~~ : /
|
|
: ~~~~~~~ BOX :/
|
|
+=============*/
|
|
|
|
#include "math.hpp"
|
|
|
|
glm::vec2 sb::math::angle_to_vector(float angle, float magnitude)
|
|
{
|
|
return {glm::sin(angle) * magnitude, glm::cos(angle) * magnitude};
|
|
}
|
|
|
|
float sb::math::angle_between(glm::vec2 start, glm::vec2 end)
|
|
{
|
|
return glm::atan(end.x - start.x, end.y - start.y);
|
|
}
|
|
|
|
float sb::math::angle_difference(float start, float end)
|
|
{
|
|
return glm::atan(glm::sin(end - start), glm::cos(end - start));
|
|
}
|
|
|
|
float sb::math::angle_ratio(float start, float end)
|
|
{
|
|
return angle_difference(start, end) / glm::pi<float>();
|
|
}
|
|
|
|
glm::vec2 sb::math::point_on_circle(const glm::vec2& center, float angle, float radius)
|
|
{
|
|
return center + angle_to_vector(angle, radius);
|
|
}
|
|
|
|
void sb::math::points_on_circle(
|
|
std::vector<glm::vec2>& points, int count, float radius, const glm::vec2& center, float offset)
|
|
{
|
|
float step = glm::two_pi<float>() / count;
|
|
for (int ii = 0; ii < count; ii++)
|
|
{
|
|
points.push_back(point_on_circle(center, radius, ii * step + offset));
|
|
}
|
|
}
|
|
|
|
std::vector<glm::vec2> sb::math::points_on_circle(int count, float radius, const glm::vec2& center, float offset)
|
|
{
|
|
std::vector<glm::vec2> points;
|
|
points.reserve(count);
|
|
points_on_circle(points, count, radius, center, offset);
|
|
return points;
|
|
}
|
|
|
|
std::vector<glm::vec2> sb::math::bezier(const std::vector<glm::vec2>& control, int resolution)
|
|
{
|
|
std::vector<glm::vec2> points;
|
|
points.reserve(resolution);
|
|
|
|
float b0x = control[0][0];
|
|
float b0y = control[0][1];
|
|
float b1x = control[1][0];
|
|
float b1y = control[1][1];
|
|
float b2x = control[2][0];
|
|
float b2y = control[2][1];
|
|
float b3x = control[3][0];
|
|
float b3y = control[3][1];
|
|
|
|
float ax = -b0x + 3.0f * b1x + -3.0f * b2x + b3x;
|
|
float ay = -b0y + 3.0f * b1y + -3.0f * b2y + b3y;
|
|
float bx = 3.0f * b0x + -6.0f * b1x + 3.0f * b2x;
|
|
float by = 3.0f * b0y + -6.0f * b1y + 3.0f * b2y;
|
|
float cx = -3.0f * b0x + 3.0f * b1x;
|
|
float cy = -3.0f * b0y + 3.0f * b1y;
|
|
float dx = b0x;
|
|
float dy = b0y;
|
|
|
|
float steps = resolution - 1;
|
|
float h = 1.0f / steps;
|
|
|
|
float pointX = dx;
|
|
float pointY = dy;
|
|
|
|
float firstFDX = ax * std::pow(h, 3.0f) + bx * std::pow(h, 2.0f) + cx * h;
|
|
float firstFDY = ay * std::pow(h, 3.0f) + by * std::pow(h, 2.0f) + cy * h;
|
|
float secondFDX = 6 * ax * std::pow(h, 3.0f) + 2 * bx * std::pow(h, 2.0f);
|
|
float secondFDY = 6 * ay * std::pow(h, 3.0f) + 2 * by * std::pow(h, 2.0f);
|
|
float thirdFDX = 6 * ax * std::pow(h, 3.0f);
|
|
float thirdFDY = 6 * ay * std::pow(h, 3.0f);
|
|
|
|
points.push_back({pointX, pointY});
|
|
|
|
for (int ii = 0; ii < steps; ii++)
|
|
{
|
|
pointX += firstFDX;
|
|
pointY += firstFDY;
|
|
firstFDX += secondFDX;
|
|
firstFDY += secondFDY;
|
|
secondFDX += thirdFDX;
|
|
secondFDY += thirdFDY;
|
|
points.push_back({pointX, pointY});
|
|
}
|
|
|
|
return points;
|
|
}
|
|
|
|
std::string sb::math::random::id(std::size_t length, std::optional<int> seed)
|
|
{
|
|
/* Mersenne Twister engine */
|
|
std::mt19937 generator;
|
|
|
|
/* Use the submitted seed, or get a random seed if no seed is given. */
|
|
if (seed.has_value())
|
|
{
|
|
generator.seed(seed.value());
|
|
}
|
|
else
|
|
{
|
|
std::random_device device;
|
|
generator.seed(device());
|
|
}
|
|
|
|
/* List of possible characters in the ID string */
|
|
std::string pool { "23456789abcdefghijklmnopqrstuvwxyz" };
|
|
|
|
/* Limit the possible choices to the indices of the string, so a random character will be chosen each call. */
|
|
std::uniform_int_distribution<> distribution(0, pool.size() - 1);
|
|
|
|
/* Generate an ID string */
|
|
std::string id;
|
|
for (std::size_t index { 0 }; index < length; index++)
|
|
{
|
|
id += pool[distribution(generator)];
|
|
}
|
|
return id;
|
|
}
|