Improve intermediate nodes generation

Added Intermediates nodes sometimes will make the whole part’s mesh failed to generate. This commit add a fallback option, when mesh failed to generate, the generator will try again without the intermediate nodes added.

This feature is inspired from Nico J. Dolloso’s model (https://twitter.com/nicodoll).
master
Jeremy Hu 2019-07-20 12:12:24 +09:30
parent 6cd42da44e
commit aec5acd793
5 changed files with 29 additions and 18 deletions

View File

@ -33,3 +33,4 @@ Satish Goda <https://github.com/SatishGodaPearl>
Sawm Fawk <https://twitter.com/sawmfawk> Sawm Fawk <https://twitter.com/sawmfawk>
Erlend Sogge Heggen <https://twitter.com/erlend_sh> Erlend Sogge Heggen <https://twitter.com/erlend_sh>
Michael Nowak <https://dust3d.discourse.group/u/mcnnowak> Michael Nowak <https://dust3d.discourse.group/u/mcnnowak>
Nico J. Dolloso <https://twitter.com/nicodoll>

View File

@ -323,7 +323,7 @@ void MeshGenerator::cutFaceStringToCutTemplate(const QString &cutFaceString, std
} }
} }
nodemesh::Combiner::Mesh *MeshGenerator::combinePartMesh(const QString &partIdString) nodemesh::Combiner::Mesh *MeshGenerator::combinePartMesh(const QString &partIdString, bool *hasError, bool addIntermediateNodes)
{ {
auto findPart = m_snapshot->parts.find(partIdString); auto findPart = m_snapshot->parts.find(partIdString);
if (findPart == m_snapshot->parts.end()) { if (findPart == m_snapshot->parts.end()) {
@ -467,6 +467,9 @@ nodemesh::Combiner::Mesh *MeshGenerator::combinePartMesh(const QString &partIdSt
nodemesh::Modifier *modifier = new nodemesh::Modifier; nodemesh::Modifier *modifier = new nodemesh::Modifier;
if (addIntermediateNodes)
modifier->enableIntermediateAddition();
QString mirroredPartIdString; QString mirroredPartIdString;
QUuid mirroredPartId; QUuid mirroredPartId;
if (xMirrored) { if (xMirrored) {
@ -561,20 +564,6 @@ nodemesh::Combiner::Mesh *MeshGenerator::combinePartMesh(const QString &partIdSt
builder->addEdge(edge.firstNodeIndex, edge.secondNodeIndex); builder->addEdge(edge.firstNodeIndex, edge.secondNodeIndex);
bool buildSucceed = builder->build(); bool buildSucceed = builder->build();
//for (size_t i = 0; i < modifier->nodes().size(); ++i) {
// const auto &node = modifier->nodes()[i];
// if (!node.isOriginal)
// continue;
// const QString &nodeIdString = nodeIndexToIdStringMap[node.originNodeIndex];
// const nodemesh::Builder::CutFaceTransform *cutFaceTransform = builder->nodeAdjustableCutFaceTransform(builderNodeIndices[i]);
// if (nullptr != cutFaceTransform &&
// PartTarget::Model == target) {
// QUuid nodeId = QUuid(nodeIdString);
// m_cutFaceTransforms->insert({nodeId, *cutFaceTransform});
// m_nodesCutFaces->insert({nodeId, cutTemplateMapByName});
// }
//}
partCache.vertices = builder->generatedVertices(); partCache.vertices = builder->generatedVertices();
partCache.faces = builder->generatedFaces(); partCache.faces = builder->generatedFaces();
for (size_t i = 0; i < partCache.vertices.size(); ++i) { for (size_t i = 0; i < partCache.vertices.size(); ++i) {
@ -633,6 +622,7 @@ nodemesh::Combiner::Mesh *MeshGenerator::combinePartMesh(const QString &partIdSt
qDebug() << "Mesh build failed"; qDebug() << "Mesh build failed";
} }
delete m_partPreviewMeshes[partId];
m_partPreviewMeshes[partId] = nullptr; m_partPreviewMeshes[partId] = nullptr;
m_generatedPreviewPartIds.insert(partId); m_generatedPreviewPartIds.insert(partId);
@ -695,7 +685,8 @@ nodemesh::Combiner::Mesh *MeshGenerator::combinePartMesh(const QString &partIdSt
} }
if (hasMeshError && target == PartTarget::Model) { if (hasMeshError && target == PartTarget::Model) {
m_isSucceed = false; *hasError = true;
//m_isSucceed = false;
} }
return mesh; return mesh;
@ -789,7 +780,17 @@ nodemesh::Combiner::Mesh *MeshGenerator::combineComponentMesh(const QString &com
QString linkDataType = valueOfKeyInMapOrEmpty(*component, "linkDataType"); QString linkDataType = valueOfKeyInMapOrEmpty(*component, "linkDataType");
if ("partId" == linkDataType) { if ("partId" == linkDataType) {
QString partIdString = valueOfKeyInMapOrEmpty(*component, "linkData"); QString partIdString = valueOfKeyInMapOrEmpty(*component, "linkData");
mesh = combinePartMesh(partIdString); bool hasError = false;
mesh = combinePartMesh(partIdString, &hasError);
if (hasError) {
delete mesh;
hasError = false;
qDebug() << "Try combine part again without adding intermediate nodes";
mesh = combinePartMesh(partIdString, &hasError, false);
if (hasError) {
m_isSucceed = false;
}
}
const auto &partCache = m_cacheContext->parts[partIdString]; const auto &partCache = m_cacheContext->parts[partIdString];
for (const auto &vertex: partCache.vertices) for (const auto &vertex: partCache.vertices)

View File

@ -100,7 +100,7 @@ private:
bool checkIsPartDirty(const QString &partIdString); bool checkIsPartDirty(const QString &partIdString);
bool checkIsPartDependencyDirty(const QString &partIdString); bool checkIsPartDependencyDirty(const QString &partIdString);
void checkDirtyFlags(); void checkDirtyFlags();
nodemesh::Combiner::Mesh *combinePartMesh(const QString &partIdString); nodemesh::Combiner::Mesh *combinePartMesh(const QString &partIdString, bool *hasError, bool addIntermediateNodes=true);
nodemesh::Combiner::Mesh *combineComponentMesh(const QString &componentIdString, CombineMode *combineMode); nodemesh::Combiner::Mesh *combineComponentMesh(const QString &componentIdString, CombineMode *combineMode);
void makeXmirror(const std::vector<QVector3D> &sourceVertices, const std::vector<std::vector<size_t>> &sourceFaces, void makeXmirror(const std::vector<QVector3D> &sourceVertices, const std::vector<std::vector<size_t>> &sourceFaces,
std::vector<QVector3D> *destVertices, std::vector<std::vector<size_t>> *destFaces); std::vector<QVector3D> *destVertices, std::vector<std::vector<size_t>> *destFaces);

View File

@ -6,6 +6,11 @@
namespace nodemesh namespace nodemesh
{ {
void Modifier::enableIntermediateAddition()
{
m_intermediateAdditionEnabled = true;
}
size_t Modifier::addNode(const QVector3D &position, float radius, const std::vector<QVector2D> &cutTemplate, float cutRotation) size_t Modifier::addNode(const QVector3D &position, float radius, const std::vector<QVector2D> &cutTemplate, float cutRotation)
{ {
size_t nodeIndex = m_nodes.size(); size_t nodeIndex = m_nodes.size();
@ -100,6 +105,8 @@ void Modifier::roundEnd()
void Modifier::finalize() void Modifier::finalize()
{ {
if (!m_intermediateAdditionEnabled)
return;
auto oldEdges = m_edges; auto oldEdges = m_edges;
m_edges.clear(); m_edges.clear();
for (const auto &edge: oldEdges) { for (const auto &edge: oldEdges) {

View File

@ -31,6 +31,7 @@ public:
size_t addEdge(size_t firstNodeIndex, size_t secondNodeIndex); size_t addEdge(size_t firstNodeIndex, size_t secondNodeIndex);
void subdivide(); void subdivide();
void roundEnd(); void roundEnd();
void enableIntermediateAddition();
const std::vector<Node> &nodes(); const std::vector<Node> &nodes();
const std::vector<Edge> &edges(); const std::vector<Edge> &edges();
void finalize(); void finalize();
@ -39,6 +40,7 @@ private:
std::vector<Node> m_nodes; std::vector<Node> m_nodes;
std::vector<Edge> m_edges; std::vector<Edge> m_edges;
bool m_intermediateAdditionEnabled = false;
void createIntermediateNode(const Node &firstNode, const Node &secondNode, float factor, Node *resultNode); void createIntermediateNode(const Node &firstNode, const Node &secondNode, float factor, Node *resultNode);
float averageCutTemplateEdgeLength(const std::vector<QVector2D> &cutTemplate); float averageCutTemplateEdgeLength(const std::vector<QVector2D> &cutTemplate);