Change subdiv stratege: subdiv after union.
parent
28a95aedee
commit
b95276ec06
15
src/mesh.cpp
15
src/mesh.cpp
|
@ -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;
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue