diff --git a/dust3d/mesh/mesh_state.cc b/dust3d/mesh/mesh_state.cc index 24e0ec2b..2e77df1a 100644 --- a/dust3d/mesh/mesh_state.cc +++ b/dust3d/mesh/mesh_state.cc @@ -20,6 +20,7 @@ * SOFTWARE. */ +#include #include namespace dust3d { @@ -30,4 +31,58 @@ void MeshState::fetch(std::vector& vertices, std::vectorfetch(vertices, faces); } +std::unique_ptr MeshState::combine(const MeshState& first, const MeshState& second, + MeshCombiner::Method method) +{ + if (first.mesh->isNull() || second.mesh->isNull()) + return nullptr; + std::vector> combinedVerticesSources; + auto newMesh = std::unique_ptr(MeshCombiner::combine(*first.mesh, + *second.mesh, + method, + &combinedVerticesSources)); + if (nullptr == newMesh) + return nullptr; + if (!newMesh->isNull()) { + MeshRecombiner recombiner; + std::vector combinedVertices; + std::vector> combinedFaces; + newMesh->fetch(combinedVertices, combinedFaces); + recombiner.setVertices(&combinedVertices, &combinedVerticesSources); + recombiner.setFaces(&combinedFaces); + if (recombiner.recombine()) { + if (MeshState::isWatertight(recombiner.regeneratedFaces())) { + auto reMesh = std::make_unique(recombiner.regeneratedVertices(), recombiner.regeneratedFaces()); + if (!reMesh->isNull()) { + newMesh = std::move(reMesh); + } + } + } + } + if (newMesh->isNull()) { + return nullptr; + } + auto newMeshState = std::make_unique(); + newMeshState->mesh = std::move(newMesh); + return newMeshState; +} + +bool MeshState::isWatertight(const std::vector>& faces) +{ + std::set> halfEdges; + for (const auto& face : faces) { + for (size_t i = 0; i < face.size(); ++i) { + size_t j = (i + 1) % face.size(); + auto insertResult = halfEdges.insert({ face[i], face[j] }); + if (!insertResult.second) + return false; + } + } + for (const auto& it : halfEdges) { + if (halfEdges.find({ it.second, it.first }) == halfEdges.end()) + return false; + } + return true; +} + } diff --git a/dust3d/mesh/mesh_state.h b/dust3d/mesh/mesh_state.h index ef232ef9..9a43e6a4 100644 --- a/dust3d/mesh/mesh_state.h +++ b/dust3d/mesh/mesh_state.h @@ -35,6 +35,9 @@ public: std::vector, std::array>> seamTriangleUvs; void fetch(std::vector& vertices, std::vector>& faces) const; + static std::unique_ptr combine(const MeshState& first, const MeshState& second, + MeshCombiner::Method method); + static bool isWatertight(const std::vector>& faces); }; }