From fc341986c05e209cca049e88aa98462ae58a4ce3 Mon Sep 17 00:00:00 2001 From: Jeremy Hu Date: Sun, 12 May 2019 17:45:07 +0930 Subject: [PATCH] Fix texture glitchs --- src/meshresultpostprocessor.cpp | 4 ++- src/outcome.h | 16 +++++++++ src/texturegenerator.cpp | 25 +++++++++++++ src/uvunwrap.cpp | 26 +++++++++++--- src/uvunwrap.h | 5 ++- thirdparty/simpleuv/simpleuv/uvunwrapper.cpp | 37 +++++++++++++++----- thirdparty/simpleuv/simpleuv/uvunwrapper.h | 12 +++++-- 7 files changed, 107 insertions(+), 18 deletions(-) diff --git a/src/meshresultpostprocessor.cpp b/src/meshresultpostprocessor.cpp index 90fb1a9f..9e564425 100644 --- a/src/meshresultpostprocessor.cpp +++ b/src/meshresultpostprocessor.cpp @@ -27,8 +27,10 @@ void MeshResultPostProcessor::poseProcess() { std::vector> triangleVertexUvs; std::set seamVertices; - uvUnwrap(*m_outcome, triangleVertexUvs, seamVertices); + std::map> partUvRects; + uvUnwrap(*m_outcome, triangleVertexUvs, seamVertices, partUvRects); m_outcome->setTriangleVertexUvs(triangleVertexUvs); + m_outcome->setPartUvRects(partUvRects); } { diff --git a/src/outcome.h b/src/outcome.h index a9e30e38..ff328118 100644 --- a/src/outcome.h +++ b/src/outcome.h @@ -6,6 +6,7 @@ #include #include #include +#include #include "bonemark.h" #define MAX_WEIGHT_NUM 4 @@ -86,6 +87,18 @@ public: m_hasTriangleTangents = true; } + const std::map> *partUvRects() const + { + if (!m_hasPartUvRects) + return nullptr; + return &m_partUvRects; + } + void setPartUvRects(const std::map> &uvRects) + { + m_partUvRects = uvRects; + m_hasPartUvRects = true; + } + private: bool m_hasTriangleSourceNodes = false; std::vector> m_triangleSourceNodes; @@ -98,6 +111,9 @@ private: bool m_hasTriangleTangents = false; std::vector m_triangleTangents; + + bool m_hasPartUvRects = false; + std::map> m_partUvRects; }; #endif diff --git a/src/texturegenerator.cpp b/src/texturegenerator.cpp index 584b87af..7e09ee07 100644 --- a/src/texturegenerator.cpp +++ b/src/texturegenerator.cpp @@ -211,6 +211,8 @@ void TextureGenerator::generate() return; if (nullptr == m_outcome->triangleSourceNodes()) return; + if (nullptr == m_outcome->partUvRects()) + return; QElapsedTimer countTimeConsumed; countTimeConsumed.start(); @@ -225,10 +227,13 @@ void TextureGenerator::generate() const auto &triangleVertexUvs = *m_outcome->triangleVertexUvs(); const auto &triangleSourceNodes = *m_outcome->triangleSourceNodes(); const auto &triangleNormals = m_outcome->triangleNormals; + const auto &partUvRects = *m_outcome->partUvRects(); + std::map partColorMap; std::map, const OutcomeNode *> nodeMap; for (const auto &item: m_outcome->nodes) { nodeMap.insert({{item.partId, item.nodeId}, &item}); + partColorMap.insert({item.partId, item.color}); } auto createImageBeginTime = countTimeConsumed.elapsed(); @@ -291,6 +296,26 @@ void TextureGenerator::generate() auto paintTextureBeginTime = countTimeConsumed.elapsed(); texturePainter.setPen(Qt::NoPen); + + for (const auto &it: partUvRects) { + const auto &partId = it.first; + const auto &rects = it.second; + auto findSourceColorResult = partColorMap.find(partId); + if (findSourceColorResult != partColorMap.end()) { + const auto &color = findSourceColorResult->second; + QBrush brush(color); + for (const auto &rect: rects) { + QRectF translatedRect = { + rect.left() * TextureGenerator::m_textureSize, + rect.top() * TextureGenerator::m_textureSize, + rect.width() * TextureGenerator::m_textureSize, + rect.height() * TextureGenerator::m_textureSize + }; + texturePainter.fillRect(translatedRect, brush); + } + } + } + for (auto i = 0u; i < triangleVertexUvs.size(); i++) { QPainterPath path; const std::vector &uv = triangleVertexUvs[i]; diff --git a/src/uvunwrap.cpp b/src/uvunwrap.cpp index 9a277ddd..c1993aed 100644 --- a/src/uvunwrap.cpp +++ b/src/uvunwrap.cpp @@ -1,7 +1,12 @@ #include +#include +#include #include "uvunwrap.h" -void uvUnwrap(const Outcome &outcome, std::vector> &triangleVertexUvs, std::set &seamVertices) +void uvUnwrap(const Outcome &outcome, + std::vector> &triangleVertexUvs, + std::set &seamVertices, + std::map> &uvRects) { const auto &choosenVertices = outcome.vertices; const auto &choosenTriangles = outcome.triangles; @@ -23,7 +28,7 @@ void uvUnwrap(const Outcome &outcome, std::vector> &trian inputMesh.vertices.push_back(v); } std::map partIdToPartitionMap; - int partitions = 0; + std::vector partitionPartUuids; for (decltype(choosenTriangles.size()) i = 0; i < choosenTriangles.size(); ++i) { const auto &triangle = choosenTriangles[i]; const auto &sourceNode = triangleSourceNodes[i]; @@ -34,9 +39,9 @@ void uvUnwrap(const Outcome &outcome, std::vector> &trian inputMesh.faces.push_back(f); auto findPartitionResult = partIdToPartitionMap.find(sourceNode.first); if (findPartitionResult == partIdToPartitionMap.end()) { - ++partitions; - partIdToPartitionMap.insert({sourceNode.first, partitions}); - inputMesh.facePartitions.push_back(partitions); + partitionPartUuids.push_back(sourceNode.first); + partIdToPartitionMap.insert({sourceNode.first, (int)partitionPartUuids.size()}); + inputMesh.facePartitions.push_back((int)partitionPartUuids.size()); } else { inputMesh.facePartitions.push_back(findPartitionResult->second); } @@ -46,6 +51,8 @@ void uvUnwrap(const Outcome &outcome, std::vector> &trian uvUnwrapper.setMesh(inputMesh); uvUnwrapper.unwrap(); const std::vector &resultFaceUvs = uvUnwrapper.getFaceUvs(); + const std::vector &resultChartRects = uvUnwrapper.getChartRects(); + const std::vector &resultChartSourcePartitions = uvUnwrapper.getChartSourcePartitions(); std::map vertexUvMap; for (decltype(choosenTriangles.size()) i = 0; i < choosenTriangles.size(); ++i) { const auto &triangle = choosenTriangles[i]; @@ -66,4 +73,13 @@ void uvUnwrap(const Outcome &outcome, std::vector> &trian } } } + for (size_t i = 0; i < resultChartRects.size(); ++i) { + const auto &rect = resultChartRects[i]; + const auto &source = resultChartSourcePartitions[i]; + if (0 == source || source > (int)partitionPartUuids.size()) { + qDebug() << "Invalid UV chart source partition:" << source; + continue; + } + uvRects[partitionPartUuids[source - 1]].push_back(rect); + } } diff --git a/src/uvunwrap.h b/src/uvunwrap.h index 7a1e79a7..c1f19b98 100644 --- a/src/uvunwrap.h +++ b/src/uvunwrap.h @@ -4,6 +4,9 @@ #include #include "outcome.h" -void uvUnwrap(const Outcome &outcome, std::vector> &triangleVertexUvs, std::set &seamVertices); +void uvUnwrap(const Outcome &outcome, + std::vector> &triangleVertexUvs, + std::set &seamVertices, + std::map> &uvRects); #endif diff --git a/thirdparty/simpleuv/simpleuv/uvunwrapper.cpp b/thirdparty/simpleuv/simpleuv/uvunwrapper.cpp index fcf7eef9..1beccd30 100644 --- a/thirdparty/simpleuv/simpleuv/uvunwrapper.cpp +++ b/thirdparty/simpleuv/simpleuv/uvunwrapper.cpp @@ -17,11 +17,21 @@ void UvUnwrapper::setMesh(const Mesh &mesh) m_mesh = mesh; } -const std::vector &UvUnwrapper::getFaceUvs() +const std::vector &UvUnwrapper::getFaceUvs() const { return m_faceUvs; } +const std::vector &UvUnwrapper::getChartRects() const +{ + return m_chartRects; +} + +const std::vector &UvUnwrapper::getChartSourcePartitions() const +{ + return m_chartSourcePartitions; +} + void UvUnwrapper::buildEdgeToFaceMap(const std::vector &faces, std::map, size_t> &edgeToFaceMap) { edgeToFaceMap.clear(); @@ -294,8 +304,11 @@ void UvUnwrapper::makeSeamAndCut(const std::vector &verticies, void UvUnwrapper::calculateSizeAndRemoveInvalidCharts() { auto charts = m_charts; + auto chartSourcePartitions = m_chartSourcePartitions; m_charts.clear(); - for (auto &chart: charts) { + chartSourcePartitions.clear(); + for (size_t chartIndex = 0; chartIndex < charts.size(); ++chartIndex) { + auto &chart = charts[chartIndex]; float left, top, right, bottom; left = top = right = bottom = 0; calculateFaceTextureBoundingBox(chart.second, left, top, right, bottom); @@ -315,6 +328,7 @@ void UvUnwrapper::calculateSizeAndRemoveInvalidCharts() //qDebug() << "width:" << size.first << "height:" << size.second; m_chartSizes.push_back(size); m_charts.push_back(chart); + m_chartSourcePartitions.push_back(chartSourcePartitions[chartIndex]); } } @@ -323,6 +337,7 @@ void UvUnwrapper::packCharts() ChartPacker chartPacker; chartPacker.setCharts(m_chartSizes); chartPacker.pack(); + m_chartRects.resize(m_chartSizes.size()); const std::vector> &packedResult = chartPacker.getResult(); for (decltype(m_charts.size()) i = 0; i < m_charts.size(); ++i) { const auto &chartSize = m_chartSizes[i]; @@ -342,6 +357,10 @@ void UvUnwrapper::packCharts() auto &width = std::get<2>(result); auto &height = std::get<3>(result); auto &flipped = std::get<4>(result); + if (flipped) + m_chartRects[i] = {left, top, height, width}; + else + m_chartRects[i] = {left, top, width, height}; if (flipped) { for (auto &item: chart.second) { for (int i = 0; i < 3; ++i) { @@ -388,7 +407,7 @@ void UvUnwrapper::partition() } } -void UvUnwrapper::unwrapSingleIsland(const std::vector &group, bool skipCheckHoles) +void UvUnwrapper::unwrapSingleIsland(const std::vector &group, int sourcePartition, bool skipCheckHoles) { if (group.empty()) return; @@ -424,7 +443,7 @@ void UvUnwrapper::unwrapSingleIsland(const std::vector &group, bool skip return; } if (1 == remainingHoleNumAfterFix) { - parametrizeSingleGroup(localVertices, localFaces, localToGlobalFacesMap, faceNumBeforeFix); + parametrizeSingleGroup(localVertices, localFaces, localToGlobalFacesMap, faceNumBeforeFix, sourcePartition); return; } @@ -436,8 +455,8 @@ void UvUnwrapper::unwrapSingleIsland(const std::vector &group, bool skip qDebug() << "Cut mesh failed"; return; } - unwrapSingleIsland(firstGroup, true); - unwrapSingleIsland(secondGroup, true); + unwrapSingleIsland(firstGroup, sourcePartition, true); + unwrapSingleIsland(secondGroup, sourcePartition, true); return; } } @@ -445,7 +464,8 @@ void UvUnwrapper::unwrapSingleIsland(const std::vector &group, bool skip void UvUnwrapper::parametrizeSingleGroup(const std::vector &verticies, const std::vector &faces, std::map &localToGlobalFacesMap, - size_t faceNumToChart) + size_t faceNumToChart, + int sourcePartition) { std::vector localVertexUvs; if (!parametrize(verticies, faces, localVertexUvs)) @@ -467,6 +487,7 @@ void UvUnwrapper::parametrizeSingleGroup(const std::vector &verticies, if (chart.first.empty()) return; m_charts.push_back(chart); + m_chartSourcePartitions.push_back(sourcePartition); } void UvUnwrapper::unwrap() @@ -478,7 +499,7 @@ void UvUnwrapper::unwrap() std::vector> islands; splitPartitionToIslands(group.second, islands); for (const auto &island: islands) - unwrapSingleIsland(island); + unwrapSingleIsland(island, group.first); } calculateSizeAndRemoveInvalidCharts(); diff --git a/thirdparty/simpleuv/simpleuv/uvunwrapper.h b/thirdparty/simpleuv/simpleuv/uvunwrapper.h index 06c00d7d..546390bc 100644 --- a/thirdparty/simpleuv/simpleuv/uvunwrapper.h +++ b/thirdparty/simpleuv/simpleuv/uvunwrapper.h @@ -2,6 +2,7 @@ #define SIMPLEUV_UV_UNWRAPPER_H #include #include +#include #include namespace simpleuv @@ -12,16 +13,19 @@ class UvUnwrapper public: void setMesh(const Mesh &mesh); void unwrap(); - const std::vector &getFaceUvs(); + const std::vector &getFaceUvs() const; + const std::vector &getChartRects() const; + const std::vector &getChartSourcePartitions() const; private: void partition(); void splitPartitionToIslands(const std::vector &group, std::vector> &islands); - void unwrapSingleIsland(const std::vector &group, bool skipCheckHoles=false); + void unwrapSingleIsland(const std::vector &group, int sourcePartition, bool skipCheckHoles=false); void parametrizeSingleGroup(const std::vector &verticies, const std::vector &faces, std::map &localToGlobalFacesMap, - size_t faceNumToChart); + size_t faceNumToChart, + int sourcePartition); bool fixHolesExceptTheLongestRing(const std::vector &verticies, std::vector &faces, size_t *remainingHoleNum=nullptr); void makeSeamAndCut(const std::vector &verticies, const std::vector &faces, @@ -43,6 +47,8 @@ private: std::map> m_partitions; std::vector, std::vector>> m_charts; std::vector> m_chartSizes; + std::vector m_chartRects; + std::vector m_chartSourcePartitions; }; }