diff --git a/thirdparty/nodemesh/nodemesh/cgalmesh.h b/thirdparty/nodemesh/nodemesh/cgalmesh.h index fad9b8f2..d876bcc7 100644 --- a/thirdparty/nodemesh/nodemesh/cgalmesh.h +++ b/thirdparty/nodemesh/nodemesh/cgalmesh.h @@ -4,6 +4,8 @@ #include #include #include +#include +#include typedef CGAL::Exact_predicates_exact_constructions_kernel ExactKernel; typedef CGAL::Surface_mesh ExactMesh; @@ -15,6 +17,16 @@ typename CGAL::Surface_mesh *buildCgalMesh(const std:: std::map::Vertex_index> vertexIndices; for (const auto &face: indices) { std::vector::Vertex_index> faceVertexIndices; + bool faceValid = true; + for (const auto &index: face) { + const auto &pos = positions[index]; + if (!nodemesh::validatePosition(pos)) { + faceValid = false; + break; + } + } + if (!faceValid) + continue; for (const auto &index: face) { auto findIndex = vertexIndices.find(index); if (findIndex != vertexIndices.end()) { diff --git a/thirdparty/nodemesh/nodemesh/combiner.cpp b/thirdparty/nodemesh/nodemesh/combiner.cpp index 7b70a5e8..d2350c8c 100644 --- a/thirdparty/nodemesh/nodemesh/combiner.cpp +++ b/thirdparty/nodemesh/nodemesh/combiner.cpp @@ -18,34 +18,27 @@ Combiner::Mesh::Mesh(const std::vector &vertices, const std::vector(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)) { + 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 { if (CGAL::Polygon_mesh_processing::does_self_intersect(*cgalMesh)) { - //nodemesh::exportMeshAsObj(vertices, triangles, "/Users/jeremy/Desktop/test.obj"); m_isSelfIntersected = true; if (removeSelfIntersects) { if (!CGAL::Polygon_mesh_processing::remove_self_intersections(*cgalMesh)) { - //qDebug() << "Mesh does self intersect and cann't remove intersections"; delete cgalMesh; cgalMesh = nullptr; - } else { - //qDebug() << "Mesh does self intersect but intersections got removed"; } } else { delete cgalMesh; cgalMesh = nullptr; - //qDebug() << "Mesh does self intersect"; } } - } else { - qDebug() << "Mesh triangulate failed"; - delete cgalMesh; - cgalMesh = nullptr; } } } diff --git a/thirdparty/nodemesh/nodemesh/misc.cpp b/thirdparty/nodemesh/nodemesh/misc.cpp index 2d54ca29..f5ebc3bc 100644 --- a/thirdparty/nodemesh/nodemesh/misc.cpp +++ b/thirdparty/nodemesh/nodemesh/misc.cpp @@ -5,6 +5,12 @@ #include #include #include +#include +#include +#include + +typedef CGAL::Exact_predicates_inexact_constructions_kernel InexactKernel; +typedef CGAL::Surface_mesh InexactMesh; #ifndef M_PI #define M_PI 3.14159265358979323846 @@ -72,8 +78,38 @@ bool nodemesh::pointInTriangle(const QVector3D &a, const QVector3D &b, const QVe return r + t <= 1.0; } -void nodemesh::triangulate(const std::vector &vertices, const std::vector> &faces, std::vector> &triangles) +bool nodemesh::validatePosition(const QVector3D &position) { + if (std::isnan(position.x())) + return false; + if (std::isnan(position.y())) + return false; + if (std::isnan(position.z())) + return false; + if (std::isinf(position.x())) + return false; + if (std::isinf(position.y())) + return false; + if (std::isinf(position.z())) + return false; + return true; +} + +bool nodemesh::triangulate(std::vector &vertices, const std::vector> &faces, std::vector> &triangles) +{ + auto cgalMesh = buildCgalMesh(vertices, faces); + bool isSucceed = CGAL::Polygon_mesh_processing::triangulate_faces(*cgalMesh); + if (isSucceed) { + vertices.clear(); + fetchFromCgalMesh(cgalMesh, vertices, triangles); + delete cgalMesh; + return true; + } + delete cgalMesh; + + // fallback to our own imeplementation + + isSucceed = true; std::vector> rings; for (const auto &face: faces) { if (face.size() > 3) { @@ -128,8 +164,10 @@ void nodemesh::triangulate(const std::vector &vertices, const std::ve triangles.push_back(newFace); } else { qDebug() << "Triangulate failed, ring size:" << fillRing.size(); + isSucceed = false; } } + return isSucceed; } void nodemesh::exportMeshAsObj(const std::vector &vertices, const std::vector> &faces, const QString &filename, const std::set *excludeFacesOfVertices) diff --git a/thirdparty/nodemesh/nodemesh/misc.h b/thirdparty/nodemesh/nodemesh/misc.h index 8f76f1e6..0bcbc022 100644 --- a/thirdparty/nodemesh/nodemesh/misc.h +++ b/thirdparty/nodemesh/nodemesh/misc.h @@ -16,7 +16,7 @@ float degreeBetween(const QVector3D &v1, const QVector3D &v2); float degreeBetweenIn360(const QVector3D &a, const QVector3D &b, const QVector3D &direct); bool pointInTriangle(const QVector3D &a, const QVector3D &b, const QVector3D &c, const QVector3D &p); QVector3D polygonNormal(const std::vector &vertices, const std::vector &polygon); -void triangulate(const std::vector &vertices, const std::vector> &faces, std::vector> &triangles); +bool triangulate(std::vector &vertices, const std::vector> &faces, std::vector> &triangles); void exportMeshAsObj(const std::vector &vertices, const std::vector> &faces, const QString &filename, const std::set *excludeFacesOfVertices=nullptr); void exportMeshAsObjWithNormals(const std::vector &vertices, const std::vector> &faces, const QString &filename, const std::vector &triangleVertexNormals); @@ -34,6 +34,7 @@ bool isManifold(const std::vector> &faces); void trim(std::vector *vertices, bool normalize=false); void subdivideFace2D(std::vector *face); void chamferFace2D(std::vector *face); +bool validatePosition(const QVector3D &position); }