From 1fa1e0e19985b529eda6580262201043eb9984ac Mon Sep 17 00:00:00 2001 From: Jeremy HU Date: Tue, 1 Nov 2022 20:53:02 +1100 Subject: [PATCH] Use MeshState in MeshGenerator --- dust3d/mesh/mesh_generator.cc | 98 ++++++++--------------------------- dust3d/mesh/mesh_generator.h | 25 ++++----- dust3d/mesh/mesh_state.cc | 34 +++++++++++- dust3d/mesh/mesh_state.h | 4 ++ 4 files changed, 69 insertions(+), 92 deletions(-) diff --git a/dust3d/mesh/mesh_generator.cc b/dust3d/mesh/mesh_generator.cc index 7de066d3..19bad801 100644 --- a/dust3d/mesh/mesh_generator.cc +++ b/dust3d/mesh/mesh_generator.cc @@ -103,24 +103,6 @@ void MeshGenerator::subdivideFace(std::vector* face) } } -bool MeshGenerator::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; -} - void MeshGenerator::recoverQuads(const std::vector& vertices, const std::vector>& triangles, const std::set>& sharedQuadEdges, std::vector>& triangleAndQuads) { std::vector verticesPositionKeys; @@ -439,7 +421,7 @@ bool MeshGenerator::fetchPartOrderedNodes(const std::string& partIdString, std:: builderNodeIdStringToIndexMap.insert({ nodeIdString, builderNodes.size() }); builderNodes.emplace_back(MeshNode { - Vector3((double)x, (double)y, (double)z), (double)radius }); + Vector3((double)x, (double)y, (double)z), (double)radius, Uuid(nodeIdString) }); } if (builderNodes.empty()) { @@ -480,7 +462,7 @@ bool MeshGenerator::fetchPartOrderedNodes(const std::string& partIdString, std:: return true; } -std::unique_ptr MeshGenerator::combineStitchingMesh(const std::vector& partIdStrings, +std::unique_ptr MeshGenerator::combineStitchingMesh(const std::vector& partIdStrings, const std::vector& componentIdStrings, GeneratedComponent& componentCache) { @@ -511,7 +493,7 @@ std::unique_ptr MeshGenerator::combineStitchingMesh(const st stitchMeshBuilder->generatedFaces(), &componentCache.sharedQuadEdges); - auto mesh = std::make_unique(stitchMeshBuilder->generatedVertices(), + auto mesh = std::make_unique(stitchMeshBuilder->generatedVertices(), stitchMeshBuilder->generatedFaces()); if (mesh && mesh->isNull()) mesh.reset(); @@ -563,7 +545,7 @@ std::unique_ptr MeshGenerator::combineStitchingMesh(const st return mesh; } -std::unique_ptr MeshGenerator::combinePartMesh(const std::string& partIdString, +std::unique_ptr MeshGenerator::combinePartMesh(const std::string& partIdString, const std::string& componentIdString, bool* hasError) { @@ -704,9 +686,9 @@ std::unique_ptr MeshGenerator::combinePartMesh(const std::st } bool hasMeshError = false; - std::unique_ptr mesh; + std::unique_ptr mesh; - mesh = std::make_unique(partCache.vertices, partCache.faces); + mesh = std::make_unique(partCache.vertices, partCache.faces); if (mesh->isNull()) { hasMeshError = true; } @@ -800,9 +782,9 @@ std::string MeshGenerator::componentColorName(const std::map MeshGenerator::combineComponentMesh(const std::string& componentIdString, CombineMode* combineMode) +std::unique_ptr MeshGenerator::combineComponentMesh(const std::string& componentIdString, CombineMode* combineMode) { - std::unique_ptr mesh; + std::unique_ptr mesh; Uuid componentId; const std::map* component = &m_snapshot->rootComponent; @@ -822,7 +804,7 @@ std::unique_ptr MeshGenerator::combineComponentMesh(const st if (m_cacheEnabled) { if (m_dirtyComponentIds.find(componentIdString) == m_dirtyComponentIds.end()) { if (nullptr != componentCache.mesh) - return std::make_unique(*componentCache.mesh); + return std::make_unique(*componentCache.mesh); } } @@ -887,7 +869,7 @@ std::unique_ptr MeshGenerator::combineComponentMesh(const st } combineGroups[currentGroupIndex].second.push_back(childIdString); } - std::vector, CombineMode, std::string>> groupMeshes; + std::vector, CombineMode, std::string>> groupMeshes; for (const auto& group : combineGroups) { auto childMesh = combineComponentChildGroupMesh(group.second, componentCache); if (nullptr == childMesh || childMesh->isNull()) @@ -908,7 +890,7 @@ std::unique_ptr MeshGenerator::combineComponentMesh(const st } if (nullptr != mesh) - componentCache.mesh = std::make_unique(*mesh); + componentCache.mesh = std::make_unique(*mesh); if (nullptr != mesh && mesh->isNull()) { mesh.reset(); @@ -917,9 +899,9 @@ std::unique_ptr MeshGenerator::combineComponentMesh(const st return mesh; } -std::unique_ptr MeshGenerator::combineMultipleMeshes(std::vector, CombineMode, std::string>>&& multipleMeshes) +std::unique_ptr MeshGenerator::combineMultipleMeshes(std::vector, CombineMode, std::string>>&& multipleMeshes) { - std::unique_ptr mesh; + std::unique_ptr mesh; std::string meshIdStrings; for (auto& it : multipleMeshes) { auto subMesh = std::move(std::get<0>(it)); @@ -936,20 +918,20 @@ std::unique_ptr MeshGenerator::combineMultipleMeshes(std::ve auto combinerMethod = childCombineMode == CombineMode::Inversion ? MeshCombiner::Method::Diff : MeshCombiner::Method::Union; auto combinerMethodString = combinerMethod == MeshCombiner::Method::Union ? "+" : "-"; meshIdStrings += combinerMethodString + subMeshIdString; - std::unique_ptr newMesh; + std::unique_ptr newMesh; auto findCached = m_cacheContext->cachedCombination.find(meshIdStrings); if (findCached != m_cacheContext->cachedCombination.end()) { - if (nullptr != findCached->second.mesh) { - newMesh = std::make_unique(*findCached->second.mesh); + if (nullptr != findCached->second) { + newMesh = std::make_unique(*findCached->second); } } else { - newMesh = combineTwoMeshes(*mesh, + newMesh = MeshState::combine(*mesh, *subMesh, combinerMethod); if (nullptr != newMesh) - m_cacheContext->cachedCombination.insert({ meshIdStrings, GeneratedCombination { std::make_unique(*newMesh) } }); + m_cacheContext->cachedCombination.insert({ meshIdStrings, std::make_unique(*newMesh) }); else - m_cacheContext->cachedCombination.insert({ meshIdStrings, GeneratedCombination {} }); + m_cacheContext->cachedCombination.insert({ meshIdStrings, nullptr }); } if (newMesh && !newMesh->isNull()) { mesh = std::move(newMesh); @@ -963,12 +945,12 @@ std::unique_ptr MeshGenerator::combineMultipleMeshes(std::ve return mesh; } -std::unique_ptr MeshGenerator::combineComponentChildGroupMesh(const std::vector& componentIdStrings, GeneratedComponent& componentCache) +std::unique_ptr MeshGenerator::combineComponentChildGroupMesh(const std::vector& componentIdStrings, GeneratedComponent& componentCache) { - std::vector, CombineMode, std::string>> multipleMeshes; + std::vector, CombineMode, std::string>> multipleMeshes; for (const auto& childIdString : componentIdStrings) { CombineMode childCombineMode = CombineMode::Normal; - std::unique_ptr subMesh = combineComponentMesh(childIdString, &childCombineMode); + std::unique_ptr subMesh = combineComponentMesh(childIdString, &childCombineMode); if (CombineMode::Uncombined == childCombineMode) { continue; @@ -999,40 +981,6 @@ std::unique_ptr MeshGenerator::combineComponentChildGroupMes return combineMultipleMeshes(std::move(multipleMeshes)); } -std::unique_ptr MeshGenerator::combineTwoMeshes(const MeshCombiner::Mesh& first, const MeshCombiner::Mesh& second, - MeshCombiner::Method method) -{ - if (first.isNull() || second.isNull()) - return nullptr; - std::vector> combinedVerticesSources; - auto newMesh = std::unique_ptr(MeshCombiner::combine(first, - second, - 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 (isWatertight(recombiner.regeneratedFaces())) { - auto reMesh = std::make_unique(recombiner.regeneratedVertices(), recombiner.regeneratedFaces()); - if (!reMesh->isNull()) { - newMesh = std::move(reMesh); - } - } - } - } - if (newMesh->isNull()) { - return nullptr; - } - return newMesh; -} - void MeshGenerator::makeXmirror(const std::vector& sourceVertices, const std::vector>& sourceFaces, std::vector* destVertices, std::vector>* destFaces) { @@ -1135,7 +1083,7 @@ void MeshGenerator::postprocessObject(Object* object) object->setTriangleVertexNormals(triangleVertexNormals); } -void MeshGenerator::collectIncombinableMesh(const MeshCombiner::Mesh* mesh, const GeneratedComponent& componentCache) +void MeshGenerator::collectIncombinableMesh(const MeshState* mesh, const GeneratedComponent& componentCache) { if (nullptr == mesh) return; diff --git a/dust3d/mesh/mesh_generator.h b/dust3d/mesh/mesh_generator.h index 9967f027..1f87e8ef 100644 --- a/dust3d/mesh/mesh_generator.h +++ b/dust3d/mesh/mesh_generator.h @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -70,7 +71,7 @@ public: }; struct GeneratedComponent { - std::unique_ptr mesh; + std::unique_ptr mesh; std::set> sharedQuadEdges; std::unordered_map, std::array>> partTriangleUvs; std::vector, std::array>> seamTriangleUvs; @@ -91,16 +92,11 @@ public: } }; - struct GeneratedCombination { - std::unique_ptr mesh; - std::vector, std::array>> seamTriangleUvs; - }; - struct GeneratedCacheContext { std::map components; std::map parts; std::map partMirrorIdMap; - std::map cachedCombination; + std::map> cachedCombination; }; struct ComponentPreview { @@ -151,27 +147,25 @@ private: bool m_weldEnabled = true; void collectParts(); - void collectIncombinableMesh(const MeshCombiner::Mesh* mesh, const GeneratedComponent& componentCache); + void collectIncombinableMesh(const MeshState* mesh, const GeneratedComponent& componentCache); bool checkIsComponentDirty(const std::string& componentIdString); bool checkIsPartDirty(const std::string& partIdString); bool checkIsPartDependencyDirty(const std::string& partIdString); void checkDirtyFlags(); - std::unique_ptr combinePartMesh(const std::string& partIdString, + std::unique_ptr combinePartMesh(const std::string& partIdString, const std::string& componentIdString, bool* hasError); - std::unique_ptr combineComponentMesh(const std::string& componentIdString, CombineMode* combineMode); + std::unique_ptr combineComponentMesh(const std::string& componentIdString, CombineMode* combineMode); void makeXmirror(const std::vector& sourceVertices, const std::vector>& sourceFaces, std::vector* destVertices, std::vector>* destFaces); void collectSharedQuadEdges(const std::vector& vertices, const std::vector>& faces, std::set>* sharedQuadEdges); - std::unique_ptr combineTwoMeshes(const MeshCombiner::Mesh& first, const MeshCombiner::Mesh& second, - MeshCombiner::Method method); const std::map* findComponent(const std::string& componentIdString); CombineMode componentCombineMode(const std::map* component); - std::unique_ptr combineComponentChildGroupMesh(const std::vector& componentIdStrings, + std::unique_ptr combineComponentChildGroupMesh(const std::vector& componentIdStrings, GeneratedComponent& componentCache); - std::unique_ptr combineMultipleMeshes(std::vector, CombineMode, std::string>>&& multipleMeshes); - std::unique_ptr combineStitchingMesh(const std::vector& partIdStrings, + std::unique_ptr combineMultipleMeshes(std::vector, CombineMode, std::string>>&& multipleMeshes); + std::unique_ptr combineStitchingMesh(const std::vector& partIdStrings, const std::vector& componentIdStrings, GeneratedComponent& componentCache); std::string componentColorName(const std::map* component); @@ -187,7 +181,6 @@ private: static void chamferFace(std::vector* face); static void subdivideFace(std::vector* face); - static bool isWatertight(const std::vector>& faces); static void flattenLinks(const std::unordered_map& links, std::vector* array, bool* isCircle); diff --git a/dust3d/mesh/mesh_state.cc b/dust3d/mesh/mesh_state.cc index 2e77df1a..df184404 100644 --- a/dust3d/mesh/mesh_state.cc +++ b/dust3d/mesh/mesh_state.cc @@ -25,17 +25,37 @@ namespace dust3d { +MeshState::MeshState(const std::vector& vertices, const std::vector>& faces) +{ + mesh = std::make_unique(vertices, faces); +} + +MeshState::MeshState(const MeshState& other) +{ + if (nullptr != other.mesh) + mesh = std::make_unique(*other.mesh); + seamTriangleUvs = other.seamTriangleUvs; +} + void MeshState::fetch(std::vector& vertices, std::vector>& faces) const { if (mesh) mesh->fetch(vertices, faces); } +bool MeshState::isNull() const +{ + if (nullptr == mesh) + return true; + return mesh->isNull(); +} + std::unique_ptr MeshState::combine(const MeshState& first, const MeshState& second, MeshCombiner::Method method) { if (first.mesh->isNull() || second.mesh->isNull()) return nullptr; + auto newMeshState = std::make_unique(); std::vector> combinedVerticesSources; auto newMesh = std::unique_ptr(MeshCombiner::combine(*first.mesh, *second.mesh, @@ -54,6 +74,19 @@ std::unique_ptr MeshState::combine(const MeshState& first, const Mesh if (MeshState::isWatertight(recombiner.regeneratedFaces())) { auto reMesh = std::make_unique(recombiner.regeneratedVertices(), recombiner.regeneratedFaces()); if (!reMesh->isNull()) { + for (const auto& uvSeams : recombiner.generatedBridgingTriangleUvs()) { + std::map, std::array> uvs; + for (const auto& it : uvSeams) { + uvs.insert(std::make_pair(std::array { + PositionKey(it.first[0]), + PositionKey(it.first[1]), + PositionKey(it.first[2]) }, + it.second)); + } + if (uvs.empty()) + continue; + newMeshState->seamTriangleUvs.push_back(uvs); + } newMesh = std::move(reMesh); } } @@ -62,7 +95,6 @@ std::unique_ptr MeshState::combine(const MeshState& first, const Mesh if (newMesh->isNull()) { return nullptr; } - auto newMeshState = std::make_unique(); newMeshState->mesh = std::move(newMesh); return newMeshState; } diff --git a/dust3d/mesh/mesh_state.h b/dust3d/mesh/mesh_state.h index 9a43e6a4..71365018 100644 --- a/dust3d/mesh/mesh_state.h +++ b/dust3d/mesh/mesh_state.h @@ -34,7 +34,11 @@ public: std::unique_ptr mesh; std::vector, std::array>> seamTriangleUvs; + MeshState() = default; + MeshState(const std::vector& vertices, const std::vector>& faces); + MeshState(const MeshState& other); void fetch(std::vector& vertices, std::vector>& faces) const; + bool isNull() const; static std::unique_ptr combine(const MeshState& first, const MeshState& second, MeshCombiner::Method method); static bool isWatertight(const std::vector>& faces);