summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Goodliffe <dan@randomdan.homeip.net>2024-12-15 15:00:08 +0000
committerDan Goodliffe <dan@randomdan.homeip.net>2024-12-15 15:00:08 +0000
commitb4576e3a40d0416dea4e82042905598680fba3ee (patch)
treeefca277a0da322abe2c323f0e6a9f687c49140fb
parentTriangle height support (diff)
downloadilt-b4576e3a40d0416dea4e82042905598680fba3ee.tar.bz2
ilt-b4576e3a40d0416dea4e82042905598680fba3ee.tar.xz
ilt-b4576e3a40d0416dea4e82042905598680fba3ee.zip
Reuse close edges when adding new vertices for surface
-rw-r--r--game/geoData.cpp50
1 files changed, 37 insertions, 13 deletions
diff --git a/game/geoData.cpp b/game/geoData.cpp
index a5fc4ef..d3b5485 100644
--- a/game/geoData.cpp
+++ b/game/geoData.cpp
@@ -430,6 +430,19 @@ GeoData::setHeights(const std::span<const GlobalPosition3D> triangleStrip, const
return std::make_pair(v, glm::length(::difference(p, this->point(v).xy())));
};
};
+ const auto vertexDistFromE = [this](GlobalPosition2D p) {
+ return [p, this](const HalfedgeHandle e) {
+ const auto fromPoint = point(from_vertex_handle(e)).xy();
+ const auto toPoint = point(to_vertex_handle(e)).xy();
+ return std::make_pair(e, Triangle<2> {fromPoint, toPoint, p}.height());
+ };
+ };
+ const auto notBoundary = std::views::filter([this](auto handleItr) {
+ return !is_boundary(*handleItr);
+ });
+ const auto notEdgeBoundary = std::views::filter([this](auto handleItr) {
+ return !is_boundary(edge_handle(*handleItr));
+ });
std::set<VertexHandle> newOrChangedVerts;
auto addVertexForNormalUpdate = [this, &newOrChangedVerts](const VertexHandle vertex) {
@@ -437,21 +450,32 @@ GeoData::setHeights(const std::span<const GlobalPosition3D> triangleStrip, const
std::ranges::copy(vv_range(vertex), std::inserter(newOrChangedVerts, newOrChangedVerts.end()));
};
- // New vertices for each vertex in triangleStrip
std::vector<VertexHandle> newVerts;
+ auto newVertexOnFace = [this, &vertexDistFrom, &opts, &vertexDistFromE, &newVerts, &notBoundary, &notEdgeBoundary](
+ GlobalPosition3D tsPoint) {
+ const auto face = findPoint(tsPoint);
+ // Check vertices
+ if (const auto nearest = std::ranges::min(std::views::iota(fv_begin(face), fv_end(face)) | notBoundary
+ | std::views::transform(vertexDistFrom(tsPoint)),
+ {}, &std::pair<VertexHandle, float>::second);
+ nearest.second < opts.nearNodeTolerance && !std::ranges::contains(newVerts, nearest.first)) {
+ point(nearest.first) = tsPoint;
+ return nearest.first;
+ }
+ // Check edges
+ if (const auto nearest = std::ranges::min(std::views::iota(fh_begin(face), fh_end(face)) | notEdgeBoundary
+ | std::views::transform(vertexDistFromE(tsPoint)),
+ {}, &std::pair<HalfedgeHandle, float>::second);
+ nearest.second < opts.nearNodeTolerance) {
+ return split(edge_handle(nearest.first), tsPoint);
+ }
+ // Nothing close, split face
+ return split(face, tsPoint);
+ };
+
+ // New vertices for each vertex in triangleStrip
newVerts.reserve(newVerts.size());
- std::transform(triangleStrip.begin(), triangleStrip.end(), std::back_inserter(newVerts),
- [this, &newVerts, &vertexDistFrom, &opts](const auto tsPoint) {
- const auto face = findPoint(tsPoint);
- if (const auto nearest = std::ranges::min(std::views::iota(fv_begin(face), fv_end(face))
- | std::views::transform(vertexDistFrom(tsPoint)),
- {}, &std::pair<VertexHandle, float>::second);
- nearest.second < opts.nearNodeTolerance && !std::ranges::contains(newVerts, nearest.first)) {
- point(nearest.first) = tsPoint;
- return nearest.first;
- }
- return split(face, tsPoint);
- });
+ std::transform(triangleStrip.begin(), triangleStrip.end(), std::back_inserter(newVerts), newVertexOnFace);
std::ranges::for_each(newVerts, addVertexForNormalUpdate);
// Create temporary triangles from triangleStrip