From 082b5ea1f16ea468dda2d6eca4038d81e3b1bdb4 Mon Sep 17 00:00:00 2001 From: huxingyi Date: Sat, 11 Apr 2020 16:23:12 +0930 Subject: [PATCH] Fallback to uncombined when component mesh is not combinable [skip ci] --- src/meshcombiner.cpp | 23 +++++------ src/meshcombiner.h | 5 +-- src/meshgenerator.cpp | 94 ++++++++++++++++++++++++++++++------------- src/meshgenerator.h | 13 +++++- 4 files changed, 90 insertions(+), 45 deletions(-) diff --git a/src/meshcombiner.cpp b/src/meshcombiner.cpp index 6b2299ff..e6b4e056 100644 --- a/src/meshcombiner.cpp +++ b/src/meshcombiner.cpp @@ -23,10 +23,11 @@ MeshCombiner::Mesh::Mesh(const std::vector &vertices, const std::vect } else { if (CGAL::Polygon_mesh_processing::triangulate_faces(*cgalMesh)) { if (CGAL::Polygon_mesh_processing::does_self_intersect(*cgalMesh)) { - m_isSelfIntersected = true; qDebug() << "Mesh does_self_intersect"; delete cgalMesh; cgalMesh = nullptr; + } else { + m_isCombinable = true; } } else { qDebug() << "Mesh triangulate failed"; @@ -43,7 +44,7 @@ MeshCombiner::Mesh::Mesh(const std::vector &vertices, const std::vect MeshCombiner::Mesh::Mesh(const Mesh &other) { if (other.m_privateData) { - m_isSelfIntersected = other.m_isSelfIntersected; + m_isCombinable = other.m_isCombinable; m_privateData = new CgalMesh(*(CgalMesh *)other.m_privateData); validate(); } @@ -69,21 +70,16 @@ bool MeshCombiner::Mesh::isNull() const return nullptr == m_privateData; } -bool MeshCombiner::Mesh::isSelfIntersected() const +bool MeshCombiner::Mesh::isCombinable() const { - return m_isSelfIntersected; -} - -void MeshCombiner::Mesh::markAsSelfIntersected() -{ - m_isSelfIntersected = true; + return m_isCombinable; } MeshCombiner::Mesh *MeshCombiner::combine(const Mesh &firstMesh, const Mesh &secondMesh, Method method, std::vector> *combinedVerticesComeFrom) { - if (firstMesh.isNull() || firstMesh.isSelfIntersected() || - secondMesh.isNull() || secondMesh.isSelfIntersected()) + if (firstMesh.isNull() || !firstMesh.isCombinable() || + secondMesh.isNull() || !secondMesh.isCombinable()) return nullptr; CgalMesh *resultCgalMesh = nullptr; @@ -157,9 +153,7 @@ MeshCombiner::Mesh *MeshCombiner::combine(const Mesh &firstMesh, const Mesh &sec Mesh *mesh = new Mesh; mesh->m_privateData = resultCgalMesh; - if (CGAL::Polygon_mesh_processing::does_self_intersect(*resultCgalMesh)) { - mesh->markAsSelfIntersected(); - } + mesh->m_isCombinable = true; return mesh; } @@ -172,5 +166,6 @@ void MeshCombiner::Mesh::validate() if (isNullCgalMesh(exactMesh)) { delete exactMesh; m_privateData = nullptr; + m_isCombinable = false; } } diff --git a/src/meshcombiner.h b/src/meshcombiner.h index 22018e96..a50d7d10 100644 --- a/src/meshcombiner.h +++ b/src/meshcombiner.h @@ -28,14 +28,13 @@ public: ~Mesh(); void fetch(std::vector &vertices, std::vector> &faces) const; bool isNull() const; - bool isSelfIntersected() const; - void markAsSelfIntersected(); + bool isCombinable() const; friend MeshCombiner; private: void *m_privateData = nullptr; - bool m_isSelfIntersected = false; + bool m_isCombinable = false; void validate(); }; diff --git a/src/meshgenerator.cpp b/src/meshgenerator.cpp index e95e767e..6a499e17 100644 --- a/src/meshgenerator.cpp +++ b/src/meshgenerator.cpp @@ -1035,8 +1035,7 @@ MeshCombiner::Mesh *MeshGenerator::combineComponentMesh(const QString &component componentCache.outcomeEdges.clear(); componentCache.outcomeNodeVertices.clear(); componentCache.outcomePaintMaps.clear(); - delete componentCache.mesh; - componentCache.mesh = nullptr; + componentCache.releaseMeshes(); QString linkDataType = valueOfKeyInMapOrEmpty(*component, "linkDataType"); if ("partId" == linkDataType) { @@ -1084,10 +1083,10 @@ MeshCombiner::Mesh *MeshGenerator::combineComponentMesh(const QString &component } auto combineMode = componentCombineMode(child); if (lastCombineMode != combineMode || lastCombineMode == CombineMode::Inversion) { - qDebug() << "New group[" << currentGroupIndex << "] for combine mode[" << CombineModeToString(combineMode) << "]"; combineGroups.push_back({combineMode, {}}); ++currentGroupIndex; lastCombineMode = combineMode; + qDebug() << "New group[" << currentGroupIndex << "] for combine mode[" << CombineModeToString(combineMode) << "]"; } if (-1 == currentGroupIndex) { qDebug() << "Should not happen: -1 == currentGroupIndex"; @@ -1214,9 +1213,19 @@ MeshCombiner::Mesh *MeshGenerator::combineComponentMesh(const QString &component }); } delete mesh; + mesh = nullptr; bool disableSelfIntersectionTest = componentId.isNull() || CombineMode::Uncombined == componentCombineMode(component); - mesh = new MeshCombiner::Mesh(newVertices, newTriangles, disableSelfIntersectionTest); + if (!disableSelfIntersectionTest) { + if (isManifold(newTriangles)) { + mesh = new MeshCombiner::Mesh(newVertices, newTriangles, disableSelfIntersectionTest); + } else { + disableSelfIntersectionTest = true; + mesh = new MeshCombiner::Mesh(newVertices, newTriangles, disableSelfIntersectionTest); + } + } else { + mesh = new MeshCombiner::Mesh(newVertices, newTriangles, disableSelfIntersectionTest); + } if (nullptr != mesh) { if (!disableSelfIntersectionTest) { if (mesh->isNull()) { @@ -1244,12 +1253,14 @@ MeshCombiner::Mesh *MeshGenerator::combineMultipleMeshes(const std::vector(it); const QString &subMeshIdString = std::get<2>(it); //qDebug() << "Combine mode:" << CombineModeToString(childCombineMode); - if (nullptr == subMesh) { + if (nullptr == subMesh || subMesh->isNull()) { + delete subMesh; qDebug() << "Child mesh is null"; continue; } - if (subMesh->isNull()) { + if (!subMesh->isCombinable()) { qDebug() << "Child mesh is uncombinable"; + // TODO: Collect vertices delete subMesh; continue; } @@ -1330,6 +1341,11 @@ MeshCombiner::Mesh *MeshGenerator::combineComponentChildGroupMesh(const std::vec delete subMesh; continue; } + + if (!subMesh->isCombinable()) { + componentCache.incombinableMeshes.push_back(subMesh); + continue; + } multipleMeshes.push_back(std::make_tuple(subMesh, childCombineMode, childIdString)); } @@ -1359,7 +1375,7 @@ MeshCombiner::Mesh *MeshGenerator::combineTwoMeshes(const MeshCombiner::Mesh &fi if (recombiner.recombine()) { if (isManifold(recombiner.regeneratedFaces())) { MeshCombiner::Mesh *reMesh = new MeshCombiner::Mesh(recombiner.regeneratedVertices(), recombiner.regeneratedFaces(), false); - if (!reMesh->isNull() && !reMesh->isSelfIntersected()) { + if (!reMesh->isNull() && reMesh->isCombinable()) { delete newMesh; newMesh = reMesh; } else { @@ -1537,6 +1553,7 @@ void MeshGenerator::generate() // Recursively check uncombined components collectUncombinedComponent(QUuid().toString()); + collectIncombinableComponentMeshes(QUuid().toString()); // Fetch nodes as body nodes before cloth nodes collecting std::set> bodyNodeMap; @@ -1691,6 +1708,48 @@ void MeshGenerator::remesh(const std::vector &inputNodes, } } +void MeshGenerator::collectIncombinableComponentMeshes(const QString &componentIdString) +{ + const auto &componentCache = m_cacheContext->components[componentIdString]; + for (const auto &mesh: componentCache.incombinableMeshes) + collectIncombinableMesh(mesh, componentCache); + const auto &component = findComponent(componentIdString); + for (const auto &childIdString: valueOfKeyInMapOrEmpty(*component, "children").split(",")) { + if (childIdString.isEmpty()) + continue; + collectIncombinableComponentMeshes(childIdString); + } +} + +void MeshGenerator::collectIncombinableMesh(const MeshCombiner::Mesh *mesh, const GeneratedComponent &componentCache) +{ + if (nullptr == mesh) + return; + + m_isSuccessful = false; + + std::vector uncombinedVertices; + std::vector> uncombinedFaces; + mesh->fetch(uncombinedVertices, uncombinedFaces); + std::vector> uncombinedTriangleAndQuads; + + recoverQuads(uncombinedVertices, uncombinedFaces, componentCache.sharedQuadEdges, uncombinedTriangleAndQuads); + + auto vertexStartIndex = m_outcome->vertices.size(); + auto updateVertexIndices = [=](std::vector> &faces) { + for (auto &it: faces) { + for (auto &subIt: it) + subIt += vertexStartIndex; + } + }; + updateVertexIndices(uncombinedFaces); + updateVertexIndices(uncombinedTriangleAndQuads); + + m_outcome->vertices.insert(m_outcome->vertices.end(), uncombinedVertices.begin(), uncombinedVertices.end()); + m_outcome->triangles.insert(m_outcome->triangles.end(), uncombinedFaces.begin(), uncombinedFaces.end()); + m_outcome->triangleAndQuads.insert(m_outcome->triangleAndQuads.end(), uncombinedTriangleAndQuads.begin(), uncombinedTriangleAndQuads.end()); +} + void MeshGenerator::collectUncombinedComponent(const QString &componentIdString) { const auto &component = findComponent(componentIdString); @@ -1708,26 +1767,7 @@ void MeshGenerator::collectUncombinedComponent(const QString &componentIdString) m_outcome->nodeVertices.insert(m_outcome->nodeVertices.end(), componentCache.outcomeNodeVertices.begin(), componentCache.outcomeNodeVertices.end()); m_outcome->paintMaps.insert(m_outcome->paintMaps.end(), componentCache.outcomePaintMaps.begin(), componentCache.outcomePaintMaps.end()); - std::vector uncombinedVertices; - std::vector> uncombinedFaces; - componentCache.mesh->fetch(uncombinedVertices, uncombinedFaces); - std::vector> uncombinedTriangleAndQuads; - - recoverQuads(uncombinedVertices, uncombinedFaces, componentCache.sharedQuadEdges, uncombinedTriangleAndQuads); - - auto vertexStartIndex = m_outcome->vertices.size(); - auto updateVertexIndices = [=](std::vector> &faces) { - for (auto &it: faces) { - for (auto &subIt: it) - subIt += vertexStartIndex; - } - }; - updateVertexIndices(uncombinedFaces); - updateVertexIndices(uncombinedTriangleAndQuads); - - m_outcome->vertices.insert(m_outcome->vertices.end(), uncombinedVertices.begin(), uncombinedVertices.end()); - m_outcome->triangles.insert(m_outcome->triangles.end(), uncombinedFaces.begin(), uncombinedFaces.end()); - m_outcome->triangleAndQuads.insert(m_outcome->triangleAndQuads.end(), uncombinedTriangleAndQuads.begin(), uncombinedTriangleAndQuads.end()); + collectIncombinableMesh(componentCache.mesh, componentCache); return; } for (const auto &childIdString: valueOfKeyInMapOrEmpty(*component, "children").split(",")) { diff --git a/src/meshgenerator.h b/src/meshgenerator.h index 2e72630b..3d53854d 100644 --- a/src/meshgenerator.h +++ b/src/meshgenerator.h @@ -40,9 +40,18 @@ class GeneratedComponent public: ~GeneratedComponent() { - delete mesh; + releaseMeshes(); }; + void releaseMeshes() + { + delete mesh; + mesh = nullptr; + for (auto &it: incombinableMeshes) + delete it; + incombinableMeshes.clear(); + } MeshCombiner::Mesh *mesh = nullptr; + std::vector incombinableMeshes; std::set> sharedQuadEdges; std::set noneSeamVertices; std::vector outcomeNodes; @@ -111,6 +120,8 @@ private: bool m_weldEnabled = true; void collectParts(); + void collectIncombinableComponentMeshes(const QString &componentIdString); + void collectIncombinableMesh(const MeshCombiner::Mesh *mesh, const GeneratedComponent &componentCache); bool checkIsComponentDirty(const QString &componentIdString); bool checkIsPartDirty(const QString &partIdString); bool checkIsPartDependencyDirty(const QString &partIdString);