diff --git a/resources/model-mosquito.ds3 b/resources/model-mosquito.ds3 index 45787e27..301e3083 100644 --- a/resources/model-mosquito.ds3 +++ b/resources/model-mosquito.ds3 @@ -1,119 +1,117 @@ DUST3D 1.0 xml 0000000193 - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - + + + + + - - - - - + + + + + diff --git a/src/document.cpp b/src/document.cpp index 612eccca..a659850f 100644 --- a/src/document.cpp +++ b/src/document.cpp @@ -1248,10 +1248,13 @@ void Document::addFromSnapshot(const Snapshot &snapshot, bool fromPaste) for (const auto &it: cutFaceLinkedIdModifyMap) { SkeletonPart &part = partMap[it.first]; auto findNewLinkedId = oldNewIdMap.find(it.second); - if (findNewLinkedId == oldNewIdMap.end()) - part.setCutFaceLinkedId(QUuid()); - else + if (oldNewIdMap.find(it.second) == oldNewIdMap.end()) { + if (partMap.find(it.second) == partMap.end()) { + part.setCutFaceLinkedId(QUuid()); + } + } else { part.setCutFaceLinkedId(findNewLinkedId->second); + } } for (const auto &nodeKv: snapshot.nodes) { if (nodeKv.second.find("radius") == nodeKv.second.end() || diff --git a/src/meshgenerator.cpp b/src/meshgenerator.cpp index 9548da91..d53efbe4 100644 --- a/src/meshgenerator.cpp +++ b/src/meshgenerator.cpp @@ -494,8 +494,11 @@ nodemesh::Combiner::Mesh *MeshGenerator::combinePartMesh(const QString &partIdSt } std::vector builderNodeIndices; - for (const auto &node: modifier->nodes()) - builderNodeIndices.push_back(builder->addNode(node.position, node.radius, node.cutTemplate)); + for (const auto &node: modifier->nodes()) { + auto nodeIndex = builder->addNode(node.position, node.radius, node.cutTemplate); + builder->setNodeOriginInfo(nodeIndex, node.nearOriginNodeIndex, node.farOriginNodeIndex); + builderNodeIndices.push_back(nodeIndex); + } for (const auto &edge: modifier->edges()) builder->addEdge(edge.firstNodeIndex, edge.secondNodeIndex); bool buildSucceed = builder->build(); diff --git a/thirdparty/nodemesh/nodemesh/builder.cpp b/thirdparty/nodemesh/nodemesh/builder.cpp index d742b7ee..9e7882b4 100644 --- a/thirdparty/nodemesh/nodemesh/builder.cpp +++ b/thirdparty/nodemesh/nodemesh/builder.cpp @@ -99,6 +99,11 @@ void Builder::prepareNode(size_t nodeIndex) neighborPositions[i] = neighbor.position; neighborRadius[i] = neighbor.radius; } + if (node.edges.size() == 1) { + node.cutNormal = node.raysToNeibors[0]; + } else if (node.edges.size() == 2) { + node.cutNormal = (node.raysToNeibors[0] - node.raysToNeibors[1]) * 0.5; + } auto baseNormalResult = calculateBaseNormal(node.raysToNeibors, neighborPositions, neighborRadius); @@ -108,6 +113,13 @@ void Builder::prepareNode(size_t nodeIndex) node.initialBaseNormal = revisedBaseNormalAcordingToCutNormal(node.initialBaseNormal, node.traverseDirection); } +void Builder::setNodeOriginInfo(size_t nodeIndex, int nearOriginNodeIndex, int farOriginNodeIndex) +{ + auto &node = m_nodes[nodeIndex]; + node.nearOriginNodeIndex = nearOriginNodeIndex; + node.farOriginNodeIndex = farOriginNodeIndex; +} + void Builder::resolveBaseNormalRecursively(size_t nodeIndex) { auto &node = m_nodes[nodeIndex]; @@ -438,7 +450,7 @@ 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) { - const QVector3D &cutNormal = node.raysToNeibors[0]; + QVector3D cutNormal = node.cutNormal; std::vector cut; makeCut(node.position, node.radius, node.cutTemplate, node.baseNormal, cutNormal, node.traverseDirection, cut, &node.cutFaceTransform); node.hasAdjustableCutFace = true; @@ -447,7 +459,23 @@ bool Builder::generateCutsForNode(size_t nodeIndex) m_generatedFaces.push_back(vertices); m_edges[node.edges[0]].cuts.push_back({vertices, -cutNormal}); } else if (2 == neighborsCount) { - const QVector3D cutNormal = (node.raysToNeibors[0].normalized() - node.raysToNeibors[1].normalized()) / 2; + QVector3D cutNormal = node.cutNormal; + if (-1 != node.nearOriginNodeIndex && -1 != node.farOriginNodeIndex) { + const auto &nearOriginNode = m_nodes[node.nearOriginNodeIndex]; + const auto &farOriginNode = m_nodes[node.farOriginNodeIndex]; + if (nearOriginNode.edges.size() <= 2 && farOriginNode.edges.size() <= 2) { + float nearDistance = node.position.distanceToPoint(nearOriginNode.position); + float farDistance = node.position.distanceToPoint(farOriginNode.position); + float totalDistance = nearDistance + farDistance; + float distanceFactor = nearDistance / totalDistance; + if (QVector3D::dotProduct(nearOriginNode.cutNormal, farOriginNode.cutNormal) <= 0) + cutNormal = (nearOriginNode.cutNormal * (1.0 - distanceFactor) - farOriginNode.cutNormal * distanceFactor).normalized(); + else + cutNormal = (nearOriginNode.cutNormal * (1.0 - distanceFactor) + farOriginNode.cutNormal * distanceFactor).normalized(); + if (QVector3D::dotProduct(cutNormal, node.cutNormal) <= 0) + cutNormal = -cutNormal; + } + } std::vector cut; makeCut(node.position, node.radius, node.cutTemplate, node.baseNormal, cutNormal, node.traverseDirection, cut, &node.cutFaceTransform); node.hasAdjustableCutFace = true; @@ -688,26 +716,25 @@ void Builder::makeCut(const QVector3D &position, float radius, const std::vector &cutTemplate, QVector3D &baseNormal, - const QVector3D &cutNormal, + QVector3D &cutNormal, const QVector3D &traverseDirection, std::vector &resultCut, CutFaceTransform *cutFaceTransform) { auto finalCutTemplate = cutTemplate; - auto finalCutNormal = cutNormal; float degree = 0; if (!qFuzzyIsNull(m_cutRotation)) { degree = m_cutRotation * 180; } if (QVector3D::dotProduct(cutNormal, traverseDirection) <= 0) { - finalCutNormal = -finalCutNormal; + cutNormal = -cutNormal; 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(); + QVector3D u = QVector3D::crossProduct(cutNormal, baseNormal).normalized(); + QVector3D v = QVector3D::crossProduct(u, cutNormal).normalized(); auto uFactor = u * radius; auto vFactor = v * radius; if (nullptr != cutFaceTransform) { @@ -721,7 +748,7 @@ void Builder::makeCut(const QVector3D &position, } if (!qFuzzyIsNull(degree)) { QMatrix4x4 rotation; - rotation.rotate(degree, traverseDirection); + rotation.rotate(degree, cutNormal); 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 62cf1e11..a31216a9 100644 --- a/thirdparty/nodemesh/nodemesh/builder.h +++ b/thirdparty/nodemesh/nodemesh/builder.h @@ -25,6 +25,7 @@ public: size_t addNode(const QVector3D &position, float radius, const std::vector &cutTemplate); size_t addEdge(size_t firstNodeIndex, size_t secondNodeIndex); + void setNodeOriginInfo(size_t nodeIndex, int nearOriginNodeIndex, int farOriginNodeIndex); void setDeformThickness(float thickness); void setDeformWidth(float width); void setCutRotation(float cutRotation); @@ -50,6 +51,7 @@ private: std::vector edges; std::vector cutTemplate; std::vector raysToNeibors; + QVector3D cutNormal; CutFaceTransform cutFaceTransform; QVector3D initialTraverseDirection; QVector3D traverseDirection; @@ -62,6 +64,8 @@ private: bool baseNormalSearched = false; bool hasInitialTraverseDirection = false; bool hasAdjustableCutFace = false; + int nearOriginNodeIndex = -1; + int farOriginNodeIndex = -1; size_t anotherEdge(size_t edgeIndex) const { @@ -134,7 +138,7 @@ private: float radius, const std::vector &cutTemplate, QVector3D &baseNormal, - const QVector3D &cutNormal, + QVector3D &cutNormal, const QVector3D &traverseDirection, std::vector &resultCut, CutFaceTransform *cutFaceTransform=nullptr); diff --git a/thirdparty/nodemesh/nodemesh/modifier.cpp b/thirdparty/nodemesh/nodemesh/modifier.cpp index 39758d6e..5d276b6b 100644 --- a/thirdparty/nodemesh/nodemesh/modifier.cpp +++ b/thirdparty/nodemesh/nodemesh/modifier.cpp @@ -117,7 +117,15 @@ void Modifier::finalize() const Node &firstNode = m_nodes[edge.firstNodeIndex]; const Node &secondNode = m_nodes[edge.secondNodeIndex]; createIntermediateNode(firstNode, secondNode, factor, &intermediateNode); - intermediateNode.originNodeIndex = factor <= 0.5 ? firstNode.originNodeIndex : secondNode.originNodeIndex; + if (factor <= 0.5) { + intermediateNode.originNodeIndex = firstNode.originNodeIndex; + intermediateNode.nearOriginNodeIndex = firstNode.originNodeIndex; + intermediateNode.farOriginNodeIndex = secondNode.originNodeIndex; + } else { + intermediateNode.originNodeIndex = secondNode.originNodeIndex; + intermediateNode.nearOriginNodeIndex = secondNode.originNodeIndex; + intermediateNode.farOriginNodeIndex = firstNode.originNodeIndex; + } size_t intermedidateNodeIndex = m_nodes.size(); nodeIndices.push_back(intermedidateNodeIndex); m_nodes.push_back(intermediateNode); diff --git a/thirdparty/nodemesh/nodemesh/modifier.h b/thirdparty/nodemesh/nodemesh/modifier.h index 007e852f..fa589582 100644 --- a/thirdparty/nodemesh/nodemesh/modifier.h +++ b/thirdparty/nodemesh/nodemesh/modifier.h @@ -15,7 +15,9 @@ public: QVector3D position; float radius = 0.0; std::vector cutTemplate; - size_t originNodeIndex = 0; + int nearOriginNodeIndex = -1; + int farOriginNodeIndex = -1; + int originNodeIndex = 0; }; struct Edge