summaryrefslogtreecommitdiff
path: root/game/geoDataMesh.h
blob: 00db67c314eb44b7dbc84638f53b4f4f2c7eaa2b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
#pragma once

#include "config/types.h"
#include "ray.h"
#include "triangle.h"
#include <OpenMesh/Core/Mesh/TriMesh_ArrayKernelT.hh>
#include <source_location>
#include <thirdparty/openmesh/glmcompat.h>
#include <thirdparty/openmesh/helpers.h>

struct GeoDataTraits : public OpenMesh::DefaultTraits {
	FaceAttributes(OpenMesh::Attributes::Status);
	EdgeAttributes(OpenMesh::Attributes::Status);
	VertexAttributes(OpenMesh::Attributes::Normal | OpenMesh::Attributes::Status);
	HalfedgeAttributes(OpenMesh::Attributes::Status);
	using Point = GlobalPosition3D;
	using Normal = Normal3D;
};

class GeoDataMesh : public OpenMesh::TriMesh_ArrayKernelT<GeoDataTraits> {
public:
	struct PointFace {
		// NOLINTNEXTLINE(hicpp-explicit-conversions)
		PointFace(GlobalPosition2D coord) : point {coord} { }

		PointFace(GlobalPosition2D coord, FaceHandle face) : point {coord}, faceCache {face} { }

		PointFace(GlobalPosition2D coord, const GeoDataMesh *);
		PointFace(GlobalPosition2D coord, GeoDataMesh const *, FaceHandle start);

		const GlobalPosition2D point;
		[[nodiscard]] FaceHandle face(const GeoDataMesh *) const;
		[[nodiscard]] FaceHandle face(const GeoDataMesh *, FaceHandle start) const;

		[[nodiscard]] bool
		isLocated() const
		{
			return faceCache.is_valid();
		}

	private:
		mutable FaceHandle faceCache;
	};

	template<glm::length_t Dim> using Triangle = ::Triangle<Dim, GlobalDistance>;

	[[nodiscard]] FaceHandle findPoint(GlobalPosition2D) const;
	[[nodiscard]] FaceHandle findPoint(GlobalPosition2D, FaceHandle) const;

	[[nodiscard]] GlobalPosition3D positionAt(const PointFace &) const;

protected:
	void sanityCheck(const std::source_location & = std::source_location::current()) const;

	[[nodiscard]] bool faceContainsPoint(GlobalPosition2D, FaceHandle) const;
	[[nodiscard]] HalfedgeHandle findBoundaryStart() const;
	[[nodiscard]] RelativePosition3D difference(HalfedgeHandle) const;
	using HalfEdgeVertices = std::pair<VertexHandle, VertexHandle>;
	[[nodiscard]] HalfEdgeVertices toVertexHandles(HalfedgeHandle) const;
	using HalfEdgePoints = std::pair<GlobalPosition3D, GlobalPosition3D>;
	[[nodiscard]] HalfEdgePoints points(HalfEdgeVertices) const;

	template<glm::length_t D>
	[[nodiscard]] RelativeDistance
	length(HalfedgeHandle heh) const
	{
		return ::distance<D, GlobalDistance, glm::defaultp>(
				point(to_vertex_handle(heh)), point(from_vertex_handle(heh)));
	}

	[[nodiscard]] GlobalPosition3D centre(HalfedgeHandle) const;

	template<glm::length_t Dim>
	[[nodiscard]] Triangle<Dim>
	triangle(FaceHandle face) const
	{
		Triangle<Dim> triangle;
		std::ranges::transform(fv_range(face), triangle.begin(), [this](auto vertex) {
			return point(vertex);
		});
		return triangle;
	}
};