diff --git a/src/meshgenerator.cpp b/src/meshgenerator.cpp index cc93a74d..44985d63 100644 --- a/src/meshgenerator.cpp +++ b/src/meshgenerator.cpp @@ -27,6 +27,7 @@ MeshGenerator::~MeshGenerator() delete m_resultMesh; delete m_snapshot; delete m_outcome; + delete m_cutFaceTransforms; } bool MeshGenerator::isSucceed() @@ -60,6 +61,13 @@ Outcome *MeshGenerator::takeOutcome() return outcome; } +std::map *MeshGenerator::takeCutFaceTransforms() +{ + auto cutFaceTransforms = m_cutFaceTransforms; + m_cutFaceTransforms = nullptr; + return cutFaceTransforms; +} + void MeshGenerator::collectParts() { for (const auto &node: m_snapshot->nodes) { @@ -465,12 +473,23 @@ nodemesh::Combiner::Mesh *MeshGenerator::combinePartMesh(const QString &partIdSt builder->enableBaseNormalOnY(false); } + std::vector builderNodeIndices; for (const auto &node: modifier->nodes()) - builder->addNode(node.position, node.radius, node.cutTemplate); + builderNodeIndices.push_back(builder->addNode(node.position, node.radius, node.cutTemplate)); for (const auto &edge: modifier->edges()) builder->addEdge(edge.firstNodeIndex, edge.secondNodeIndex); 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) + m_cutFaceTransforms->insert({QUuid(nodeIdString), *cutFaceTransform}); + } + partCache.vertices = builder->generatedVertices(); partCache.faces = builder->generatedFaces(); for (size_t i = 0; i < partCache.vertices.size(); ++i) { @@ -962,6 +981,7 @@ void MeshGenerator::generate() countTimeConsumed.start(); m_outcome = new Outcome; + m_cutFaceTransforms = new std::map; bool needDeleteCacheContext = false; if (nullptr == m_cacheContext) { diff --git a/src/meshgenerator.h b/src/meshgenerator.h index d71a2e60..2e0764a8 100644 --- a/src/meshgenerator.h +++ b/src/meshgenerator.h @@ -5,6 +5,7 @@ #include #include #include +#include #include "outcome.h" #include "snapshot.h" #include "combinemode.h" @@ -59,6 +60,7 @@ public: MeshLoader *takePartPreviewMesh(const QUuid &partId); const std::set &generatedPreviewPartIds(); Outcome *takeOutcome(); + std::map *takeCutFaceTransforms(); void generate(); void setGeneratedCacheContext(GeneratedCacheContext *cacheContext); void setSmoothShadingThresholdAngleDegrees(float degrees); @@ -86,6 +88,7 @@ private: bool m_isSucceed = false; bool m_cacheEnabled = false; float m_smoothShadingThresholdAngleDegrees = 60; + std::map *m_cutFaceTransforms = nullptr; void collectParts(); bool checkIsComponentDirty(const QString &componentIdString); diff --git a/thirdparty/nodemesh/nodemesh/builder.cpp b/thirdparty/nodemesh/nodemesh/builder.cpp index 358ca8a1..ef03bd0e 100644 --- a/thirdparty/nodemesh/nodemesh/builder.cpp +++ b/thirdparty/nodemesh/nodemesh/builder.cpp @@ -417,6 +417,16 @@ void Builder::insertCutVertices(const std::vector &cut, std::vector= m_nodes.size()) + return nullptr; + const auto &node = m_nodes[nodeIndex]; + if (!node.hasAdjustableCutFace) + return nullptr; + return &node.cutFaceTransform; +} + bool Builder::generateCutsForNode(size_t nodeIndex) { if (m_swallowedNodes.find(nodeIndex) != m_swallowedNodes.end()) { @@ -430,7 +440,8 @@ bool Builder::generateCutsForNode(size_t nodeIndex) if (1 == neighborsCount) { const QVector3D &cutNormal = node.raysToNeibors[0]; std::vector cut; - makeCut(node.position, node.radius, node.cutTemplate, node.baseNormal, cutNormal, node.traverseDirection, cut); + makeCut(node.position, node.radius, node.cutTemplate, node.baseNormal, cutNormal, node.traverseDirection, cut, &node.cutFaceTransform); + node.hasAdjustableCutFace = true; std::vector vertices; insertCutVertices(cut, vertices, nodeIndex, cutNormal); m_generatedFaces.push_back(vertices); @@ -438,7 +449,8 @@ bool Builder::generateCutsForNode(size_t nodeIndex) } else if (2 == neighborsCount) { const QVector3D cutNormal = (node.raysToNeibors[0].normalized() - node.raysToNeibors[1].normalized()) / 2; std::vector cut; - makeCut(node.position, node.radius, node.cutTemplate, node.baseNormal, cutNormal, node.traverseDirection, cut); + makeCut(node.position, node.radius, node.cutTemplate, node.baseNormal, cutNormal, node.traverseDirection, cut, &node.cutFaceTransform); + node.hasAdjustableCutFace = true; std::vector vertices; insertCutVertices(cut, vertices, nodeIndex, cutNormal); std::vector verticesReversed; @@ -678,7 +690,8 @@ void Builder::makeCut(const QVector3D &position, QVector3D &baseNormal, const QVector3D &cutNormal, const QVector3D &traverseDirection, - std::vector &resultCut) + std::vector &resultCut, + CutFaceTransform *cutFaceTransform) { auto finalCutTemplate = cutTemplate; auto finalCutNormal = cutNormal; @@ -690,11 +703,17 @@ void Builder::makeCut(const QVector3D &position, finalCutNormal = -finalCutNormal; std::reverse(finalCutTemplate.begin(), finalCutTemplate.end()); std::rotate(finalCutTemplate.begin(), finalCutTemplate.begin() + finalCutTemplate.size() - 1, finalCutTemplate.end()); + if (nullptr != cutFaceTransform) + cutFaceTransform->reverse = true; } QVector3D u = QVector3D::crossProduct(finalCutNormal, baseNormal).normalized(); QVector3D v = QVector3D::crossProduct(u, finalCutNormal).normalized(); auto uFactor = u * radius; auto vFactor = v * radius; + if (nullptr != cutFaceTransform) { + cutFaceTransform->uFactor = uFactor; + cutFaceTransform->vFactor = vFactor; + } for (const auto &t: finalCutTemplate) { resultCut.push_back(uFactor * t.x() + vFactor * t.y()); } @@ -705,6 +724,8 @@ void Builder::makeCut(const QVector3D &position, for (auto &positionOnCut: resultCut) { positionOnCut = rotation * positionOnCut; } + if (nullptr != cutFaceTransform) + cutFaceTransform->rotation = rotation; } for (auto &positionOnCut: resultCut) { positionOnCut += position; diff --git a/thirdparty/nodemesh/nodemesh/builder.h b/thirdparty/nodemesh/nodemesh/builder.h index f228d5d8..746595d2 100644 --- a/thirdparty/nodemesh/nodemesh/builder.h +++ b/thirdparty/nodemesh/nodemesh/builder.h @@ -5,6 +5,7 @@ #include #include #include +#include namespace nodemesh { @@ -12,6 +13,14 @@ namespace nodemesh class Builder { public: + struct CutFaceTransform + { + QMatrix4x4 rotation; + QVector3D uFactor; + QVector3D vFactor; + bool reverse = false; + }; + size_t addNode(const QVector3D &position, float radius, const std::vector &cutTemplate); size_t addEdge(size_t firstNodeIndex, size_t secondNodeIndex); void setDeformThickness(float thickness); @@ -26,6 +35,7 @@ public: const std::vector &generatedVerticesSourceNodeIndices(); void exportAsObj(const QString &filename); bool build(); + const CutFaceTransform *nodeAdjustableCutFaceTransform(size_t nodeIndex); private: @@ -38,6 +48,7 @@ private: std::vector edges; std::vector cutTemplate; std::vector raysToNeibors; + CutFaceTransform cutFaceTransform; QVector3D initialTraverseDirection; QVector3D traverseDirection; QVector3D growthDirection; @@ -48,6 +59,7 @@ private: bool baseNormalResolved = false; bool baseNormalSearched = false; bool hasInitialTraverseDirection = false; + bool hasAdjustableCutFace = false; size_t anotherEdge(size_t edgeIndex) const { @@ -122,7 +134,8 @@ private: QVector3D &baseNormal, const QVector3D &cutNormal, const QVector3D &traverseDirection, - std::vector &resultCut); + std::vector &resultCut, + CutFaceTransform *cutFaceTransform=nullptr); void insertCutVertices(const std::vector &cut, std::vector &vertices, size_t nodeIndex, const QVector3D &cutDirect); void stitchEdgeCuts(); void applyWeld(); diff --git a/thirdparty/nodemesh/nodemesh/modifier.cpp b/thirdparty/nodemesh/nodemesh/modifier.cpp index 75f4cf9d..39758d6e 100644 --- a/thirdparty/nodemesh/nodemesh/modifier.cpp +++ b/thirdparty/nodemesh/nodemesh/modifier.cpp @@ -11,6 +11,7 @@ size_t Modifier::addNode(const QVector3D &position, float radius, const std::vec size_t nodeIndex = m_nodes.size(); Node node; + node.isOriginal = true; node.position = position; node.radius = radius; node.cutTemplate = cutTemplate; diff --git a/thirdparty/nodemesh/nodemesh/modifier.h b/thirdparty/nodemesh/nodemesh/modifier.h index 31e124a4..007e852f 100644 --- a/thirdparty/nodemesh/nodemesh/modifier.h +++ b/thirdparty/nodemesh/nodemesh/modifier.h @@ -11,10 +11,11 @@ class Modifier public: struct Node { + bool isOriginal = false; QVector3D position; - float radius; + float radius = 0.0; std::vector cutTemplate; - size_t originNodeIndex; + size_t originNodeIndex = 0; }; struct Edge