summaryrefslogtreecommitdiff
path: root/game
diff options
context:
space:
mode:
authorDan Goodliffe <dan@randomdan.homeip.net>2023-10-28 02:34:45 +0100
committerDan Goodliffe <dan@randomdan.homeip.net>2023-10-28 12:35:11 +0100
commit16bec12e3e75e95d251745f904ac4e15af9c9724 (patch)
treefb4c24204dd1ff71fc55fb0b8a1eb909a35046fb /game
parentMove OpenMesh/GLM compatibility structs to common place (diff)
downloadilt-16bec12e3e75e95d251745f904ac4e15af9c9724.tar.bz2
ilt-16bec12e3e75e95d251745f904ac4e15af9c9724.tar.xz
ilt-16bec12e3e75e95d251745f904ac4e15af9c9724.zip
Initial OpenMesh based terrain data and tests
Diffstat (limited to 'game')
-rw-r--r--game/terrain2.cpp66
-rw-r--r--game/terrain2.h24
2 files changed, 90 insertions, 0 deletions
diff --git a/game/terrain2.cpp b/game/terrain2.cpp
new file mode 100644
index 0000000..83df3fa
--- /dev/null
+++ b/game/terrain2.cpp
@@ -0,0 +1,66 @@
+#include "terrain2.h"
+#include <fstream>
+
+TerrainMesh::TerrainMesh(const std::filesystem::path & input)
+{
+ size_t ncols = 0, nrows = 0, xllcorner = 0, yllcorner = 0, cellsize = 0;
+ std::map<std::string_view, size_t *> properties {
+ {"ncols", &ncols},
+ {"nrows", &nrows},
+ {"xllcorner", &xllcorner},
+ {"yllcorner", &yllcorner},
+ {"cellsize", &cellsize},
+ };
+ std::ifstream f {input};
+ while (!properties.empty()) {
+ std::string property;
+ f >> property;
+ f >> *properties.at(property);
+ properties.erase(property);
+ }
+ std::vector<VertexHandle> vertices;
+ vertices.reserve(ncols * nrows);
+ for (size_t row = 0; row < nrows; ++row) {
+ for (size_t col = 0; col < ncols; ++col) {
+ float height = 0;
+ f >> height;
+ vertices.push_back(add_vertex({xllcorner + (col * cellsize), yllcorner + (row * cellsize), height}));
+ }
+ }
+ if (!f.good()) {
+ throw std::runtime_error("Couldn't read terrain file");
+ }
+ for (size_t row = 1; row < nrows; ++row) {
+ for (size_t col = 1; col < ncols; ++col) {
+ add_face({
+ vertices[ncols * (row - 1) + (col - 1)],
+ vertices[ncols * (row - 0) + (col - 0)],
+ vertices[ncols * (row - 0) + (col - 1)],
+ });
+ add_face({
+ vertices[ncols * (row - 1) + (col - 1)],
+ vertices[ncols * (row - 1) + (col - 0)],
+ vertices[ncols * (row - 0) + (col - 0)],
+ });
+ }
+ }
+ update_face_normals();
+ update_vertex_normals();
+};
+
+bool
+TerrainMesh::triangleContainsPoint(const glm::vec2 p, const glm::vec2 a, const glm::vec2 b, const glm::vec2 c)
+{
+ const auto det = (b.x - a.x) * (c.y - a.y) - (b.y - a.y) * (c.x - a.x);
+
+ return det * ((b.x - a.x) * (p.y - a.y) - (b.y - a.y) * (p.x - a.x)) >= 0
+ && det * ((c.x - b.x) * (p.y - b.y) - (c.y - b.y) * (p.x - b.x)) >= 0
+ && det * ((a.x - c.x) * (p.y - c.y) - (a.y - c.y) * (p.x - c.x)) >= 0;
+}
+
+bool
+TerrainMesh::triangleContainsPoint(const glm::vec2 p, FaceHandle face) const
+{
+ auto vertices = cfv_iter(face);
+ return triangleContainsPoint(p, point(*vertices++), point(*vertices++), point(*vertices++));
+}
diff --git a/game/terrain2.h b/game/terrain2.h
new file mode 100644
index 0000000..d2da8d0
--- /dev/null
+++ b/game/terrain2.h
@@ -0,0 +1,24 @@
+#pragma once
+
+#include <OpenMesh/Core/Mesh/TriMesh_ArrayKernelT.hh>
+#include <filesystem>
+#include <glm/vec2.hpp>
+#include <thirdparty/openmesh/glmcompat.h>
+
+struct TerrainTraits : 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 = glm::vec3;
+ using Normal = glm::vec3;
+};
+
+class TerrainMesh : public OpenMesh::TriMesh_ArrayKernelT<TerrainTraits> {
+public:
+ explicit TerrainMesh(const std::filesystem::path &);
+
+protected:
+ [[nodiscard]] static bool triangleContainsPoint(const glm::vec2, const glm::vec2, const glm::vec2, const glm::vec2);
+ [[nodiscard]] bool triangleContainsPoint(const glm::vec2, FaceHandle) const;
+};