diff --git a/src/mesh.cpp b/src/mesh.cpp index 8367d520..55309453 100644 --- a/src/mesh.cpp +++ b/src/mesh.cpp @@ -5,11 +5,12 @@ #define MAX_VERTICES_PER_FACE 100 -Mesh::Mesh(void *meshlite, int meshId) : +Mesh::Mesh(void *meshlite, int meshId, bool broken) : m_triangleVertices(NULL), m_triangleVertexCount(0), m_edgeVertices(NULL), - m_edgeVertexCount(0) + m_edgeVertexCount(0), + m_broken(broken) { int edgeVertexPositionCount = meshlite_get_vertex_count(meshlite, meshId); GLfloat *edgeVertexPositions = new GLfloat[edgeVertexPositionCount * 3]; @@ -82,6 +83,11 @@ Mesh::Mesh(void *meshlite, int meshId) : float modelR = Theme::white.redF(); float modelG = Theme::white.greenF(); float modelB = Theme::white.blueF(); + if (m_broken) { + modelR = 1.0; + modelG = 1.0; + modelB = 1.0; + } m_triangleVertexCount = triangleCount * 3; m_triangleVertices = new Vertex[m_triangleVertexCount * 3]; for (int i = 0; i < triangleCount; i++) { @@ -119,6 +125,11 @@ Mesh::~Mesh() m_triangleVertexCount = 0; } +void Mesh::setBroken(bool broken) +{ + m_broken = broken; +} + const std::vector &Mesh::vertices() { return m_vertices; diff --git a/src/mesh.h b/src/mesh.h index fb3a64a6..d8ce90d3 100644 --- a/src/mesh.h +++ b/src/mesh.h @@ -24,7 +24,7 @@ typedef struct class Mesh { public: - Mesh(void *meshlite, int meshId); + Mesh(void *meshlite, int meshId, bool broken=false); ~Mesh(); Vertex *triangleVertices(); int triangleVertexCount(); @@ -32,6 +32,7 @@ public: int edgeVertexCount(); const std::vector &vertices(); const std::vector> &faces(); + void setBroken(bool broken); private: Vertex *m_triangleVertices; int m_triangleVertexCount; @@ -39,6 +40,7 @@ private: int m_edgeVertexCount; std::vector m_vertices; std::vector> m_faces; + bool m_broken; }; #endif diff --git a/src/meshgenerator.cpp b/src/meshgenerator.cpp index bf0b4b0c..e47bef76 100644 --- a/src/meshgenerator.cpp +++ b/src/meshgenerator.cpp @@ -8,6 +8,8 @@ #include "meshutil.h" #include "theme.h" +bool MeshGenerator::enableDebug = false; + MeshGenerator::MeshGenerator(SkeletonSnapshot *snapshot, QThread *thread) : m_snapshot(snapshot), m_mesh(nullptr), @@ -75,34 +77,46 @@ QImage *MeshGenerator::takePartPreview(const QString &partId) void MeshGenerator::resolveBoundingBox(QRectF *mainProfile, QRectF *sideProfile) { - float left = -1; - float right = -1; - float top = -1; - float bottom = -1; - float zLeft = -1; - float zRight = -1; + float left = 0; + bool leftFirstTime = true; + float right = 0; + bool rightFirstTime = true; + float top = 0; + bool topFirstTime = true; + float bottom = 0; + bool bottomFirstTime = true; + float zLeft = 0; + bool zLeftFirstTime = true; + float zRight = 0; + bool zRightFirstTime = true; for (const auto &nodeIt: m_snapshot->nodes) { float radius = valueOfKeyInMapOrEmpty(nodeIt.second, "radius").toFloat(); float x = valueOfKeyInMapOrEmpty(nodeIt.second, "x").toFloat(); float y = valueOfKeyInMapOrEmpty(nodeIt.second, "y").toFloat(); float z = valueOfKeyInMapOrEmpty(nodeIt.second, "z").toFloat(); - if (left < 0 || x - radius < left) { + if (leftFirstTime || x - radius < left) { left = x - radius; + leftFirstTime = false; } - if (top < 0 || y - radius < top) { + if (topFirstTime || y - radius < top) { top = y - radius; + topFirstTime = false; } - if (x + radius > right) { + if (rightFirstTime > right) { right = x + radius; + rightFirstTime = false; } - if (y + radius > bottom) { + if (bottomFirstTime > bottom) { bottom = y + radius; + bottomFirstTime = false; } - if (zLeft < 0 || z - radius < zLeft) { + if (zLeftFirstTime || z - radius < zLeft) { zLeft = z - radius; + zLeftFirstTime = false; } - if (z + radius > zRight) { + if (zRightFirstTime > zRight) { zRight = z + radius; + zRightFirstTime = false; } } *mainProfile = QRectF(left, top, right - left, bottom - top); @@ -117,7 +131,6 @@ void MeshGenerator::process() void *meshliteContext = meshlite_create_context(); std::map partBmeshMap; std::map bmeshNodeMap; - bool hasSubdiv = false; QRectF mainProfile, sideProfile; resolveBoundingBox(&mainProfile, &sideProfile); @@ -132,6 +145,8 @@ void MeshGenerator::process() for (const auto &partIdIt: m_snapshot->partIdList) { int bmeshId = meshlite_bmesh_create(meshliteContext); + if (MeshGenerator::enableDebug) + meshlite_bmesh_enable_debug(meshliteContext, bmeshId, 1); partBmeshMap[partIdIt] = bmeshId; } @@ -200,39 +215,65 @@ void MeshGenerator::process() bmeshNodeMap[nodeIt.first] = bmeshNodeId; } - std::map partMeshMap; std::vector meshIds; + std::vector subdivMeshIds; for (const auto &partIdIt: m_snapshot->partIdList) { const auto part = m_snapshot->parts.find(partIdIt); int bmeshId = partBmeshMap[partIdIt]; - int meshId = meshlite_bmesh_generate_mesh(meshliteContext, bmeshId, 0); - if (isTrueValueString(part->second["subdived"])) { - int subdivedMeshId = subdivMesh(meshliteContext, meshId); - if (subdivedMeshId > 0) { - meshId = subdivedMeshId; - hasSubdiv = true; - } - } + int meshId = meshlite_bmesh_generate_mesh(meshliteContext, bmeshId); + bool subdived = isTrueValueString(part->second["subdived"]); if (m_requirePartPreviewMap.find(partIdIt) != m_requirePartPreviewMap.end()) { ModelOfflineRender *render = m_partPreviewRenderMap[partIdIt]; int trimedMeshId = meshlite_trim(meshliteContext, meshId, 1); + if (subdived) { + int subdivedMeshId = subdivMesh(meshliteContext, trimedMeshId); + if (subdivedMeshId > 0) { + trimedMeshId = subdivedMeshId; + } + } render->updateMesh(new Mesh(meshliteContext, trimedMeshId)); QImage *image = new QImage(render->toImage(QSize(Theme::previewImageSize, Theme::previewImageSize))); m_partPreviewMap[partIdIt] = image; } - int triangulatedMeshId = meshlite_triangulate(meshliteContext, meshId); - meshIds.push_back(triangulatedMeshId); + if (subdived) + subdivMeshIds.push_back(meshId); + else + meshIds.push_back(meshId); + } + + bool broken = false; + if (!subdivMeshIds.empty()) { + int mergedMeshId = 0; + int errorCount = 0; + mergedMeshId = unionMeshs(meshliteContext, subdivMeshIds, &errorCount); + if (errorCount) + broken = true; + else if (mergedMeshId > 0) + mergedMeshId = meshlite_combine_coplanar_faces(meshliteContext, mergedMeshId); + if (mergedMeshId > 0) { + int subdivedMeshId = subdivMesh(meshliteContext, mergedMeshId); + if (subdivedMeshId > 0) + mergedMeshId = subdivedMeshId; + else + broken = true; + } + if (mergedMeshId > 0) + meshIds.push_back(mergedMeshId); + else + broken = true; } int mergedMeshId = 0; if (meshIds.size() > 1) { - mergedMeshId = unionMeshs(meshliteContext, meshIds); + int errorCount = 0; + mergedMeshId = unionMeshs(meshliteContext, meshIds, &errorCount); + if (errorCount) + broken = true; + else if (mergedMeshId > 0) + mergedMeshId = meshlite_combine_coplanar_faces(meshliteContext, mergedMeshId); } else if (meshIds.size() > 0) { mergedMeshId = meshIds[0]; } - if (mergedMeshId > 0 && !hasSubdiv) { - mergedMeshId = meshlite_combine_coplanar_faces(meshliteContext, mergedMeshId); - } if (mergedMeshId > 0) { if (m_requirePreview) { @@ -241,7 +282,7 @@ void MeshGenerator::process() m_preview = image; } int trimedMeshId = meshlite_trim(meshliteContext, mergedMeshId, 1); - m_mesh = new Mesh(meshliteContext, trimedMeshId); + m_mesh = new Mesh(meshliteContext, trimedMeshId, broken); } if (m_previewRender) { diff --git a/src/meshgenerator.h b/src/meshgenerator.h index 42f9a8e5..0699c019 100644 --- a/src/meshgenerator.h +++ b/src/meshgenerator.h @@ -37,6 +37,7 @@ private: QThread *m_thread; private: void resolveBoundingBox(QRectF *mainProfile, QRectF *sideProfile); + static bool enableDebug; }; #endif diff --git a/src/meshutil.cpp b/src/meshutil.cpp index 72f5ba04..7cfd4458 100644 --- a/src/meshutil.cpp +++ b/src/meshutil.cpp @@ -139,7 +139,7 @@ ExactMesh *unionCgalMeshs(ExactMesh *first, ExactMesh *second) #endif -int unionMeshs(void *meshliteContext, const std::vector &meshIds) +int unionMeshs(void *meshliteContext, const std::vector &meshIds, int *errorCount) { #if USE_CGAL == 1 CGAL::set_error_behaviour(CGAL::THROW_EXCEPTION); @@ -158,14 +158,13 @@ int unionMeshs(void *meshliteContext, const std::vector &meshIds) try { unionedExternalMesh = unionCgalMeshs(mergedExternalMesh, externalMeshs[i]); } catch (...) { - // ignore; + if (errorCount) + (*errorCount)++; } delete externalMeshs[i]; if (unionedExternalMesh) { delete mergedExternalMesh; mergedExternalMesh = unionedExternalMesh; - } else { - // TOOD: } } if (mergedExternalMesh) { @@ -199,7 +198,7 @@ int subdivMesh(void *meshliteContext, int meshId) // return makeMeshliteMeshFromCgal(meshliteContext, simpleMesh); //#else if (0 == meshlite_is_triangulated_manifold(meshliteContext, triangulatedMeshId)) { - return meshId; + return 0; } return meshlite_subdivide(meshliteContext, meshId); //#endif diff --git a/src/meshutil.h b/src/meshutil.h index f4ef67ee..a2cfcd46 100644 --- a/src/meshutil.h +++ b/src/meshutil.h @@ -3,7 +3,7 @@ #include int mergeMeshs(void *meshliteContext, const std::vector &meshIds); -int unionMeshs(void *meshliteContext, const std::vector &meshIds); +int unionMeshs(void *meshliteContext, const std::vector &meshIds, int *errorCount=0); int subdivMesh(void *meshliteContext, int meshId); #endif