diff options
author | Dan Goodliffe <dan@randomdan.homeip.net> | 2025-05-12 00:23:42 +0100 |
---|---|---|
committer | Dan Goodliffe <dan@randomdan.homeip.net> | 2025-05-12 00:23:42 +0100 |
commit | b3105c56c277f6e1e27a3e5e5ee5e1b6c3f47afd (patch) | |
tree | 2f136cb121ef5aa5a78267ccbfa220ca87b56aac /game/network | |
parent | Split definition creation from link creation (diff) | |
download | ilt-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.cpp | 75 | ||||
-rw-r--r-- | game/network/network.h | 5 |
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; |