diff options
author | Dan Goodliffe <dan@randomdan.homeip.net> | 2024-04-04 20:06:36 +0100 |
---|---|---|
committer | Dan Goodliffe <dan@randomdan.homeip.net> | 2024-04-04 20:06:36 +0100 |
commit | 30b027f84772d4b1d18eebd03b83ce3a5966d5fe (patch) | |
tree | bf1f424ee3c92516d652934cf502ee06f60c57e5 /lib | |
parent | Simplify vector addition/subtraction with differnt types (diff) | |
parent | Remove wireframe mode from test renders (diff) | |
download | ilt-30b027f84772d4b1d18eebd03b83ce3a5966d5fe.tar.bz2 ilt-30b027f84772d4b1d18eebd03b83ce3a5966d5fe.tar.xz ilt-30b027f84772d4b1d18eebd03b83ce3a5966d5fe.zip |
Merge remote-tracking branch 'origin/deform-terrain'
Two related issues remain:
* Terrain self shadowing is common and handled poorly
* Odd, but mathematically correct patterns/stripes in feature boundaries
Neither of these relate directly to deformation.
Diffstat (limited to 'lib')
-rw-r--r-- | lib/collections.h | 73 | ||||
-rw-r--r-- | lib/geometricPlane.h | 10 | ||||
-rw-r--r-- | lib/maths.cpp | 7 | ||||
-rw-r--r-- | lib/maths.h | 51 | ||||
-rw-r--r-- | lib/persistence.h | 65 | ||||
-rw-r--r-- | lib/ray.h | 16 | ||||
-rw-r--r-- | lib/stream_support.h | 16 |
7 files changed, 187 insertions, 51 deletions
diff --git a/lib/collections.h b/lib/collections.h index 943b986..dd603be 100644 --- a/lib/collections.h +++ b/lib/collections.h @@ -2,6 +2,7 @@ #include <algorithm> #include <array> +#include <cstdint> #include <span> #include <utility> #include <vector> @@ -129,18 +130,25 @@ vectorOfN(std::integral auto N, T start = {}, T step = 1) return v; } +template<template<typename...> typename Rtn = std::vector, typename In> +[[nodiscard]] auto +materializeRange(const In begin, const In end) +{ + return Rtn(begin, end); +} + template<template<typename...> typename Rtn = std::vector, IterableCollection In> [[nodiscard]] auto -materializeRange(In && in) +materializeRange(const In & in) { - return Rtn(in.begin(), in.end()); + return materializeRange<Rtn>(in.begin(), in.end()); } template<template<typename...> typename Rtn = std::vector, typename In> [[nodiscard]] auto materializeRange(const std::pair<In, In> & in) { - return Rtn(in.first, in.second); + return materializeRange<Rtn>(in.first, in.second); } template<typename T> struct pair_range { @@ -160,3 +168,62 @@ template<typename T> struct pair_range { }; template<typename T> pair_range(std::pair<T, T>) -> pair_range<T>; + +template<typename iter> struct stripiter { + [[nodiscard]] constexpr bool + operator!=(const stripiter & other) const + { + return current != other.current; + } + + [[nodiscard]] constexpr bool + operator==(const stripiter & other) const + { + return current == other.current; + } + + constexpr stripiter & + operator++() + { + ++current; + off = 1 - off; + return *this; + } + + constexpr stripiter & + operator--() + { + --current; + off = 1 - off; + return *this; + } + + constexpr auto + operator-(const stripiter & other) const + { + return current - other.current; + } + + constexpr auto + operator*() const + { + return std::tie(*(current - (2 - off)), *(current - off - 1), *current); + } + + iter current; + uint8_t off {}; +}; + +template<typename T> struct std::iterator_traits<stripiter<T>> : std::iterator_traits<T> { }; + +constexpr auto +strip_begin(IterableCollection auto & cont) +{ + return stripiter {cont.begin() + 2}; +} + +constexpr auto +strip_end(IterableCollection auto & cont) +{ + return stripiter {cont.end()}; +} diff --git a/lib/geometricPlane.h b/lib/geometricPlane.h index 3f95d3c..d4b803d 100644 --- a/lib/geometricPlane.h +++ b/lib/geometricPlane.h @@ -16,18 +16,22 @@ public: template<typename PositionType> class GeometricPlaneT : public GeometricPlane { public: + GeometricPlaneT() = default; + + GeometricPlaneT(PositionType origin, Normal3D normal) : origin(std::move(origin)), normal(normal) { } + struct DistAndPosition { PositionType::value_type dist; PositionType position; }; - PositionType origin; - Normal3D normal; + PositionType origin {}; + Normal3D normal {}; [[nodiscard]] inline PlaneRelation getRelation(PositionType point) const { - const auto d = glm::dot(normal, point - origin); + const auto d = glm::dot(normal, RelativePosition3D(point - origin)); return d < 0.F ? PlaneRelation::Below : d > 0.F ? PlaneRelation::Above : PlaneRelation::On; } diff --git a/lib/maths.cpp b/lib/maths.cpp index 68662fc..51e27fe 100644 --- a/lib/maths.cpp +++ b/lib/maths.cpp @@ -4,6 +4,11 @@ #include <glm/gtx/rotate_vector.hpp> #include <glm/gtx/transform.hpp> +Arc::Arc(const RelativePosition2D & dir0, const RelativePosition2D & dir1) : + Arc {vector_yaw(dir0), vector_yaw(dir1)} { } + +Arc::Arc(const Angle anga, const Angle angb) : pair {anga, (angb < anga) ? angb + two_pi : angb} { } + glm::mat4 flat_orientation(const Direction3D & diff) { @@ -76,7 +81,7 @@ rotate_yp(Rotation2D a) } float -vector_yaw(const Direction3D & diff) +vector_yaw(const Direction2D & diff) { return std::atan2(diff.x, diff.y); } diff --git a/lib/maths.h b/lib/maths.h index 5886326..63b752a 100644 --- a/lib/maths.h +++ b/lib/maths.h @@ -8,17 +8,28 @@ #include <stdexcept> #include <utility> -struct Arc : public std::pair<float, float> { - using std::pair<float, float>::pair; +struct Arc : public std::pair<Angle, Angle> { + template<glm::length_t Lc, glm::length_t Le, typename T, glm::qualifier Q> + requires(Lc >= 2, Le >= 2) + Arc(const glm::vec<Lc, T, Q> & centre, const glm::vec<Le, T, Q> & e0p, const glm::vec<Le, T, Q> & e1p) : + Arc {RelativePosition2D {e0p.xy() - centre.xy()}, RelativePosition2D {e1p.xy() - centre.xy()}} + { + } - template<typename T, glm::qualifier Q> - Arc(const glm::vec<3, T, Q> & centre3, const glm::vec<3, T, Q> & e0p, const glm::vec<3, T, Q> & e1p); + Arc(const RelativePosition2D & dir0, const RelativePosition2D & dir1); + Arc(const Angle angb, const Angle anga); auto operator[](bool i) const { return i ? second : first; } + + [[nodiscard]] constexpr inline float + length() const + { + return second - first; + } }; constexpr const RelativePosition3D up {0, 0, 1}; @@ -84,9 +95,16 @@ glm::mat4 rotate_pitch(float); glm::mat4 rotate_yp(Rotation2D); glm::mat4 rotate_ypr(Rotation3D); -float vector_yaw(const Direction3D & diff); +float vector_yaw(const Direction2D & diff); float vector_pitch(const Direction3D & diff); +template<typename T, glm::qualifier Q> +glm::vec<2, T, Q> +vector_normal(const glm::vec<2, T, Q> & v) +{ + return {-v.y, v.x}; +}; + float round_frac(const float & v, const float & frac); template<typename T> @@ -111,7 +129,7 @@ template<std::integral T, glm::qualifier Q> inline constexpr glm::vec<3, T, Q> crossProduct(const glm::vec<3, T, Q> a, const glm::vec<3, T, Q> b) { - return crossProduct<int64_t, Q>(a, b); + return crossProduct<Q>(a, b); } template<std::floating_point T, glm::qualifier Q> @@ -171,12 +189,6 @@ operator%=(glm::vec<L, T, Q> & p, const glm::mat<L + 1, L + 1, T, Q> & mutation) return p = p % mutation; } -constexpr inline float -arc_length(const Arc & arc) -{ - return arc.second - arc.first; -} - float normalize(float ang); template<typename T, glm::qualifier Q> @@ -244,21 +256,6 @@ midpoint(const std::pair<T, T> & v) return std::midpoint(v.first, v.second); } -template<typename T, glm::qualifier Q> -Arc::Arc(const glm::vec<3, T, Q> & centre3, const glm::vec<3, T, Q> & e0p, const glm::vec<3, T, Q> & 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}; - }()) -{ -} - // Conversions template<typename T> inline constexpr auto diff --git a/lib/persistence.h b/lib/persistence.h index c53ff99..3c95a00 100644 --- a/lib/persistence.h +++ b/lib/persistence.h @@ -81,11 +81,11 @@ namespace Persistence { return make_s<SelectionT<T>>(value); } - template<typename S> + template<typename S, typename... Extra> [[nodiscard]] static SelectionPtr - make_s(T & value) + make_s(T & value, Extra &&... extra) { - return std::make_unique<S>(value); + return std::make_unique<S>(value, std::forward<Extra>(extra)...); } T & v; @@ -331,6 +331,65 @@ namespace Persistence { } }; + template<typename... T> struct SelectionT<std::tuple<T...>> : public SelectionV<std::tuple<T...>> { + using V = std::tuple<T...>; + using SelectionV<V>::SelectionV; + + struct Members : public SelectionV<V> { + template<size_t... Idx> + explicit Members(V & v, std::integer_sequence<size_t, Idx...>) : + SelectionV<V> {v}, members {SelectionV<std::tuple_element_t<Idx, V>>::make(std::get<Idx>(v))...} + { + } + + void + beforeValue(Stack & stk) override + { + stk.push(std::move(members[idx++])); + } + + std::size_t idx {0}; + std::array<SelectionPtr, std::tuple_size_v<V>> members; + }; + + void + beginArray(Stack & stk) override + { + stk.push(this->template make_s<Members>( + this->v, std::make_integer_sequence<size_t, std::tuple_size_v<V>>())); + } + }; + + template<typename T, typename U> struct SelectionT<std::pair<T, U>> : public SelectionV<std::pair<T, U>> { + using V = std::pair<T, U>; + using SelectionV<V>::SelectionV; + + struct Members : public SelectionV<V> { + explicit Members(V & v) : + SelectionV<V> {v}, members { + SelectionV<T>::make(v.first), + SelectionV<U>::make(v.second), + } + { + } + + void + beforeValue(Stack & stk) override + { + stk.push(std::move(members[idx++])); + } + + std::size_t idx {0}; + std::array<SelectionPtr, 2> members; + }; + + void + beginArray(Stack & stk) override + { + stk.push(this->template make_s<Members>(this->v)); + } + }; + template<typename Map, typename Type = typename Map::mapped_type, auto Key = &Type::element_type::id> struct MapByMember : public Persistence::SelectionT<Type> { MapByMember(Map & m) : Persistence::SelectionT<Type> {s}, map {m} { } @@ -43,15 +43,27 @@ public: } bool + intersectPlane(const PositionType orig, const Direction3D norm, RelativeDistance & distance) const + { + if constexpr (std::is_floating_point_v<typename PositionType::value_type>) { + return glm::intersectRayPlane(start, direction, orig, norm, distance) && distance >= 0.F; + } + else { + const RelativePosition3D origr = orig - start; + return glm::intersectRayPlane({}, direction, origr, norm, distance) && distance >= 0.F; + } + } + + bool intersectTriangle(const PositionType t0, const PositionType t1, const PositionType t2, BaryPosition & bary, RelativeDistance & distance) const { if constexpr (std::is_floating_point_v<typename PositionType::value_type>) { - return glm::intersectRayTriangle(start, direction, t0, t1, t2, bary, distance); + return glm::intersectRayTriangle(start, direction, t0, t1, t2, bary, distance) && distance >= 0.F; } else { const RelativePosition3D t0r = t0 - start, t1r = t1 - start, t2r = t2 - start; - return glm::intersectRayTriangle({}, direction, t0r, t1r, t2r, bary, distance); + return glm::intersectRayTriangle({}, direction, t0r, t1r, t2r, bary, distance) && distance >= 0.F; } } diff --git a/lib/stream_support.h b/lib/stream_support.h index fa536f1..57d82a1 100644 --- a/lib/stream_support.h +++ b/lib/stream_support.h @@ -11,17 +11,16 @@ template<typename S> concept stringlike = requires(const S & s) { s.substr(0); }; template<typename T> -concept spanable = std::is_constructible_v<std::span<const typename T::value_type>, T> && !stringlike<T> - && !std::is_same_v<std::span<typename T::value_type>, T>; +concept NonStringIterableCollection + = std::is_same_v<decltype(std::declval<T>().begin()), decltype(std::declval<T>().end())> && !stringlike<T>; namespace std { - template<typename T, std::size_t L> std::ostream & - operator<<(std::ostream & s, const span<T, L> v) + operator<<(std::ostream & s, const NonStringIterableCollection auto & v) { s << '('; for (const auto & i : v) { - if (&i != &v.front()) { + if (&i != &*v.begin()) { s << ", "; } s << i; @@ -43,13 +42,6 @@ namespace std { return (s << std::span {&v[0], L}); } - template<spanable T> - std::ostream & - operator<<(std::ostream & s, const T & v) - { - return (s << std::span {v}); - } - template<typename First, typename Second> std::ostream & operator<<(std::ostream & s, const std::pair<First, Second> & v) |