From 141c7075622460ccb3be463a64f3fd3eb3720e83 Mon Sep 17 00:00:00 2001 From: lisyarus Date: Thu, 9 Jun 2022 11:15:10 +0300 Subject: [PATCH] Add geom::subdivide for subdividing an indexed mesh --- libs/geom/include/psemek/geom/mesh.hpp | 52 ++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/libs/geom/include/psemek/geom/mesh.hpp b/libs/geom/include/psemek/geom/mesh.hpp index 0869abfb..50eec89d 100644 --- a/libs/geom/include/psemek/geom/mesh.hpp +++ b/libs/geom/include/psemek/geom/mesh.hpp @@ -156,4 +156,56 @@ namespace psemek::geom return result; } + template + void subdivide(std::vector & vertices, std::vector> & triangles) + { + using edge = std::pair; + + using scalar = std::decay_t; + + auto normalise = [](edge e) -> edge + { + if (e.first > e.second) + std::swap(e.first, e.second); + return e; + }; + + std::unordered_map midpoints; + + auto add_midpoint = [&](Index i0, Index i1) + { + auto ne = normalise({i0, i1}); + + if (!midpoints.contains(ne)) + { + midpoints[ne] = vertices.size(); + vertices.push_back(lerp(vertices[i0], vertices[i1], scalar{0.5})); + } + }; + + for (auto const & t : triangles) + { + add_midpoint(t[0], t[1]); + add_midpoint(t[1], t[2]); + add_midpoint(t[2], t[0]); + } + + auto get_midpoint = [&](Index i0, Index i1) + { + return midpoints.at(normalise({i0, i1})); + }; + + std::vector> new_triangles; + + for (auto const & t : triangles) + { + new_triangles.push_back({t[0], get_midpoint(t[0], t[1]), get_midpoint(t[2], t[0])}); + new_triangles.push_back({t[1], get_midpoint(t[1], t[2]), get_midpoint(t[0], t[1])}); + new_triangles.push_back({t[2], get_midpoint(t[2], t[0]), get_midpoint(t[1], t[2])}); + new_triangles.push_back({get_midpoint(t[0], t[1]), get_midpoint(t[1], t[2]), get_midpoint(t[2], t[0])}); + } + + triangles.swap(new_triangles); + } + }