summaryrefslogtreecommitdiff
path: root/game/network
diff options
context:
space:
mode:
authorDan Goodliffe <dan@randomdan.homeip.net>2025-05-12 00:23:42 +0100
committerDan Goodliffe <dan@randomdan.homeip.net>2025-05-12 00:23:42 +0100
commitb3105c56c277f6e1e27a3e5e5ee5e1b6c3f47afd (patch)
tree2f136cb121ef5aa5a78267ccbfa220ca87b56aac /game/network
parentSplit definition creation from link creation (diff)
downloadilt-b3105c56c277f6e1e27a3e5e5ee5e1b6c3f47afd.tar.bz2
ilt-b3105c56c277f6e1e27a3e5e5ee5e1b6c3f47afd.tar.xz
ilt-b3105c56c277f6e1e27a3e5e5ee5e1b6c3f47afd.zip
Split link generation definitions according to terrain
Copies the same imperfect logic from old link addition functions.
Diffstat (limited to 'game/network')
-rw-r--r--game/network/network.cpp75
-rw-r--r--game/network/network.h5
2 files changed, 77 insertions, 3 deletions
diff --git a/game/network/network.cpp b/game/network/network.cpp
index 561cafb..1c3a122 100644
--- a/game/network/network.cpp
+++ b/game/network/network.cpp
@@ -1,6 +1,8 @@
#include "network.h"
+#include "game/geoData.h"
#include "routeWalker.h"
#include <array>
+#include <collections.h>
#include <game/network/link.h>
#include <gfx/models/texture.h>
#include <glm/gtx/intersect.hpp>
@@ -96,6 +98,66 @@ Network::routeFromTo(const Link::End & end, const Node::Ptr & dest)
return RouteWalker().findRouteTo(end, dest);
}
+void
+Network::terrainSplitAt(GenLinkDef & previous, GenLinkDef & next, GlobalPosition3D pos)
+{
+ std::visit(
+ [pos](auto & typedDefPrevious, auto & typedDefNext) {
+ std::get<1>(typedDefPrevious) = std::get<0>(typedDefNext) = pos;
+ },
+ previous, next);
+}
+
+GenLinksDef
+Network::terrainSplit(const GeoData * geoData, const GenStraightDef & def) const
+{
+ GenLinksDef out {def};
+ const auto [fromPos, toPos] = def;
+ geoData->walk(fromPos.xy(), toPos, [geoData, &out](const GeoData::WalkStep & step) {
+ if (step.previous.is_valid() && geoData->getSurface(step.current) != geoData->getSurface(step.previous)) {
+ const auto surfaceEdgePosition = geoData->positionAt(GeoData::PointFace(step.exitPosition, step.current));
+ out.emplace_back(out.back());
+ terrainSplitAt(*out.rbegin(), *++out.rbegin(), surfaceEdgePosition);
+ }
+ });
+ return out;
+}
+
+GenLinksDef
+Network::terrainSplit(const GeoData * geoData, const GenCurveDef & def) const
+{
+ static constexpr auto MIN_DISTANCE = 2000.F;
+ auto [cstart, cend, centre] = def;
+ std::set<GeoData::WalkStepCurve, SortedBy<&GeoData::WalkStepCurve::angle>> breaks;
+ const auto radiusMid = ::distance(cstart.xy(), centre);
+ for (const auto radiusOffset : {-getBaseWidth() / 2.F, 0.F, getBaseWidth() / 2.F}) {
+ const auto radius = radiusOffset + radiusMid;
+ const auto start = centre + (difference(cstart.xy(), centre) * radius) / radiusMid;
+ const auto end = centre + (difference(cend.xy(), centre) * radius) / radiusMid;
+ geoData->walk(start, end, centre, [geoData, &breaks](const GeoData::WalkStepCurve & step) {
+ if (step.previous.is_valid() && geoData->getSurface(step.current) != geoData->getSurface(step.previous)) {
+ breaks.insert(step);
+ }
+ });
+ }
+ std::vector<GlobalPosition3D> points;
+ points.reserve(breaks.size() + 2);
+ points.push_back(cstart);
+ std::ranges::transform(
+ breaks, std::back_inserter(points), [geoData, centre, radiusMid](const GeoData::WalkStepCurve & step) {
+ return (centre + (sincos(step.angle) * radiusMid))
+ || geoData->positionAt(GeoData::PointFace(step.exitPosition, step.current)).z;
+ });
+ points.push_back(cend);
+ mergeClose(points, ::distance<3, GlobalDistance>, ::midpoint<3, GlobalDistance>, MIN_DISTANCE);
+ GenLinksDef out {def};
+ std::ranges::for_each(++points.begin(), --points.end(), [&out](const auto pos) {
+ out.emplace_back(out.back());
+ terrainSplitAt(*out.rbegin(), *++out.rbegin(), pos);
+ });
+ return out;
+}
+
GenCurveDef
Network::genCurveDef(const GlobalPosition3D & start, const GlobalPosition3D & end, float startDir)
{
@@ -144,7 +206,7 @@ Network::genCurveDef(const GlobalPosition3D & start, const GlobalPosition3D & en
}
Link::Collection
-Network::create(const CreationDefinition & def)
+Network::create(const GeoData * geoData, const CreationDefinition & def)
{
// TODO
// Where to make a straight to join because angles align?
@@ -168,8 +230,17 @@ Network::create(const CreationDefinition & def)
// One specific direction, single curve from the other
return {genCurveDef(def.toEnd.position, def.fromEnd.position, *def.toEnd.direction)};
};
+ const auto splitDefs = [&linkDefs, this, geoData]() {
+ return std::ranges::fold_left(linkDefs(), GenLinksDef {}, [this, geoData](auto && existing, const auto & def) {
+ return existing += std::visit(
+ [this, geoData](const auto & typedDef) {
+ return this->terrainSplit(geoData, typedDef);
+ },
+ def);
+ });
+ };
Link::Collection links;
- std::ranges::transform(linkDefs(), std::back_inserter(links), [this](const auto & def) {
+ std::ranges::transform(geoData ? splitDefs() : linkDefs(), std::back_inserter(links), [this](const auto & def) {
return std::visit(
[this](const auto & typedDef) {
return this->create(typedDef);
diff --git a/game/network/network.h b/game/network/network.h
index 153b410..65db016 100644
--- a/game/network/network.h
+++ b/game/network/network.h
@@ -64,7 +64,7 @@ public:
[[nodiscard]] virtual float findNodeDirection(Node::AnyCPtr) const = 0;
- [[nodiscard]] Link::Collection create(const CreationDefinition &);
+ [[nodiscard]] Link::Collection create(const GeoData *, const CreationDefinition &);
virtual void add(GeoData *, const Link::Ptr &) = 0;
[[nodiscard]] virtual const Surface * getBaseSurface() const = 0;
@@ -76,6 +76,9 @@ protected:
static std::pair<GenCurveDef, GenCurveDef> genCurveDef(
const GlobalPosition3D & start, const GlobalPosition3D & end, float startDir, float endDir);
+ [[nodiscard]] GenLinksDef terrainSplit(const GeoData *, const GenStraightDef &) const;
+ [[nodiscard]] GenLinksDef terrainSplit(const GeoData *, const GenCurveDef &) const;
+ static void terrainSplitAt(GenLinkDef & previous, GenLinkDef & next, GlobalPosition3D pos);
[[nodiscard]] virtual Link::Ptr create(const GenStraightDef &) = 0;
[[nodiscard]] virtual Link::Ptr create(const GenCurveDef &) = 0;