summaryrefslogtreecommitdiff
path: root/game
diff options
context:
space:
mode:
Diffstat (limited to 'game')
-rw-r--r--game/network/network.cpp17
-rw-r--r--game/network/network.h10
-rw-r--r--game/network/network.impl.h15
3 files changed, 42 insertions, 0 deletions
diff --git a/game/network/network.cpp b/game/network/network.cpp
index f59fe1e..775d420 100644
--- a/game/network/network.cpp
+++ b/game/network/network.cpp
@@ -5,7 +5,9 @@
#include <filesystem>
#include <game/network/link.h>
#include <gfx/models/texture.h>
+#include <glm/gtx/intersect.hpp>
#include <initializer_list>
+#include <ray.hpp>
#include <stdexcept>
#include <utility>
@@ -33,6 +35,21 @@ Network::findNodeAt(glm::vec3 pos) const
return {};
}
+Network::IntersectRayResult
+Network::intersectRay(const Ray & ray) const
+{
+ // Click within 2m of a node
+ if (const auto node = std::find_if(nodes.begin(), nodes.end(),
+ [&ray](const NodePtr & node) {
+ glm::vec3 ipos, inorm;
+ return glm::intersectRaySphere(ray.start, ray.direction, node->pos, 2.F, ipos, inorm);
+ });
+ node != nodes.end()) {
+ return *node;
+ }
+ return intersectRayLinks(ray);
+}
+
void
Network::joinLinks(const LinkPtr & l, const LinkPtr & ol)
{
diff --git a/game/network/network.h b/game/network/network.h
index 2ce45f7..64f3f91 100644
--- a/game/network/network.h
+++ b/game/network/network.h
@@ -9,23 +9,30 @@
#include <sorting.hpp>
#include <string>
#include <utility>
+#include <variant>
class Texture;
class Shader;
+class Ray;
class Network {
public:
+ using LinkEnd = std::pair<LinkPtr, unsigned char>;
+ using IntersectRayResult = std::variant<std::nullptr_t, NodePtr, LinkEnd, LinkPtr>;
explicit Network(const std::string & textureName);
+ virtual ~Network() = default;
[[nodiscard]] NodePtr findNodeAt(glm::vec3) const;
[[nodiscard]] NodePtr nodeAt(glm::vec3);
[[nodiscard]] std::pair<NodePtr, bool> newNodeAt(glm::vec3);
+ [[nodiscard]] IntersectRayResult intersectRay(const Ray &) const;
[[nodiscard]] Link::Nexts routeFromTo(const Link::End &, glm::vec3) const;
[[nodiscard]] Link::Nexts routeFromTo(const Link::End &, const NodePtr &) const;
protected:
static void joinLinks(const LinkPtr & l, const LinkPtr & ol);
+ [[nodiscard]] virtual IntersectRayResult intersectRayLinks(const Ray &) const = 0;
using Nodes = std::set<NodePtr, PtrSorter<NodePtr>>;
Nodes nodes;
@@ -39,6 +46,9 @@ protected:
Collection<T> links;
void joinLinks(const LinkPtr &) const;
+protected:
+ [[nodiscard]] IntersectRayResult intersectRayLinks(const Ray &) const override;
+
public:
template<typename L, typename... Params>
std::shared_ptr<L>
diff --git a/game/network/network.impl.h b/game/network/network.impl.h
index d2e9ff0..afc9304 100644
--- a/game/network/network.impl.h
+++ b/game/network/network.impl.h
@@ -21,3 +21,18 @@ NetworkOf<T>::joinLinks(const LinkPtr & l) const
Network::joinLinks(l, ol);
}
}
+
+template<typename T>
+Network::IntersectRayResult
+NetworkOf<T>::intersectRayLinks(const Ray & ray) const
+{
+ // Click link
+ if (const auto link = std::find_if(links.objects.begin(), links.objects.end(),
+ [&ray](const std::shared_ptr<T> & link) {
+ return link->intersectRay(ray);
+ });
+ link != links.objects.end()) {
+ return *link;
+ }
+ return {};
+}