diff --git a/thirdparty/nodemesh/nodemesh/builder.cpp b/thirdparty/nodemesh/nodemesh/builder.cpp index bc5aed27..1dce9562 100644 --- a/thirdparty/nodemesh/nodemesh/builder.cpp +++ b/thirdparty/nodemesh/nodemesh/builder.cpp @@ -151,6 +151,46 @@ void Builder::resolveBaseNormalForLeavesRecursively(size_t nodeIndex, const QVec } } +void Builder::resolveInitialTraverseDirectionRecursively(size_t nodeIndex, const QVector3D *from, std::set *visited) +{ + if (visited->find(nodeIndex) != visited->end()) + return; + auto &node = m_nodes[nodeIndex]; + node.reversedTraverseOrder = visited->size(); + visited->insert(nodeIndex); + if (nullptr != from) { + node.initialTraverseDirection = (node.position - *from).normalized(); + node.hasInitialTraverseDirection = true; + } + for (size_t i = 0; i < node.edges.size(); ++i) { + size_t neighborIndex = m_edges[node.edges[i]].neiborOf(nodeIndex); + resolveInitialTraverseDirectionRecursively(neighborIndex, &node.position, visited); + } +} + +void Builder::resolveTraverseDirection(size_t nodeIndex) +{ + auto &node = m_nodes[nodeIndex]; + if (!node.hasInitialTraverseDirection) { + if (node.edges.size() > 0) { + size_t neighborIndex = m_edges[node.edges[0]].neiborOf(nodeIndex); + const auto &neighbor = m_nodes[neighborIndex]; + node.initialTraverseDirection = neighbor.initialTraverseDirection; + node.hasInitialTraverseDirection = true; + } + } + if (node.edges.size() == 2) { + std::vector neighborIndices = {m_edges[node.edges[0]].neiborOf(nodeIndex), + m_edges[node.edges[1]].neiborOf(nodeIndex)}; + std::sort(neighborIndices.begin(), neighborIndices.end(), [&](const size_t &firstIndex, const size_t &secondIndex) { + return m_nodes[firstIndex].reversedTraverseOrder < m_nodes[secondIndex].reversedTraverseOrder; + }); + node.traverseDirection = (node.initialTraverseDirection + m_nodes[neighborIndices[1]].initialTraverseDirection).normalized(); + } else { + node.traverseDirection = node.initialTraverseDirection; + } +} + std::pair Builder::searchBaseNormalFromNeighborsRecursively(size_t nodeIndex) { auto &node = m_nodes[nodeIndex]; @@ -198,6 +238,22 @@ bool Builder::build() return true; } + { + std::set visited; + for (auto nodeIndex = m_sortedNodeIndices.rbegin(); + nodeIndex != m_sortedNodeIndices.rend(); + ++nodeIndex) { + resolveInitialTraverseDirectionRecursively(*nodeIndex, nullptr, &visited); + } + } + { + for (auto nodeIndex = m_sortedNodeIndices.rbegin(); + nodeIndex != m_sortedNodeIndices.rend(); + ++nodeIndex) { + resolveTraverseDirection(*nodeIndex); + } + } + for (const auto &nodeIndex: m_sortedNodeIndices) { prepareNode(nodeIndex); } @@ -295,17 +351,17 @@ bool Builder::generateCutsForNode(size_t nodeIndex) size_t neighborsCount = node.edges.size(); //qDebug() << "Generate cuts for node" << nodeIndex << "with neighbor count" << neighborsCount; if (1 == neighborsCount) { - QVector3D cutNormal = node.raysToNeibors[0]; + const QVector3D &cutNormal = node.raysToNeibors[0]; std::vector cut; - makeCut(node.position, node.radius, node.cutTemplate, node.baseNormal, cutNormal, cut); + makeCut(node.position, node.radius, node.cutTemplate, node.baseNormal, cutNormal, node.traverseDirection, cut); std::vector vertices; insertCutVertices(cut, vertices, nodeIndex, cutNormal); m_generatedFaces.push_back(vertices); m_edges[node.edges[0]].cuts.push_back({vertices, -cutNormal}); } else if (2 == neighborsCount) { - QVector3D cutNormal = (node.raysToNeibors[0].normalized() - node.raysToNeibors[1].normalized()) / 2; + 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, cut); + makeCut(node.position, node.radius, node.cutTemplate, node.baseNormal, cutNormal, node.traverseDirection, cut); std::vector vertices; insertCutVertices(cut, vertices, nodeIndex, cutNormal); std::vector verticesReversed; @@ -344,7 +400,7 @@ bool Builder::tryWrapMultipleBranchesForNode(size_t nodeIndex, std::vector, QVector3D>> cutsForEdges; bool directSwallowed = false; for (size_t i = 0; i < node.edges.size(); ++i) { - QVector3D cutNormal = node.raysToNeibors[i]; + const QVector3D &cutNormal = node.raysToNeibors[i]; size_t edgeIndex = node.edges[i]; size_t neighborIndex = m_edges[edgeIndex].neiborOf(nodeIndex); const auto &neighbor = m_nodes[neighborIndex]; @@ -368,7 +424,7 @@ bool Builder::tryWrapMultipleBranchesForNode(size_t nodeIndex, std::vector vertices; insertCutVertices(cut, vertices, nodeIndex, cutNormal); cutsForEdges.push_back({vertices, -cutNormal}); @@ -504,6 +560,7 @@ void Builder::makeCut(const QVector3D &position, const std::vector &cutTemplate, QVector3D &baseNormal, const QVector3D &cutNormal, + const QVector3D &traverseDirection, std::vector &resultCut) { QVector3D orientedBaseNormal = QVector3D::dotProduct(cutNormal, baseNormal) > 0 ? @@ -527,7 +584,7 @@ void Builder::makeCut(const QVector3D &position, if (!qFuzzyIsNull(m_cutRotation)) { float degree = m_cutRotation * 180; QMatrix4x4 rotation; - rotation.rotate(degree, cutNormal); + rotation.rotate(degree, traverseDirection); baseNormal = rotation * baseNormal; for (auto &positionOnCut: resultCut) { positionOnCut = rotation * positionOnCut; diff --git a/thirdparty/nodemesh/nodemesh/builder.h b/thirdparty/nodemesh/nodemesh/builder.h index 112d3356..90b79bab 100644 --- a/thirdparty/nodemesh/nodemesh/builder.h +++ b/thirdparty/nodemesh/nodemesh/builder.h @@ -34,12 +34,16 @@ private: std::vector edges; std::vector cutTemplate; std::vector raysToNeibors; + QVector3D initialTraverseDirection; + QVector3D traverseDirection; QVector3D growthDirection; QVector3D initialBaseNormal; QVector3D baseNormal; + size_t reversedTraverseOrder; bool hasInitialBaseNormal = false; bool baseNormalResolved = false; bool baseNormalSearched = false; + bool hasInitialTraverseDirection = false; size_t anotherEdge(size_t edgeIndex) const { @@ -98,6 +102,8 @@ private: void resolveBaseNormalRecursively(size_t nodeIndex); void resolveBaseNormalForLeavesRecursively(size_t nodeIndex, const QVector3D &baseNormal); std::pair searchBaseNormalFromNeighborsRecursively(size_t nodeIndex); + void resolveInitialTraverseDirectionRecursively(size_t nodeIndex, const QVector3D *from, std::set *visited); + void resolveTraverseDirection(size_t nodeIndex); bool generateCutsForNode(size_t nodeIndex); bool tryWrapMultipleBranchesForNode(size_t nodeIndex, std::vector &offsets, bool &offsetsChanged); void makeCut(const QVector3D &position, @@ -105,6 +111,7 @@ private: const std::vector &cutTemplate, QVector3D &baseNormal, const QVector3D &cutNormal, + const QVector3D &traverseDirection, std::vector &resultCut); void insertCutVertices(const std::vector &cut, std::vector &vertices, size_t nodeIndex, const QVector3D &cutDirect); void stitchEdgeCuts();