Fix cut rotation

master
Jeremy Hu 2019-02-23 00:03:04 +09:30
parent d866e0147b
commit b2fdb7f4e8
2 changed files with 71 additions and 7 deletions

View File

@ -151,6 +151,46 @@ void Builder::resolveBaseNormalForLeavesRecursively(size_t nodeIndex, const QVec
} }
} }
void Builder::resolveInitialTraverseDirectionRecursively(size_t nodeIndex, const QVector3D *from, std::set<size_t> *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<size_t> 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<QVector3D, bool> Builder::searchBaseNormalFromNeighborsRecursively(size_t nodeIndex) std::pair<QVector3D, bool> Builder::searchBaseNormalFromNeighborsRecursively(size_t nodeIndex)
{ {
auto &node = m_nodes[nodeIndex]; auto &node = m_nodes[nodeIndex];
@ -198,6 +238,22 @@ bool Builder::build()
return true; return true;
} }
{
std::set<size_t> 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) { for (const auto &nodeIndex: m_sortedNodeIndices) {
prepareNode(nodeIndex); prepareNode(nodeIndex);
} }
@ -295,17 +351,17 @@ bool Builder::generateCutsForNode(size_t nodeIndex)
size_t neighborsCount = node.edges.size(); size_t neighborsCount = node.edges.size();
//qDebug() << "Generate cuts for node" << nodeIndex << "with neighbor count" << neighborsCount; //qDebug() << "Generate cuts for node" << nodeIndex << "with neighbor count" << neighborsCount;
if (1 == neighborsCount) { if (1 == neighborsCount) {
QVector3D cutNormal = node.raysToNeibors[0]; const QVector3D &cutNormal = node.raysToNeibors[0];
std::vector<QVector3D> cut; std::vector<QVector3D> 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<size_t> vertices; std::vector<size_t> vertices;
insertCutVertices(cut, vertices, nodeIndex, cutNormal); insertCutVertices(cut, vertices, nodeIndex, cutNormal);
m_generatedFaces.push_back(vertices); m_generatedFaces.push_back(vertices);
m_edges[node.edges[0]].cuts.push_back({vertices, -cutNormal}); m_edges[node.edges[0]].cuts.push_back({vertices, -cutNormal});
} else if (2 == neighborsCount) { } 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<QVector3D> cut; std::vector<QVector3D> 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<size_t> vertices; std::vector<size_t> vertices;
insertCutVertices(cut, vertices, nodeIndex, cutNormal); insertCutVertices(cut, vertices, nodeIndex, cutNormal);
std::vector<size_t> verticesReversed; std::vector<size_t> verticesReversed;
@ -344,7 +400,7 @@ bool Builder::tryWrapMultipleBranchesForNode(size_t nodeIndex, std::vector<float
std::vector<std::pair<std::vector<size_t>, QVector3D>> cutsForEdges; std::vector<std::pair<std::vector<size_t>, QVector3D>> cutsForEdges;
bool directSwallowed = false; bool directSwallowed = false;
for (size_t i = 0; i < node.edges.size(); ++i) { 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 edgeIndex = node.edges[i];
size_t neighborIndex = m_edges[edgeIndex].neiborOf(nodeIndex); size_t neighborIndex = m_edges[edgeIndex].neiborOf(nodeIndex);
const auto &neighbor = m_nodes[neighborIndex]; const auto &neighbor = m_nodes[neighborIndex];
@ -368,7 +424,7 @@ bool Builder::tryWrapMultipleBranchesForNode(size_t nodeIndex, std::vector<float
continue; continue;
} }
} }
makeCut(node.position + cutNormal * finalDistance, radius, node.cutTemplate, node.baseNormal, cutNormal, cut); makeCut(node.position + cutNormal * finalDistance, radius, node.cutTemplate, node.baseNormal, cutNormal, neighbor.traverseDirection, cut);
std::vector<size_t> vertices; std::vector<size_t> vertices;
insertCutVertices(cut, vertices, nodeIndex, cutNormal); insertCutVertices(cut, vertices, nodeIndex, cutNormal);
cutsForEdges.push_back({vertices, -cutNormal}); cutsForEdges.push_back({vertices, -cutNormal});
@ -504,6 +560,7 @@ void Builder::makeCut(const QVector3D &position,
const std::vector<QVector2D> &cutTemplate, const std::vector<QVector2D> &cutTemplate,
QVector3D &baseNormal, QVector3D &baseNormal,
const QVector3D &cutNormal, const QVector3D &cutNormal,
const QVector3D &traverseDirection,
std::vector<QVector3D> &resultCut) std::vector<QVector3D> &resultCut)
{ {
QVector3D orientedBaseNormal = QVector3D::dotProduct(cutNormal, baseNormal) > 0 ? QVector3D orientedBaseNormal = QVector3D::dotProduct(cutNormal, baseNormal) > 0 ?
@ -527,7 +584,7 @@ void Builder::makeCut(const QVector3D &position,
if (!qFuzzyIsNull(m_cutRotation)) { if (!qFuzzyIsNull(m_cutRotation)) {
float degree = m_cutRotation * 180; float degree = m_cutRotation * 180;
QMatrix4x4 rotation; QMatrix4x4 rotation;
rotation.rotate(degree, cutNormal); rotation.rotate(degree, traverseDirection);
baseNormal = rotation * baseNormal; baseNormal = rotation * baseNormal;
for (auto &positionOnCut: resultCut) { for (auto &positionOnCut: resultCut) {
positionOnCut = rotation * positionOnCut; positionOnCut = rotation * positionOnCut;

View File

@ -34,12 +34,16 @@ private:
std::vector<size_t> edges; std::vector<size_t> edges;
std::vector<QVector2D> cutTemplate; std::vector<QVector2D> cutTemplate;
std::vector<QVector3D> raysToNeibors; std::vector<QVector3D> raysToNeibors;
QVector3D initialTraverseDirection;
QVector3D traverseDirection;
QVector3D growthDirection; QVector3D growthDirection;
QVector3D initialBaseNormal; QVector3D initialBaseNormal;
QVector3D baseNormal; QVector3D baseNormal;
size_t reversedTraverseOrder;
bool hasInitialBaseNormal = false; bool hasInitialBaseNormal = false;
bool baseNormalResolved = false; bool baseNormalResolved = false;
bool baseNormalSearched = false; bool baseNormalSearched = false;
bool hasInitialTraverseDirection = false;
size_t anotherEdge(size_t edgeIndex) const size_t anotherEdge(size_t edgeIndex) const
{ {
@ -98,6 +102,8 @@ private:
void resolveBaseNormalRecursively(size_t nodeIndex); void resolveBaseNormalRecursively(size_t nodeIndex);
void resolveBaseNormalForLeavesRecursively(size_t nodeIndex, const QVector3D &baseNormal); void resolveBaseNormalForLeavesRecursively(size_t nodeIndex, const QVector3D &baseNormal);
std::pair<QVector3D, bool> searchBaseNormalFromNeighborsRecursively(size_t nodeIndex); std::pair<QVector3D, bool> searchBaseNormalFromNeighborsRecursively(size_t nodeIndex);
void resolveInitialTraverseDirectionRecursively(size_t nodeIndex, const QVector3D *from, std::set<size_t> *visited);
void resolveTraverseDirection(size_t nodeIndex);
bool generateCutsForNode(size_t nodeIndex); bool generateCutsForNode(size_t nodeIndex);
bool tryWrapMultipleBranchesForNode(size_t nodeIndex, std::vector<float> &offsets, bool &offsetsChanged); bool tryWrapMultipleBranchesForNode(size_t nodeIndex, std::vector<float> &offsets, bool &offsetsChanged);
void makeCut(const QVector3D &position, void makeCut(const QVector3D &position,
@ -105,6 +111,7 @@ private:
const std::vector<QVector2D> &cutTemplate, const std::vector<QVector2D> &cutTemplate,
QVector3D &baseNormal, QVector3D &baseNormal,
const QVector3D &cutNormal, const QVector3D &cutNormal,
const QVector3D &traverseDirection,
std::vector<QVector3D> &resultCut); std::vector<QVector3D> &resultCut);
void insertCutVertices(const std::vector<QVector3D> &cut, std::vector<size_t> &vertices, size_t nodeIndex, const QVector3D &cutDirect); void insertCutVertices(const std::vector<QVector3D> &cut, std::vector<size_t> &vertices, size_t nodeIndex, const QVector3D &cutDirect);
void stitchEdgeCuts(); void stitchEdgeCuts();