diff options
Diffstat (limited to 'game/geoData.h')
-rw-r--r-- | game/geoData.h | 131 |
1 files changed, 89 insertions, 42 deletions
diff --git a/game/geoData.h b/game/geoData.h index 3bceb9c..3141dbe 100644 --- a/game/geoData.h +++ b/game/geoData.h @@ -1,63 +1,110 @@ #pragma once +#include "collections.h" // IWYU pragma: keep IterableCollection #include "config/types.h" -#include <array> +#include "ray.h" +#include <OpenMesh/Core/Mesh/TriMesh_ArrayKernelT.hh> #include <filesystem> -#include <glm/glm.hpp> +#include <glm/vec2.hpp> #include <optional> -#include <span> -#include <utility> -#include <vector> +#include <thirdparty/openmesh/glmcompat.h> -class Ray; +struct GeoDataTraits : public OpenMesh::DefaultTraits { + FaceAttributes(OpenMesh::Attributes::Normal | OpenMesh::Attributes::Status); + EdgeAttributes(OpenMesh::Attributes::Status); + VertexAttributes(OpenMesh::Attributes::Normal | OpenMesh::Attributes::Status); + HalfedgeAttributes(OpenMesh::Attributes::Normal | OpenMesh::Attributes::Status); + using Point = GlobalPosition3D; + using Normal = Normal3D; +}; -class GeoData { -public: - struct Node { - float height {-1500.F}; - }; +class GeoData : public OpenMesh::TriMesh_ArrayKernelT<GeoDataTraits> { +private: + GeoData() = default; - using Quad = std::array<Position3D, 4>; +public: + static GeoData loadFromAsciiGrid(const std::filesystem::path &); + static GeoData createFlat(GlobalPosition2D lower, GlobalPosition2D upper, GlobalDistance h); - using Limits = std::pair<glm::vec<2, int>, glm::vec<2, int>>; + struct PointFace { + // NOLINTNEXTLINE(hicpp-explicit-conversions) + PointFace(const GlobalPosition2D p) : point {p} { } - explicit GeoData(Limits limit, float scale = 10.F); + PointFace(const GlobalPosition2D p, FaceHandle face) : point {p}, _face {face} { } - void generateRandom(); - void loadFromImages(const std::filesystem::path &, float scale); + PointFace(const GlobalPosition2D p, const GeoData *); + PointFace(const GlobalPosition2D p, const GeoData *, FaceHandle start); - [[nodiscard]] Position3D positionAt(Position2D) const; - [[nodiscard]] std::optional<Position3D> intersectRay(const Ray &) const; + const GlobalPosition2D point; + [[nodiscard]] FaceHandle face(const GeoData *) const; + [[nodiscard]] FaceHandle face(const GeoData *, FaceHandle start) const; - [[nodiscard]] unsigned int at(glm::vec<2, int>) const; - [[nodiscard]] unsigned int at(int x, int y) const; - [[nodiscard]] Quad quad(Position2D) const; + [[nodiscard]] bool + isLocated() const + { + return _face.is_valid(); + } - [[nodiscard]] Limits getLimit() const; - [[nodiscard]] glm::vec<2, unsigned int> getSize() const; - [[nodiscard]] float getScale() const; - [[nodiscard]] std::span<const Node> getNodes() const; + private: + mutable FaceHandle _face {}; + }; - class RayTracer { - public: - RayTracer(Position2D p0, Position2D p1); + template<glm::length_t Dim> struct Triangle : public glm::vec<3, glm::vec<Dim, GlobalDistance>> { + using base = glm::vec<3, glm::vec<Dim, GlobalDistance>>; + using base::base; - Position2D next(); + template<IterableCollection Range> Triangle(const GeoData * m, Range range) + { + assert(std::distance(range.begin(), range.end()) == 3); + std::transform(range.begin(), range.end(), &base::operator[](0), [m](auto vh) { + return m->point(vh); + }); + } - private: - RayTracer(Position2D p0, Position2D p1, Position2D d); - RayTracer(Position2D p0, Position2D d, std::pair<float, float>, std::pair<float, float>); - static std::pair<float, float> byAxis(Position2D p0, Position2D p1, Position2D d, glm::length_t); - - Position2D p; - const Position2D d; - float error; - Position2D inc; + glm::vec<Dim, GlobalDistance> + operator*(BaryPosition bari) const + { + const auto & t {*this}; + return t[0] + GlobalPosition<Dim>(RelativePosition<Dim>(t[1] - t[0]) * bari.x) + + GlobalPosition<Dim>(RelativePosition<Dim>(t[2] - t[1]) * bari.y); + } }; + [[nodiscard]] FaceHandle findPoint(GlobalPosition2D) const; + [[nodiscard]] FaceHandle findPoint(GlobalPosition2D, FaceHandle start) const; + + [[nodiscard]] GlobalPosition3D positionAt(const PointFace &) const; + [[nodiscard]] std::optional<GlobalPosition3D> intersectRay(const Ray &) const; + [[nodiscard]] std::optional<GlobalPosition3D> intersectRay(const Ray &, FaceHandle start) const; + + void walk(const PointFace & from, const GlobalPosition2D to, const std::function<void(FaceHandle)> & op) const; + void walkUntil(const PointFace & from, const GlobalPosition2D to, const std::function<bool(FaceHandle)> & op) const; + + void boundaryWalk(const std::function<void(HalfedgeHandle)> &) const; + void boundaryWalk(const std::function<void(HalfedgeHandle)> &, HalfedgeHandle start) const; + void boundaryWalkUntil(const std::function<bool(HalfedgeHandle)> &) const; + void boundaryWalkUntil(const std::function<bool(HalfedgeHandle)> &, HalfedgeHandle start) const; + + [[nodiscard]] HalfedgeHandle findEntry(const GlobalPosition2D from, const GlobalPosition2D to) const; + + [[nodiscard]] auto + getExtents() const + { + return std::tie(lowerExtent, upperExtent); + } + protected: - Limits limit {}; // Base grid limits first(x,y) -> second(x,y) - glm::vec<2, unsigned> size {}; - float scale {1}; - std::vector<Node> nodes; + template<glm::length_t Dim> + [[nodiscard]] Triangle<Dim> + triangle(FaceHandle f) const + { + return {this, fv_range(f)}; + } + + [[nodiscard]] static bool triangleContainsPoint(const GlobalPosition2D, const Triangle<2> &); + [[nodiscard]] bool triangleContainsPoint(const GlobalPosition2D, FaceHandle) const; + [[nodiscard]] HalfedgeHandle findBoundaryStart() const; + +private: + GlobalPosition3D lowerExtent {}, upperExtent {}; }; |