diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/collection.hpp | 71 | ||||
-rw-r--r-- | lib/embed-glsl.cpp.m4 | 11 | ||||
-rw-r--r-- | lib/embed-glsl.h.m4 | 4 | ||||
-rw-r--r-- | lib/glRef.hpp | 56 | ||||
-rw-r--r-- | lib/maths.cpp | 128 | ||||
-rw-r--r-- | lib/maths.h | 61 | ||||
-rw-r--r-- | lib/ptr.hpp | 25 | ||||
-rw-r--r-- | lib/sorting.hpp | 12 | ||||
-rw-r--r-- | lib/special_members.hpp | 18 | ||||
-rw-r--r-- | lib/stream_support.hpp | 42 |
10 files changed, 428 insertions, 0 deletions
diff --git a/lib/collection.hpp b/lib/collection.hpp new file mode 100644 index 0000000..79c331a --- /dev/null +++ b/lib/collection.hpp @@ -0,0 +1,71 @@ +#ifndef COLLECTION_H +#define COLLECTION_H + +#include <algorithm> +#include <memory> +#include <type_traits> + +template<typename Object, bool shared = true> class Collection { +public: + using Ptr = std::conditional_t<shared, std::shared_ptr<Object>, std::unique_ptr<Object>>; + using Objects = std::vector<Ptr>; + Objects objects; + + template<typename T = Object, typename... Params> + auto + create(Params &&... params) + { + if constexpr (shared) { + auto obj = std::make_shared<T>(std::forward<Params>(params)...); + objects.emplace_back(obj); + return obj; + } + else { + return static_cast<T *>(objects.emplace_back(std::make_unique<T>(std::forward<Params>(params)...)).get()); + } + } + + template<typename T = Object, typename M = void, typename... Params> + auto + apply(const M & m, Params &&... params) const + { + return std::count_if(objects.begin(), objects.end(), [&m, ¶ms...](auto && op) { + if (auto o = dynamic_cast<T *>(op.get())) { + std::invoke(m, o, std::forward<Params>(params)...); + return true; + } + return false; + }); + } + + template<typename T = Object, typename M = void, typename... Params> + auto + applyOne(const M & m, Params &&... params) const + { + return std::find_if(objects.begin(), objects.end(), [&m, ¶ms...](auto && op) { + if (auto o = dynamic_cast<T *>(op.get())) { + return std::invoke(m, o, std::forward<Params>(params)...); + } + return false; + }); + } + + template<typename T = Object> + void + removeAll() + { + objects.erase(std::remove_if(objects.begin(), objects.end(), + [](auto && op) { + return dynamic_cast<T *>(op.get()); + }), + objects.end()); + } + + auto + end() const + { + return objects.end(); + } +}; + +#endif diff --git a/lib/embed-glsl.cpp.m4 b/lib/embed-glsl.cpp.m4 new file mode 100644 index 0000000..9e4c6d4 --- /dev/null +++ b/lib/embed-glsl.cpp.m4 @@ -0,0 +1,11 @@ +changecom()dnl +// NAME +#include "substr(TYPE,1)-NAME.h" +#include <GL/glew.h> +#include "gfx/gl/shader-source.h" + +constexpr const GLchar * src { R"GLSL-EMBED(dnl +include(SOURCE))GLSL-EMBED" }; +constexpr auto len { constexpr_strlen (src) }; + +const GLsource NAME`_'substr(TYPE,1) { src, len, GLTYPE }; diff --git a/lib/embed-glsl.h.m4 b/lib/embed-glsl.h.m4 new file mode 100644 index 0000000..918007b --- /dev/null +++ b/lib/embed-glsl.h.m4 @@ -0,0 +1,4 @@ +// NAME +#include <gfx/gl/shader-source.h> + +extern const GLsource NAME`_'substr(TYPE,1); diff --git a/lib/glRef.hpp b/lib/glRef.hpp new file mode 100644 index 0000000..8596bd3 --- /dev/null +++ b/lib/glRef.hpp @@ -0,0 +1,56 @@ +#ifndef GLREF_H +#define GLREF_H + +#include <special_members.hpp> +#include <stdexcept> + +template<typename IdType, auto & get, auto & release, auto... fixed> class glRef { +public: + template<typename... Args> explicit glRef(Args &&... args) : id {get(fixed..., std::forward<Args>(args)...)} + { + if (!id) { + throw std::runtime_error("Get function failed"); + } + } + + glRef(glRef && other) : id {other.id} + { + other.id = {}; + } + + ~glRef() + { + if (id) { + release(id); + } + } + + NO_COPY(glRef); + + const auto & + operator=(glRef && other) + { + if (id) { + release(id); + } + id = other.id; + other.id = {}; + return *this; + } + + auto + operator*() const + { + return id; + } + + operator IdType() const + { + return id; + } + +private: + IdType id; +}; + +#endif diff --git a/lib/maths.cpp b/lib/maths.cpp new file mode 100644 index 0000000..543c887 --- /dev/null +++ b/lib/maths.cpp @@ -0,0 +1,128 @@ +#include "maths.h" +#include <cmath> +#include <glm/glm.hpp> +#include <glm/gtx/rotate_vector.hpp> +#include <glm/gtx/transform.hpp> +#include <stdexcept> + +glm::mat4 +flat_orientation(const glm::vec3 & diff) +{ + static const auto oneeighty {glm::rotate(pi, up)}; + const auto flatdiff {glm::normalize(glm::vec3 {diff.x, 0, diff.z})}; + auto e {glm::orientation(flatdiff, north)}; + // Handle if diff is exactly opposite to north + return (std::isnan(e[0][0])) ? oneeighty : e; +} + +float +vector_yaw(const glm::vec3 & diff) +{ + return std::atan2(diff.x, diff.z); +} + +float +vector_pitch(const glm::vec3 & diff) +{ + return std::atan(diff.y); +} + +float +round_frac(const float & v, const float & frac) +{ + return std::round(v / frac) * frac; +} + +float +normalize(float ang) +{ + while (ang > pi) { + ang -= two_pi; + } + while (ang <= -pi) { + ang += two_pi; + } + return ang; +} + +Arc::Arc(const glm::vec3 & centre3, const glm::vec3 & e0p, const glm::vec3 & e1p) : + Arc([&]() -> Arc { + const auto diffa = e0p - centre3; + const auto diffb = e1p - centre3; + const auto anga = vector_yaw(diffa); + const auto angb = [&diffb, &anga]() { + const auto angb = vector_yaw(diffb); + return (angb < anga) ? angb + two_pi : angb; + }(); + return {anga, angb}; + }()) +{ +} + +std::pair<glm::vec2, bool> +find_arc_centre(glm::vec2 as, float entrys, glm::vec2 bs, float entrye) +{ + if (as == bs) { + return {as, false}; + } + const auto perps = entrys + half_pi; + const auto perpe = entrye - half_pi; + const glm::vec2 ad {std::sin(perps), std::cos(perps)}; + const glm::vec2 bd {std::sin(perpe), std::cos(perpe)}; + return find_arc_centre(as, ad, bs, bd); +} + +std::pair<glm::vec2, bool> +find_arc_centre(glm::vec2 as, glm::vec2 ad, glm::vec2 bs, glm::vec2 bd) +{ + const auto det = bd.x * ad.y - bd.y * ad.x; + if (det != 0) { // near parallel line will yield noisy results + const auto d = bs - as; + const auto u = (d.y * bd.x - d.x * bd.y) / det; + return {as + ad * u, u < 0}; + } + throw std::runtime_error("no intersection"); +} + +std::pair<float, float> +find_arcs_radius(glm::vec2 start, float entrys, glm::vec2 end, float entrye) +{ + const auto getrad = [&](float leftOrRight) { + const auto perps = entrys + leftOrRight; + const auto perpe = entrye + leftOrRight; + const glm::vec2 ad {std::sin(perps), std::cos(perps)}; + const glm::vec2 bd {std::sin(perpe), std::cos(perpe)}; + return find_arcs_radius(start, ad, end, bd); + }; + return {getrad(-half_pi), getrad(half_pi)}; +} + +float +find_arcs_radius(glm::vec2 start, glm::vec2 ad, glm::vec2 end, glm::vec2 bd) +{ + // Short name functions for big forula + auto sq = [](auto v) { + return v * v; + }; + auto sqrt = [](float v) { + return std::sqrt(v); + }; + + // Calculates path across both arcs along the normals... pythagorean theorem... for some known radius r + // (2r)^2 = ((m + (X*r)) - (o + (Z*r)))^2 + ((n + (Y*r)) - (p + (W*r)))^2 + // According to symbolabs.com equation tool, that solves for r to give: + // r=(-2 m X+2 X o+2 m Z-2 o Z-2 n Y+2 Y p+2 n W-2 p W-sqrt((2 m X-2 X o-2 m Z+2 o Z+2 n Y-2 Y p-2 n W+2 p W)^(2)-4 + // (X^(2)-2 X Z+Z^(2)+Y^(2)-2 Y W+W^(2)-4) (m^(2)-2 m o+o^(2)+n^(2)-2 n p+p^(2))))/(2 (X^(2)-2 X Z+Z^(2)+Y^(2)-2 Y + // W+W^(2)-4)) + + // These exist cos limitations of online formula rearrangement, and I'm OK with that. + const auto &m {start.x}, &n {start.y}, &o {end.x}, &p {end.y}; + const auto &X {ad.x}, &Y {ad.y}, &Z {bd.x}, &W {bd.y}; + + return (2 * m * X - 2 * X * o - 2 * m * Z + 2 * o * Z + 2 * n * Y - 2 * Y * p - 2 * n * W + 2 * p * W + - sqrt(sq(-2 * m * X + 2 * X * o + 2 * m * Z - 2 * o * Z - 2 * n * Y + 2 * Y * p + 2 * n * W + - 2 * p * W) + - (4 * (sq(X) - 2 * X * Z + sq(Z) + sq(Y) - 2 * Y * W + sq(W) - 4) + * (sq(m) - 2 * m * o + sq(o) + sq(n) - 2 * n * p + sq(p))))) + / (2 * (sq(X) - 2 * X * Z + sq(Z) + sq(Y) - 2 * Y * W + sq(W) - 4)); +} diff --git a/lib/maths.h b/lib/maths.h new file mode 100644 index 0000000..89cb7cb --- /dev/null +++ b/lib/maths.h @@ -0,0 +1,61 @@ +#ifndef MATH_H +#define MATH_H + +#include <glm/glm.hpp> +#include <glm/gtc/constants.hpp> +#include <utility> + +struct Arc : public std::pair<float, float> { + using std::pair<float, float>::pair; + + Arc(const glm::vec3 & centre3, const glm::vec3 & e0p, const glm::vec3 & e1p); + + float + operator[](unsigned int i) const + { + return i ? second : first; + } +}; + +constexpr const glm::vec3 up {0, 1, 0}; +constexpr const glm::vec3 north {0, 0, 1}; +constexpr const glm::vec3 south {0, 0, -1}; +constexpr const glm::vec3 east {-1, 0, 0}; +constexpr const glm::vec3 west {1, 0, 0}; +constexpr auto half_pi {glm::half_pi<float>()}; +constexpr auto pi {glm::pi<float>()}; +constexpr auto two_pi {glm::two_pi<float>()}; + +glm::mat4 flat_orientation(const glm::vec3 & diff); + +float vector_yaw(const glm::vec3 & diff); +float vector_pitch(const glm::vec3 & diff); + +float round_frac(const float & v, const float & frac); + +constexpr inline glm::vec2 +operator!(const glm::vec3 & v) +{ + return {v.x, v.z}; +} + +constexpr inline glm::vec3 +operator!(const glm::vec2 & v) +{ + return {v.x, 0, v.y}; +} + +constexpr inline float +arc_length(const Arc & arc) +{ + return arc.second - arc.first; +} + +float normalize(float ang); + +std::pair<glm::vec2, bool> find_arc_centre(glm::vec2 start, float entrys, glm::vec2 end, float entrye); +std::pair<glm::vec2, bool> find_arc_centre(glm::vec2 start, glm::vec2 ad, glm::vec2 end, glm::vec2 bd); +std::pair<float, float> find_arcs_radius(glm::vec2 start, float entrys, glm::vec2 end, float entrye); +float find_arcs_radius(glm::vec2 start, glm::vec2 ad, glm::vec2 end, glm::vec2 bd); + +#endif diff --git a/lib/ptr.hpp b/lib/ptr.hpp new file mode 100644 index 0000000..b92b63e --- /dev/null +++ b/lib/ptr.hpp @@ -0,0 +1,25 @@ +#ifndef PTR_H +#define PTR_H + +#include <memory> + +template<typename Obj> class wrapped_ptr : public std::unique_ptr<Obj, void (*)(Obj *)> { +public: + using std::unique_ptr<Obj, void (*)(Obj *)>::unique_ptr; + wrapped_ptr() : std::unique_ptr<Obj, void (*)(Obj *)> {{}, {}} { } + + inline + operator Obj *() const + { + return this->get(); + } + + template<typename... Args, typename... Params> + static auto + create(Obj * (*factory)(Args...), void (*deleter)(Obj *), Params &&... params) + { + return wrapped_ptr<Obj> {factory(std::forward<Params>(params)...), deleter}; + } +}; + +#endif diff --git a/lib/sorting.hpp b/lib/sorting.hpp new file mode 100644 index 0000000..0cb0eaf --- /dev/null +++ b/lib/sorting.hpp @@ -0,0 +1,12 @@ +#ifndef SORTING_H +#define SORTING_H + +template<typename T> struct PtrSorter { + bool + operator()(const T & a, const T & b) const + { + return *a < *b; + } +}; + +#endif diff --git a/lib/special_members.hpp b/lib/special_members.hpp new file mode 100644 index 0000000..0d63f58 --- /dev/null +++ b/lib/special_members.hpp @@ -0,0 +1,18 @@ +#ifndef SPECIAL_MEMBERS_H +#define SPECIAL_MEMBERS_H + +#define NO_COPY(TYPE) \ + TYPE(const TYPE &) = delete; \ + void operator=(const TYPE &) = delete + +#define NO_MOVE(TYPE) \ + TYPE(TYPE &&) = delete; \ + void operator=(TYPE &&) = delete + +#define DEFAULT_MOVE_COPY(TYPE) \ + TYPE(const TYPE &) = default; \ + TYPE(TYPE &&) = default; \ + TYPE & operator=(const TYPE &) = default; \ + TYPE & operator=(TYPE &&) = default + +#endif diff --git a/lib/stream_support.hpp b/lib/stream_support.hpp new file mode 100644 index 0000000..1ee1661 --- /dev/null +++ b/lib/stream_support.hpp @@ -0,0 +1,42 @@ +#ifndef STREAM_SUPPORT_H +#define STREAM_SUPPORT_H + +#include <glm/glm.hpp> +#include <iostream> +#include <maths.h> + +namespace std { + template<glm::length_t L, glm::length_t R, typename T, glm::qualifier Q> + std::ostream & + operator<<(std::ostream & s, const glm::mat<L, R, T, Q> & m) + { + for (int y = 0; y < m.length(); y++) { + const auto & col = m[y]; + for (int x = 0; x < col.length(); x++) { + s << col[x] << ", "; + } + s << "\n"; + } + return s; + } + + template<glm::length_t L, typename T, glm::qualifier Q> + std::ostream & + operator<<(std::ostream & s, const glm::vec<L, T, Q> & v) + { + for (int x = 0; x < L; x++) { + s << v[x] << ", "; + } + return s; + } + + inline std::ostream & + operator<<(std::ostream & s, const Arc & arc) + { + return s << arc.first << " ↺ " << arc.second; + } +} + +#define CLOG(x) std::clog << #x " : " << x << "\n"; + +#endif |