diff --git a/thirdparty/nodemesh/nodemesh/builder.cpp b/thirdparty/nodemesh/nodemesh/builder.cpp index fa2f747d..be25414c 100644 --- a/thirdparty/nodemesh/nodemesh/builder.cpp +++ b/thirdparty/nodemesh/nodemesh/builder.cpp @@ -283,7 +283,7 @@ bool Builder::validateNormal(const QVector3D &normal) if (normal.isNull()) { return false; } - if (std::isnan(normal.x()) || std::isnan(normal.y()) || std::isnan(normal.z())) { + if (!validatePosition(normal)) { return false; } return true; @@ -293,6 +293,13 @@ std::pair Builder::calculateBaseNormal(const std::vector &positions, const std::vector &weights) { + auto calculateTwoPointsNormal = [&](size_t i0, size_t i1) -> std::pair { + auto normal = QVector3D::crossProduct(directs[i0], directs[i1]).normalized(); + if (validateNormal(normal)) { + return {normal, true}; + } + return {{}, false}; + }; auto calculateThreePointsNormal = [&](size_t i0, size_t i1, size_t i2) -> std::pair { auto normal = QVector3D::normal(positions[i0], positions[i1], positions[i2]); if (validateNormal(normal)) { @@ -300,14 +307,21 @@ std::pair Builder::calculateBaseNormal(const std::vector=15 degrees && <= 165 degrees if (abs(QVector3D::dotProduct(directs[i0], directs[i1])) < 0.966) { - return {QVector3D::crossProduct(directs[i0], directs[i1]).normalized(), true}; - } else if (abs(QVector3D::dotProduct(directs[i1], directs[i2])) < 0.966) { - return {QVector3D::crossProduct(directs[i1], directs[i2]).normalized(), true}; - } else if (abs(QVector3D::dotProduct(directs[i2], directs[i0])) < 0.966) { - return {QVector3D::crossProduct(directs[i2], directs[i0]).normalized(), true}; - } else { - return {{}, false}; + auto twoPointsResult = calculateTwoPointsNormal(i0, i1); + if (twoPointsResult.second) + return twoPointsResult; } + if (abs(QVector3D::dotProduct(directs[i1], directs[i2])) < 0.966) { + auto twoPointsResult = calculateTwoPointsNormal(i1, i2); + if (twoPointsResult.second) + return twoPointsResult; + } + if (abs(QVector3D::dotProduct(directs[i2], directs[i0])) < 0.966) { + auto twoPointsResult = calculateTwoPointsNormal(i2, i0); + if (twoPointsResult.second) + return twoPointsResult; + } + return {{}, false}; }; if (directs.size() <= 1) { @@ -315,7 +329,9 @@ std::pair Builder::calculateBaseNormal(const std::vector=15 degrees && <= 165 degrees if (abs(QVector3D::dotProduct(directs[0], directs[1])) < 0.966) { - return {QVector3D::crossProduct(directs[0], directs[1]).normalized(), true}; + auto twoPointsResult = calculateTwoPointsNormal(0, 1); + if (twoPointsResult.second) + return twoPointsResult; } return {{}, false}; } else if (directs.size() <= 3) { diff --git a/thirdparty/nodemesh/nodemesh/cgalmesh.h b/thirdparty/nodemesh/nodemesh/cgalmesh.h index b9d4d1cb..5d8d4232 100644 --- a/thirdparty/nodemesh/nodemesh/cgalmesh.h +++ b/thirdparty/nodemesh/nodemesh/cgalmesh.h @@ -6,6 +6,7 @@ #include #include #include +#include typedef CGAL::Exact_predicates_inexact_constructions_kernel CgalKernel; typedef CGAL::Surface_mesh CgalMesh; @@ -14,27 +15,40 @@ template typename CGAL::Surface_mesh *buildCgalMesh(const std::vector &positions, const std::vector> &indices) { typename CGAL::Surface_mesh *mesh = new typename CGAL::Surface_mesh; - std::map::Vertex_index> vertexIndices; + std::map::Vertex_index> vertexIndices; for (const auto &face: indices) { std::vector::Vertex_index> faceVertexIndices; bool faceValid = true; + std::vector positionKeys; + std::vector positionsInKeys; + std::set existedKeys; for (const auto &index: face) { - const auto &pos = positions[index]; - if (!nodemesh::validatePosition(pos)) { + const auto &position = positions[index]; + if (!nodemesh::validatePosition(position)) { faceValid = false; break; } + auto positionKey = nodemesh::PositionKey(position); + if (existedKeys.find(positionKey) != existedKeys.end()) { + continue; + } + existedKeys.insert(positionKey); + positionKeys.push_back(positionKey); + positionsInKeys.push_back(position); } if (!faceValid) continue; - for (const auto &index: face) { - auto findIndex = vertexIndices.find(index); + if (positionKeys.size() < 3) + continue; + for (size_t index = 0; index < positionKeys.size(); ++index) { + const auto &position = positionsInKeys[index]; + const auto &positionKey = positionKeys[index]; + auto findIndex = vertexIndices.find(positionKey); if (findIndex != vertexIndices.end()) { faceVertexIndices.push_back(findIndex->second); } else { - const auto &pos = positions[index]; - auto newIndex = mesh->add_vertex(typename Kernel::Point_3(pos.x(), pos.y(), pos.z())); - vertexIndices.insert({index, newIndex}); + auto newIndex = mesh->add_vertex(typename Kernel::Point_3(position.x(), position.y(), position.z())); + vertexIndices.insert({positionKey, newIndex}); faceVertexIndices.push_back(newIndex); } } diff --git a/thirdparty/nodemesh/nodemesh/combiner.cpp b/thirdparty/nodemesh/nodemesh/combiner.cpp index 59361c48..ced2908f 100644 --- a/thirdparty/nodemesh/nodemesh/combiner.cpp +++ b/thirdparty/nodemesh/nodemesh/combiner.cpp @@ -18,27 +18,31 @@ Combiner::Mesh::Mesh(const std::vector &vertices, const std::vector triangleVertices = vertices; - std::vector> triangles; - if (nodemesh::triangulate(triangleVertices, faces, triangles)) { - cgalMesh = buildCgalMesh(triangleVertices, triangles); - if (!CGAL::is_valid_polygon_mesh(*cgalMesh)) { - qDebug() << "Mesh is not valid polygon"; - delete cgalMesh; - cgalMesh = nullptr; - } else { + cgalMesh = buildCgalMesh(vertices, faces); + if (!CGAL::is_valid_polygon_mesh(*cgalMesh)) { + qDebug() << "Mesh is not valid polygon"; + delete cgalMesh; + cgalMesh = nullptr; + } else { + if (CGAL::Polygon_mesh_processing::triangulate_faces(*cgalMesh)) { if (CGAL::Polygon_mesh_processing::does_self_intersect(*cgalMesh)) { m_isSelfIntersected = true; if (removeSelfIntersects) { if (!CGAL::Polygon_mesh_processing::remove_self_intersections(*cgalMesh)) { + qDebug() << "Mesh remove_self_intersections failed"; delete cgalMesh; cgalMesh = nullptr; } } else { + qDebug() << "Mesh does_self_intersect"; delete cgalMesh; cgalMesh = nullptr; } } + } else { + qDebug() << "Mesh triangulate failed"; + delete cgalMesh; + cgalMesh = nullptr; } } }