summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/collection.hpp71
-rw-r--r--lib/embed-glsl.cpp.m411
-rw-r--r--lib/embed-glsl.h.m44
-rw-r--r--lib/glRef.hpp56
-rw-r--r--lib/maths.cpp128
-rw-r--r--lib/maths.h61
-rw-r--r--lib/ptr.hpp25
-rw-r--r--lib/sorting.hpp12
-rw-r--r--lib/special_members.hpp18
-rw-r--r--lib/stream_support.hpp42
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, &params...](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, &params...](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