summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Goodliffe <dan@randomdan.homeip.net>2023-11-03 20:12:03 +0000
committerDan Goodliffe <dan@randomdan.homeip.net>2023-11-03 20:12:03 +0000
commit3931bda936aba6ddae26c1d9f1d450781df800e8 (patch)
treec66bb3e540354baa2e45a782d8ae1f012be33a96
parentHelper to get cartesian position from baricentric on Triangle (diff)
downloadilt-3931bda936aba6ddae26c1d9f1d450781df800e8.tar.bz2
ilt-3931bda936aba6ddae26c1d9f1d450781df800e8.tar.xz
ilt-3931bda936aba6ddae26c1d9f1d450781df800e8.zip
Implement terrain intersect ray
-rw-r--r--game/terrain2.cpp23
-rw-r--r--game/terrain2.h4
-rw-r--r--test/test-terrain.cpp12
3 files changed, 39 insertions, 0 deletions
diff --git a/game/terrain2.cpp b/game/terrain2.cpp
index b129284..d1af221 100644
--- a/game/terrain2.cpp
+++ b/game/terrain2.cpp
@@ -135,6 +135,29 @@ TerrainMesh::positionAt(const PointFace & p) const
return p.point ^ out[0];
}
+[[nodiscard]] std::optional<glm::vec3>
+TerrainMesh::intersectRay(const Ray & ray) const
+{
+ return intersectRay(ray, findPoint(ray.start));
+}
+
+[[nodiscard]] std::optional<glm::vec3>
+TerrainMesh::intersectRay(const Ray & ray, FaceHandle face) const
+{
+ std::optional<glm::vec3> out;
+ walkUntil(PointFace {ray.start, face}, ray.start + (ray.direction * 10000.F), [&out, &ray, this](FaceHandle face) {
+ glm::vec2 bari {};
+ float dist {};
+ Triangle<3> t {this, fv_range(face)};
+ if (glm::intersectRayTriangle(ray.start, ray.direction, t[0], t[1], t[2], bari, dist)) {
+ out = t * bari;
+ return true;
+ }
+ return false;
+ });
+ return out;
+}
+
void
TerrainMesh::walk(const PointFace & from, const glm::vec2 to, const std::function<void(FaceHandle)> & op) const
{
diff --git a/game/terrain2.h b/game/terrain2.h
index da9f823..5539a50 100644
--- a/game/terrain2.h
+++ b/game/terrain2.h
@@ -1,9 +1,11 @@
#pragma once
#include "collections.h" // IWYU pragma: keep IterableCollection
+#include "ray.h"
#include <OpenMesh/Core/Mesh/TriMesh_ArrayKernelT.hh>
#include <filesystem>
#include <glm/vec2.hpp>
+#include <optional>
#include <thirdparty/openmesh/glmcompat.h>
struct TerrainTraits : public OpenMesh::DefaultTraits {
@@ -66,6 +68,8 @@ public:
[[nodiscard]] FaceHandle findPoint(glm::vec2, FaceHandle start) const;
[[nodiscard]] glm::vec3 positionAt(const PointFace &) const;
+ [[nodiscard]] std::optional<glm::vec3> intersectRay(const Ray &) const;
+ [[nodiscard]] std::optional<glm::vec3> intersectRay(const Ray &, FaceHandle start) const;
void walk(const PointFace & from, const glm::vec2 to, const std::function<void(FaceHandle)> & op) const;
void walkUntil(const PointFace & from, const glm::vec2 to, const std::function<bool(FaceHandle)> & op) const;
diff --git a/test/test-terrain.cpp b/test/test-terrain.cpp
index 38cb51f..53eebfb 100644
--- a/test/test-terrain.cpp
+++ b/test/test-terrain.cpp
@@ -104,6 +104,18 @@ BOOST_DATA_TEST_CASE(findPositionAt,
BOOST_CHECK_CLOSE_VEC(fixedTerrtain.positionAt(p), p ^ h);
}
+using FindRayIntersectData = std::tuple<glm::vec3, glm::vec3, glm::vec3>;
+
+BOOST_DATA_TEST_CASE(findRayIntersect,
+ boost::unit_test::data::make<FindRayIntersectData>({
+ {{310000, 490000, 50}, {1, 1, -2}, {310008.59, 490008.59, 32.834301}},
+ {{310000, 490000, 50}, {1, 1, -1}, {310017.12, 490017.12, 32.868526}},
+ }),
+ p, d, i)
+{
+ BOOST_CHECK_CLOSE_VEC(fixedTerrtain.intersectRay({p, d}).value(), i);
+}
+
using WalkTerrainData = std::tuple<glm::vec2, glm::vec2, std::vector<int>>;
BOOST_DATA_TEST_CASE(walkTerrain,