From 0f411d3bd9b2074fc025cec2cf0b6d4929ba5e47 Mon Sep 17 00:00:00 2001 From: Jeremy Hu Date: Sat, 27 Jul 2019 14:12:07 +0930 Subject: [PATCH] Fix inconsistent base normal when shape is too straight --- thirdparty/nodemesh/nodemesh/builder.cpp | 47 +++++++++++++++--------- thirdparty/nodemesh/nodemesh/builder.h | 1 + 2 files changed, 31 insertions(+), 17 deletions(-) diff --git a/thirdparty/nodemesh/nodemesh/builder.cpp b/thirdparty/nodemesh/nodemesh/builder.cpp index 3bd7c32b..7710438f 100644 --- a/thirdparty/nodemesh/nodemesh/builder.cpp +++ b/thirdparty/nodemesh/nodemesh/builder.cpp @@ -121,6 +121,33 @@ void Builder::setNodeOriginInfo(size_t nodeIndex, int nearOriginNodeIndex, int f node.farOriginNodeIndex = farOriginNodeIndex; } +QVector3D Builder::calculateBaseNormalFromTraverseDirection(const QVector3D &traverseDirection) +{ + const std::vector axisList = { + QVector3D {1, 0, 0}, + QVector3D {0, 1, 0}, + QVector3D {0, 0, 1}, + }; + float maxDot = -1; + size_t nearAxisIndex = 0; + bool reversed = false; + for (size_t i = 0; i < axisList.size(); ++i) { + const auto axis = axisList[i]; + auto dot = QVector3D::dotProduct(axis, traverseDirection); + auto positiveDot = abs(dot); + if (positiveDot >= maxDot) { + reversed = dot < 0; + maxDot = positiveDot; + nearAxisIndex = i; + } + } + // axisList[nearAxisIndex] align with the traverse direction, + // So we pick the next axis to do cross product with traverse direction + const auto& choosenAxis = axisList[(nearAxisIndex + 1) % 3]; + auto baseNormal = QVector3D::crossProduct(traverseDirection, choosenAxis).normalized(); + return reversed ? -baseNormal : baseNormal; +} + void Builder::resolveBaseNormalRecursively(size_t nodeIndex) { auto &node = m_nodes[nodeIndex]; @@ -135,18 +162,8 @@ void Builder::resolveBaseNormalRecursively(size_t nodeIndex) if (searchResult.second) { resolveBaseNormalForLeavesRecursively(nodeIndex, searchResult.first); } else { - const std::vector axisList = { - QVector3D {0, 0, 1}, - QVector3D {0, 1, 0}, - QVector3D {1, 0, 0} - }; - for (const auto &axis: axisList) { - if (validateNormal(QVector3D::crossProduct(axis, node.traverseDirection).normalized())) { - resolveBaseNormalForLeavesRecursively(nodeIndex, axis); - return; - } - } - resolveBaseNormalForLeavesRecursively(nodeIndex, axisList[0]); + resolveBaseNormalForLeavesRecursively(nodeIndex, + calculateBaseNormalFromTraverseDirection(node.traverseDirection)); } } } @@ -746,11 +763,7 @@ QVector3D Builder::revisedBaseNormalAcordingToCutNormal(const QVector3D &baseNor baseNormal : -baseNormal; // 0.966: < 15 degress if (QVector3D::dotProduct(cutNormal, orientedBaseNormal) > 0.966) { - if (QVector3D::dotProduct(cutNormal, QVector3D(1, 0, 0)) > 0.966) { - orientedBaseNormal = QVector3D(0, 1, 0); - } else { - orientedBaseNormal = QVector3D(1, 0, 0); - } + orientedBaseNormal = calculateBaseNormalFromTraverseDirection(cutNormal); } return orientedBaseNormal.normalized(); } diff --git a/thirdparty/nodemesh/nodemesh/builder.h b/thirdparty/nodemesh/nodemesh/builder.h index de281550..73eb7643 100644 --- a/thirdparty/nodemesh/nodemesh/builder.h +++ b/thirdparty/nodemesh/nodemesh/builder.h @@ -150,6 +150,7 @@ private: void applyDeform(); QVector3D calculateDeformPosition(const QVector3D &vertexPosition, const QVector3D &ray, const QVector3D &deformNormal, float deformFactor); bool swallowEdgeForNode(size_t nodeIndex, size_t edgeOrder); + static QVector3D calculateBaseNormalFromTraverseDirection(const QVector3D &traverseDirection); }; }