Change subdiv stratege: subdiv after union.

master
Jeremy Hu 2018-04-11 14:15:11 +08:00
parent 28a95aedee
commit b95276ec06
6 changed files with 92 additions and 38 deletions

View File

@ -5,11 +5,12 @@
#define MAX_VERTICES_PER_FACE 100 #define MAX_VERTICES_PER_FACE 100
Mesh::Mesh(void *meshlite, int meshId) : Mesh::Mesh(void *meshlite, int meshId, bool broken) :
m_triangleVertices(NULL), m_triangleVertices(NULL),
m_triangleVertexCount(0), m_triangleVertexCount(0),
m_edgeVertices(NULL), m_edgeVertices(NULL),
m_edgeVertexCount(0) m_edgeVertexCount(0),
m_broken(broken)
{ {
int edgeVertexPositionCount = meshlite_get_vertex_count(meshlite, meshId); int edgeVertexPositionCount = meshlite_get_vertex_count(meshlite, meshId);
GLfloat *edgeVertexPositions = new GLfloat[edgeVertexPositionCount * 3]; GLfloat *edgeVertexPositions = new GLfloat[edgeVertexPositionCount * 3];
@ -82,6 +83,11 @@ Mesh::Mesh(void *meshlite, int meshId) :
float modelR = Theme::white.redF(); float modelR = Theme::white.redF();
float modelG = Theme::white.greenF(); float modelG = Theme::white.greenF();
float modelB = Theme::white.blueF(); float modelB = Theme::white.blueF();
if (m_broken) {
modelR = 1.0;
modelG = 1.0;
modelB = 1.0;
}
m_triangleVertexCount = triangleCount * 3; m_triangleVertexCount = triangleCount * 3;
m_triangleVertices = new Vertex[m_triangleVertexCount * 3]; m_triangleVertices = new Vertex[m_triangleVertexCount * 3];
for (int i = 0; i < triangleCount; i++) { for (int i = 0; i < triangleCount; i++) {
@ -119,6 +125,11 @@ Mesh::~Mesh()
m_triangleVertexCount = 0; m_triangleVertexCount = 0;
} }
void Mesh::setBroken(bool broken)
{
m_broken = broken;
}
const std::vector<QVector3D> &Mesh::vertices() const std::vector<QVector3D> &Mesh::vertices()
{ {
return m_vertices; return m_vertices;

View File

@ -24,7 +24,7 @@ typedef struct
class Mesh class Mesh
{ {
public: public:
Mesh(void *meshlite, int meshId); Mesh(void *meshlite, int meshId, bool broken=false);
~Mesh(); ~Mesh();
Vertex *triangleVertices(); Vertex *triangleVertices();
int triangleVertexCount(); int triangleVertexCount();
@ -32,6 +32,7 @@ public:
int edgeVertexCount(); int edgeVertexCount();
const std::vector<QVector3D> &vertices(); const std::vector<QVector3D> &vertices();
const std::vector<std::vector<int>> &faces(); const std::vector<std::vector<int>> &faces();
void setBroken(bool broken);
private: private:
Vertex *m_triangleVertices; Vertex *m_triangleVertices;
int m_triangleVertexCount; int m_triangleVertexCount;
@ -39,6 +40,7 @@ private:
int m_edgeVertexCount; int m_edgeVertexCount;
std::vector<QVector3D> m_vertices; std::vector<QVector3D> m_vertices;
std::vector<std::vector<int>> m_faces; std::vector<std::vector<int>> m_faces;
bool m_broken;
}; };
#endif #endif

View File

@ -8,6 +8,8 @@
#include "meshutil.h" #include "meshutil.h"
#include "theme.h" #include "theme.h"
bool MeshGenerator::enableDebug = false;
MeshGenerator::MeshGenerator(SkeletonSnapshot *snapshot, QThread *thread) : MeshGenerator::MeshGenerator(SkeletonSnapshot *snapshot, QThread *thread) :
m_snapshot(snapshot), m_snapshot(snapshot),
m_mesh(nullptr), m_mesh(nullptr),
@ -75,34 +77,46 @@ QImage *MeshGenerator::takePartPreview(const QString &partId)
void MeshGenerator::resolveBoundingBox(QRectF *mainProfile, QRectF *sideProfile) void MeshGenerator::resolveBoundingBox(QRectF *mainProfile, QRectF *sideProfile)
{ {
float left = -1; float left = 0;
float right = -1; bool leftFirstTime = true;
float top = -1; float right = 0;
float bottom = -1; bool rightFirstTime = true;
float zLeft = -1; float top = 0;
float zRight = -1; 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) { for (const auto &nodeIt: m_snapshot->nodes) {
float radius = valueOfKeyInMapOrEmpty(nodeIt.second, "radius").toFloat(); float radius = valueOfKeyInMapOrEmpty(nodeIt.second, "radius").toFloat();
float x = valueOfKeyInMapOrEmpty(nodeIt.second, "x").toFloat(); float x = valueOfKeyInMapOrEmpty(nodeIt.second, "x").toFloat();
float y = valueOfKeyInMapOrEmpty(nodeIt.second, "y").toFloat(); float y = valueOfKeyInMapOrEmpty(nodeIt.second, "y").toFloat();
float z = valueOfKeyInMapOrEmpty(nodeIt.second, "z").toFloat(); float z = valueOfKeyInMapOrEmpty(nodeIt.second, "z").toFloat();
if (left < 0 || x - radius < left) { if (leftFirstTime || x - radius < left) {
left = x - radius; left = x - radius;
leftFirstTime = false;
} }
if (top < 0 || y - radius < top) { if (topFirstTime || y - radius < top) {
top = y - radius; top = y - radius;
topFirstTime = false;
} }
if (x + radius > right) { if (rightFirstTime > right) {
right = x + radius; right = x + radius;
rightFirstTime = false;
} }
if (y + radius > bottom) { if (bottomFirstTime > bottom) {
bottom = y + radius; bottom = y + radius;
bottomFirstTime = false;
} }
if (zLeft < 0 || z - radius < zLeft) { if (zLeftFirstTime || z - radius < zLeft) {
zLeft = z - radius; zLeft = z - radius;
zLeftFirstTime = false;
} }
if (z + radius > zRight) { if (zRightFirstTime > zRight) {
zRight = z + radius; zRight = z + radius;
zRightFirstTime = false;
} }
} }
*mainProfile = QRectF(left, top, right - left, bottom - top); *mainProfile = QRectF(left, top, right - left, bottom - top);
@ -117,7 +131,6 @@ void MeshGenerator::process()
void *meshliteContext = meshlite_create_context(); void *meshliteContext = meshlite_create_context();
std::map<QString, int> partBmeshMap; std::map<QString, int> partBmeshMap;
std::map<QString, int> bmeshNodeMap; std::map<QString, int> bmeshNodeMap;
bool hasSubdiv = false;
QRectF mainProfile, sideProfile; QRectF mainProfile, sideProfile;
resolveBoundingBox(&mainProfile, &sideProfile); resolveBoundingBox(&mainProfile, &sideProfile);
@ -132,6 +145,8 @@ void MeshGenerator::process()
for (const auto &partIdIt: m_snapshot->partIdList) { for (const auto &partIdIt: m_snapshot->partIdList) {
int bmeshId = meshlite_bmesh_create(meshliteContext); int bmeshId = meshlite_bmesh_create(meshliteContext);
if (MeshGenerator::enableDebug)
meshlite_bmesh_enable_debug(meshliteContext, bmeshId, 1);
partBmeshMap[partIdIt] = bmeshId; partBmeshMap[partIdIt] = bmeshId;
} }
@ -200,39 +215,65 @@ void MeshGenerator::process()
bmeshNodeMap[nodeIt.first] = bmeshNodeId; bmeshNodeMap[nodeIt.first] = bmeshNodeId;
} }
std::map<QString, int> partMeshMap;
std::vector<int> meshIds; std::vector<int> meshIds;
std::vector<int> subdivMeshIds;
for (const auto &partIdIt: m_snapshot->partIdList) { for (const auto &partIdIt: m_snapshot->partIdList) {
const auto part = m_snapshot->parts.find(partIdIt); const auto part = m_snapshot->parts.find(partIdIt);
int bmeshId = partBmeshMap[partIdIt]; int bmeshId = partBmeshMap[partIdIt];
int meshId = meshlite_bmesh_generate_mesh(meshliteContext, bmeshId, 0); int meshId = meshlite_bmesh_generate_mesh(meshliteContext, bmeshId);
if (isTrueValueString(part->second["subdived"])) { bool subdived = isTrueValueString(part->second["subdived"]);
int subdivedMeshId = subdivMesh(meshliteContext, meshId);
if (subdivedMeshId > 0) {
meshId = subdivedMeshId;
hasSubdiv = true;
}
}
if (m_requirePartPreviewMap.find(partIdIt) != m_requirePartPreviewMap.end()) { if (m_requirePartPreviewMap.find(partIdIt) != m_requirePartPreviewMap.end()) {
ModelOfflineRender *render = m_partPreviewRenderMap[partIdIt]; ModelOfflineRender *render = m_partPreviewRenderMap[partIdIt];
int trimedMeshId = meshlite_trim(meshliteContext, meshId, 1); 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)); render->updateMesh(new Mesh(meshliteContext, trimedMeshId));
QImage *image = new QImage(render->toImage(QSize(Theme::previewImageSize, Theme::previewImageSize))); QImage *image = new QImage(render->toImage(QSize(Theme::previewImageSize, Theme::previewImageSize)));
m_partPreviewMap[partIdIt] = image; m_partPreviewMap[partIdIt] = image;
} }
int triangulatedMeshId = meshlite_triangulate(meshliteContext, meshId); if (subdived)
meshIds.push_back(triangulatedMeshId); 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; int mergedMeshId = 0;
if (meshIds.size() > 1) { 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) { } else if (meshIds.size() > 0) {
mergedMeshId = meshIds[0]; mergedMeshId = meshIds[0];
} }
if (mergedMeshId > 0 && !hasSubdiv) {
mergedMeshId = meshlite_combine_coplanar_faces(meshliteContext, mergedMeshId);
}
if (mergedMeshId > 0) { if (mergedMeshId > 0) {
if (m_requirePreview) { if (m_requirePreview) {
@ -241,7 +282,7 @@ void MeshGenerator::process()
m_preview = image; m_preview = image;
} }
int trimedMeshId = meshlite_trim(meshliteContext, mergedMeshId, 1); int trimedMeshId = meshlite_trim(meshliteContext, mergedMeshId, 1);
m_mesh = new Mesh(meshliteContext, trimedMeshId); m_mesh = new Mesh(meshliteContext, trimedMeshId, broken);
} }
if (m_previewRender) { if (m_previewRender) {

View File

@ -37,6 +37,7 @@ private:
QThread *m_thread; QThread *m_thread;
private: private:
void resolveBoundingBox(QRectF *mainProfile, QRectF *sideProfile); void resolveBoundingBox(QRectF *mainProfile, QRectF *sideProfile);
static bool enableDebug;
}; };
#endif #endif

View File

@ -139,7 +139,7 @@ ExactMesh *unionCgalMeshs(ExactMesh *first, ExactMesh *second)
#endif #endif
int unionMeshs(void *meshliteContext, const std::vector<int> &meshIds) int unionMeshs(void *meshliteContext, const std::vector<int> &meshIds, int *errorCount)
{ {
#if USE_CGAL == 1 #if USE_CGAL == 1
CGAL::set_error_behaviour(CGAL::THROW_EXCEPTION); CGAL::set_error_behaviour(CGAL::THROW_EXCEPTION);
@ -158,14 +158,13 @@ int unionMeshs(void *meshliteContext, const std::vector<int> &meshIds)
try { try {
unionedExternalMesh = unionCgalMeshs(mergedExternalMesh, externalMeshs[i]); unionedExternalMesh = unionCgalMeshs(mergedExternalMesh, externalMeshs[i]);
} catch (...) { } catch (...) {
// ignore; if (errorCount)
(*errorCount)++;
} }
delete externalMeshs[i]; delete externalMeshs[i];
if (unionedExternalMesh) { if (unionedExternalMesh) {
delete mergedExternalMesh; delete mergedExternalMesh;
mergedExternalMesh = unionedExternalMesh; mergedExternalMesh = unionedExternalMesh;
} else {
// TOOD:
} }
} }
if (mergedExternalMesh) { if (mergedExternalMesh) {
@ -199,7 +198,7 @@ int subdivMesh(void *meshliteContext, int meshId)
// return makeMeshliteMeshFromCgal<SimpleKernel>(meshliteContext, simpleMesh); // return makeMeshliteMeshFromCgal<SimpleKernel>(meshliteContext, simpleMesh);
//#else //#else
if (0 == meshlite_is_triangulated_manifold(meshliteContext, triangulatedMeshId)) { if (0 == meshlite_is_triangulated_manifold(meshliteContext, triangulatedMeshId)) {
return meshId; return 0;
} }
return meshlite_subdivide(meshliteContext, meshId); return meshlite_subdivide(meshliteContext, meshId);
//#endif //#endif

View File

@ -3,7 +3,7 @@
#include <vector> #include <vector>
int mergeMeshs(void *meshliteContext, const std::vector<int> &meshIds); int mergeMeshs(void *meshliteContext, const std::vector<int> &meshIds);
int unionMeshs(void *meshliteContext, const std::vector<int> &meshIds); int unionMeshs(void *meshliteContext, const std::vector<int> &meshIds, int *errorCount=0);
int subdivMesh(void *meshliteContext, int meshId); int subdivMesh(void *meshliteContext, int meshId);
#endif #endif