summaryrefslogtreecommitdiff
path: root/game/network/network.impl.h
diff options
context:
space:
mode:
Diffstat (limited to 'game/network/network.impl.h')
-rw-r--r--game/network/network.impl.h90
1 files changed, 68 insertions, 22 deletions
diff --git a/game/network/network.impl.h b/game/network/network.impl.h
index ff29088..e339922 100644
--- a/game/network/network.impl.h
+++ b/game/network/network.impl.h
@@ -1,13 +1,15 @@
+#include "collections.h"
#include "network.h"
+#include <game/geoData.h>
#include <gfx/gl/sceneShader.h>
#include <gfx/models/texture.h>
template<typename T, typename... Links>
void
-NetworkOf<T, Links...>::joinLinks(const Link::Ptr & l) const
+NetworkOf<T, Links...>::joinLinks(const Link::Ptr & link) const
{
- for (const auto & ol : links.objects) {
- Network::joinLinks(l, ol);
+ for (const auto & oldLink : links) {
+ Network::joinLinks(link, oldLink);
}
}
@@ -16,11 +18,11 @@ Link::Ptr
NetworkOf<T, Links...>::intersectRayLinks(const Ray<GlobalPosition3D> & ray) const
{
// Click link
- if (const auto link = std::find_if(links.objects.begin(), links.objects.end(),
+ if (const auto link = std::find_if(links.begin(), links.end(),
[&ray](const std::shared_ptr<T> & link) {
return link->intersectRay(ray);
});
- link != links.objects.end()) {
+ link != links.end()) {
return *link;
}
return {};
@@ -30,11 +32,11 @@ template<typename T, typename... Links>
float
NetworkOf<T, Links...>::findNodeDirection(Node::AnyCPtr n) const
{
- for (const auto & l : links.objects) {
- for (const auto & e : l->ends) {
+ for (const auto & link : links) {
+ for (const auto & end : link->ends) {
// cppcheck-suppress useStlAlgorithm
- if (e.node.get() == n.get()) {
- return e.dir;
+ if (end.node.get() == n.get()) {
+ return end.dir;
}
}
}
@@ -43,16 +45,17 @@ NetworkOf<T, Links...>::findNodeDirection(Node::AnyCPtr n) const
template<typename T, typename... Links>
Link::CCollection
-NetworkOf<T, Links...>::candidateStraight(GlobalPosition3D n1, GlobalPosition3D n2)
+NetworkOf<T, Links...>::candidateStraight(GlobalPosition3D positionA, GlobalPosition3D positionB)
{
- return {candidateLink<typename T::StraightLink>(n1, n2)};
+ return {candidateLink<typename T::StraightLink>(positionA, positionB)};
}
template<typename T, typename... Links>
Link::CCollection
NetworkOf<T, Links...>::candidateJoins(GlobalPosition3D start, GlobalPosition3D end)
{
- if (glm::length(RelativePosition3D(start - end)) < 2000.F) {
+ static constexpr auto MIN_DISTANCE = 2000.F;
+ if (::distance(start, end) < MIN_DISTANCE) {
return {};
}
const auto defs = genCurveDef(
@@ -72,28 +75,71 @@ NetworkOf<T, Links...>::candidateExtend(GlobalPosition3D start, GlobalPosition3D
template<typename T, typename... Links>
Link::CCollection
-NetworkOf<T, Links...>::addStraight(GlobalPosition3D n1, GlobalPosition3D n2)
+NetworkOf<T, Links...>::addStraight(const GeoData * geoData, GlobalPosition3D positionA, GlobalPosition3D positionB)
{
- return {addLink<typename T::StraightLink>(n1, n2)};
+ Link::CCollection out;
+ geoData->walk(positionA.xy(), positionB, [geoData, &out, this, &positionA](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(addLink<typename T::StraightLink>(positionA, surfaceEdgePosition));
+ positionA = surfaceEdgePosition;
+ }
+ });
+ out.emplace_back(addLink<typename T::StraightLink>(positionA, positionB));
+ return out;
+}
+
+template<typename T, typename... Links>
+Link::CCollection
+NetworkOf<T, Links...>::addCurve(const GeoData * geoData, const GenCurveDef & curve)
+{
+ static constexpr auto MIN_DISTANCE = 2000.F;
+ auto [cstart, cend, centre] = curve;
+ Link::CCollection out;
+ 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);
+ std::ranges::transform(points | std::views::pairwise, std::back_inserter(out), [this, centre](const auto pair) {
+ const auto [a, b] = pair;
+ return this->addLink<typename T::CurveLink>(a, b, centre);
+ });
+ return out;
}
template<typename T, typename... Links>
Link::CCollection
-NetworkOf<T, Links...>::addJoins(GlobalPosition3D start, GlobalPosition3D end)
+NetworkOf<T, Links...>::addJoins(const GeoData * geoData, GlobalPosition3D start, GlobalPosition3D end)
{
- if (glm::length(RelativePosition3D(start - end)) < 2000.F) {
+ static constexpr auto MIN_DISTANCE = 2000.F;
+ if (::distance(start, end) < MIN_DISTANCE) {
return {};
}
const auto defs = genCurveDef(start, end, findNodeDirection(nodeAt(start)), findNodeDirection(nodeAt(end)));
- const auto & [c1s, c1e, c1c] = defs.first;
- const auto & [c2s, c2e, c2c] = defs.second;
- return {addLink<typename T::CurveLink>(c1s, c1e, c1c), addLink<typename T::CurveLink>(c2s, c2e, c2c)};
+ return addCurve(geoData, defs.first) + addCurve(geoData, defs.second);
}
template<typename T, typename... Links>
Link::CCollection
-NetworkOf<T, Links...>::addExtend(GlobalPosition3D start, GlobalPosition3D end)
+NetworkOf<T, Links...>::addExtend(const GeoData * geoData, GlobalPosition3D start, GlobalPosition3D end)
{
- const auto [cstart, cend, centre] = genCurveDef(start, end, findNodeDirection(nodeAt(start)));
- return {addLink<typename T::CurveLink>(cstart, cend, centre)};
+ return addCurve(geoData, genCurveDef(start, end, findNodeDirection(nodeAt(start))));
}