Fix crash on linux

master
Jeremy Hu 2019-03-08 20:25:24 +09:30
parent 499c3f439a
commit 8f5bbfd758
4 changed files with 62 additions and 18 deletions

View File

@ -4,6 +4,8 @@
#include <CGAL/Surface_mesh.h> #include <CGAL/Surface_mesh.h>
#include <QVector3D> #include <QVector3D>
#include <vector> #include <vector>
#include <cmath>
#include <nodemesh/misc.h>
typedef CGAL::Exact_predicates_exact_constructions_kernel ExactKernel; typedef CGAL::Exact_predicates_exact_constructions_kernel ExactKernel;
typedef CGAL::Surface_mesh<ExactKernel::Point_3> ExactMesh; typedef CGAL::Surface_mesh<ExactKernel::Point_3> ExactMesh;
@ -15,6 +17,16 @@ typename CGAL::Surface_mesh<typename Kernel::Point_3> *buildCgalMesh(const std::
std::map<size_t, typename CGAL::Surface_mesh<typename Kernel::Point_3>::Vertex_index> vertexIndices; std::map<size_t, typename CGAL::Surface_mesh<typename Kernel::Point_3>::Vertex_index> vertexIndices;
for (const auto &face: indices) { for (const auto &face: indices) {
std::vector<typename CGAL::Surface_mesh<typename Kernel::Point_3>::Vertex_index> faceVertexIndices; std::vector<typename CGAL::Surface_mesh<typename Kernel::Point_3>::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) { for (const auto &index: face) {
auto findIndex = vertexIndices.find(index); auto findIndex = vertexIndices.find(index);
if (findIndex != vertexIndices.end()) { if (findIndex != vertexIndices.end()) {

View File

@ -18,34 +18,27 @@ Combiner::Mesh::Mesh(const std::vector<QVector3D> &vertices, const std::vector<s
{ {
ExactMesh *cgalMesh = nullptr; ExactMesh *cgalMesh = nullptr;
if (!faces.empty()) { if (!faces.empty()) {
cgalMesh = buildCgalMesh<ExactKernel>(vertices, faces); std::vector<QVector3D> triangleVertices = vertices;
if (!CGAL::is_valid_polygon_mesh(*cgalMesh)) { std::vector<std::vector<size_t>> triangles;
qDebug() << "Mesh is not valid polygon"; if (nodemesh::triangulate(triangleVertices, faces, triangles)) {
delete cgalMesh; cgalMesh = buildCgalMesh<ExactKernel>(triangleVertices, triangles);
cgalMesh = nullptr; if (!CGAL::is_valid_polygon_mesh(*cgalMesh)) {
} else { qDebug() << "Mesh is not valid polygon";
if (CGAL::Polygon_mesh_processing::triangulate_faces(*cgalMesh)) { delete cgalMesh;
cgalMesh = nullptr;
} else {
if (CGAL::Polygon_mesh_processing::does_self_intersect(*cgalMesh)) { if (CGAL::Polygon_mesh_processing::does_self_intersect(*cgalMesh)) {
//nodemesh::exportMeshAsObj(vertices, triangles, "/Users/jeremy/Desktop/test.obj");
m_isSelfIntersected = true; m_isSelfIntersected = true;
if (removeSelfIntersects) { if (removeSelfIntersects) {
if (!CGAL::Polygon_mesh_processing::remove_self_intersections(*cgalMesh)) { if (!CGAL::Polygon_mesh_processing::remove_self_intersections(*cgalMesh)) {
//qDebug() << "Mesh does self intersect and cann't remove intersections";
delete cgalMesh; delete cgalMesh;
cgalMesh = nullptr; cgalMesh = nullptr;
} else {
//qDebug() << "Mesh does self intersect but intersections got removed";
} }
} else { } else {
delete cgalMesh; delete cgalMesh;
cgalMesh = nullptr; cgalMesh = nullptr;
//qDebug() << "Mesh does self intersect";
} }
} }
} else {
qDebug() << "Mesh triangulate failed";
delete cgalMesh;
cgalMesh = nullptr;
} }
} }
} }

View File

@ -5,6 +5,12 @@
#include <QDebug> #include <QDebug>
#include <unordered_set> #include <unordered_set>
#include <unordered_map> #include <unordered_map>
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Polygon_mesh_processing/triangulate_faces.h>
#include <nodemesh/cgalmesh.h>
typedef CGAL::Exact_predicates_inexact_constructions_kernel InexactKernel;
typedef CGAL::Surface_mesh<InexactKernel::Point_3> InexactMesh;
#ifndef M_PI #ifndef M_PI
#define M_PI 3.14159265358979323846 #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; return r + t <= 1.0;
} }
void nodemesh::triangulate(const std::vector<QVector3D> &vertices, const std::vector<std::vector<size_t>> &faces, std::vector<std::vector<size_t>> &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<QVector3D> &vertices, const std::vector<std::vector<size_t>> &faces, std::vector<std::vector<size_t>> &triangles)
{
auto cgalMesh = buildCgalMesh<InexactKernel>(vertices, faces);
bool isSucceed = CGAL::Polygon_mesh_processing::triangulate_faces(*cgalMesh);
if (isSucceed) {
vertices.clear();
fetchFromCgalMesh<InexactKernel>(cgalMesh, vertices, triangles);
delete cgalMesh;
return true;
}
delete cgalMesh;
// fallback to our own imeplementation
isSucceed = true;
std::vector<std::vector<size_t>> rings; std::vector<std::vector<size_t>> rings;
for (const auto &face: faces) { for (const auto &face: faces) {
if (face.size() > 3) { if (face.size() > 3) {
@ -128,8 +164,10 @@ void nodemesh::triangulate(const std::vector<QVector3D> &vertices, const std::ve
triangles.push_back(newFace); triangles.push_back(newFace);
} else { } else {
qDebug() << "Triangulate failed, ring size:" << fillRing.size(); qDebug() << "Triangulate failed, ring size:" << fillRing.size();
isSucceed = false;
} }
} }
return isSucceed;
} }
void nodemesh::exportMeshAsObj(const std::vector<QVector3D> &vertices, const std::vector<std::vector<size_t>> &faces, const QString &filename, const std::set<size_t> *excludeFacesOfVertices) void nodemesh::exportMeshAsObj(const std::vector<QVector3D> &vertices, const std::vector<std::vector<size_t>> &faces, const QString &filename, const std::set<size_t> *excludeFacesOfVertices)

View File

@ -16,7 +16,7 @@ float degreeBetween(const QVector3D &v1, const QVector3D &v2);
float degreeBetweenIn360(const QVector3D &a, const QVector3D &b, const QVector3D &direct); 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); bool pointInTriangle(const QVector3D &a, const QVector3D &b, const QVector3D &c, const QVector3D &p);
QVector3D polygonNormal(const std::vector<QVector3D> &vertices, const std::vector<size_t> &polygon); QVector3D polygonNormal(const std::vector<QVector3D> &vertices, const std::vector<size_t> &polygon);
void triangulate(const std::vector<QVector3D> &vertices, const std::vector<std::vector<size_t>> &faces, std::vector<std::vector<size_t>> &triangles); bool triangulate(std::vector<QVector3D> &vertices, const std::vector<std::vector<size_t>> &faces, std::vector<std::vector<size_t>> &triangles);
void exportMeshAsObj(const std::vector<QVector3D> &vertices, const std::vector<std::vector<size_t>> &faces, const QString &filename, const std::set<size_t> *excludeFacesOfVertices=nullptr); void exportMeshAsObj(const std::vector<QVector3D> &vertices, const std::vector<std::vector<size_t>> &faces, const QString &filename, const std::set<size_t> *excludeFacesOfVertices=nullptr);
void exportMeshAsObjWithNormals(const std::vector<QVector3D> &vertices, const std::vector<std::vector<size_t>> &faces, const QString &filename, void exportMeshAsObjWithNormals(const std::vector<QVector3D> &vertices, const std::vector<std::vector<size_t>> &faces, const QString &filename,
const std::vector<QVector3D> &triangleVertexNormals); const std::vector<QVector3D> &triangleVertexNormals);
@ -34,6 +34,7 @@ bool isManifold(const std::vector<std::vector<size_t>> &faces);
void trim(std::vector<QVector3D> *vertices, bool normalize=false); void trim(std::vector<QVector3D> *vertices, bool normalize=false);
void subdivideFace2D(std::vector<QVector2D> *face); void subdivideFace2D(std::vector<QVector2D> *face);
void chamferFace2D(std::vector<QVector2D> *face); void chamferFace2D(std::vector<QVector2D> *face);
bool validatePosition(const QVector3D &position);
} }