From 16bec12e3e75e95d251745f904ac4e15af9c9724 Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Sat, 28 Oct 2023 02:34:45 +0100 Subject: Initial OpenMesh based terrain data and tests --- game/terrain2.cpp | 66 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ game/terrain2.h | 24 ++++++++++++++++++++ 2 files changed, 90 insertions(+) create mode 100644 game/terrain2.cpp create mode 100644 game/terrain2.h (limited to 'game') 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 + +TerrainMesh::TerrainMesh(const std::filesystem::path & input) +{ + size_t ncols = 0, nrows = 0, xllcorner = 0, yllcorner = 0, cellsize = 0; + std::map 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 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 +#include +#include +#include + +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 { +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; +}; -- cgit v1.2.3