Fix texture glitchs

master
Jeremy Hu 2019-05-12 17:45:07 +09:30
parent 5baf139cb6
commit fc341986c0
7 changed files with 107 additions and 18 deletions

View File

@ -27,8 +27,10 @@ void MeshResultPostProcessor::poseProcess()
{ {
std::vector<std::vector<QVector2D>> triangleVertexUvs; std::vector<std::vector<QVector2D>> triangleVertexUvs;
std::set<int> seamVertices; std::set<int> seamVertices;
uvUnwrap(*m_outcome, triangleVertexUvs, seamVertices); std::map<QUuid, std::vector<QRectF>> partUvRects;
uvUnwrap(*m_outcome, triangleVertexUvs, seamVertices, partUvRects);
m_outcome->setTriangleVertexUvs(triangleVertexUvs); m_outcome->setTriangleVertexUvs(triangleVertexUvs);
m_outcome->setPartUvRects(partUvRects);
} }
{ {

View File

@ -6,6 +6,7 @@
#include <QUuid> #include <QUuid>
#include <QColor> #include <QColor>
#include <QVector2D> #include <QVector2D>
#include <QRectF>
#include "bonemark.h" #include "bonemark.h"
#define MAX_WEIGHT_NUM 4 #define MAX_WEIGHT_NUM 4
@ -86,6 +87,18 @@ public:
m_hasTriangleTangents = true; m_hasTriangleTangents = true;
} }
const std::map<QUuid, std::vector<QRectF>> *partUvRects() const
{
if (!m_hasPartUvRects)
return nullptr;
return &m_partUvRects;
}
void setPartUvRects(const std::map<QUuid, std::vector<QRectF>> &uvRects)
{
m_partUvRects = uvRects;
m_hasPartUvRects = true;
}
private: private:
bool m_hasTriangleSourceNodes = false; bool m_hasTriangleSourceNodes = false;
std::vector<std::pair<QUuid, QUuid>> m_triangleSourceNodes; std::vector<std::pair<QUuid, QUuid>> m_triangleSourceNodes;
@ -98,6 +111,9 @@ private:
bool m_hasTriangleTangents = false; bool m_hasTriangleTangents = false;
std::vector<QVector3D> m_triangleTangents; std::vector<QVector3D> m_triangleTangents;
bool m_hasPartUvRects = false;
std::map<QUuid, std::vector<QRectF>> m_partUvRects;
}; };
#endif #endif

View File

@ -211,6 +211,8 @@ void TextureGenerator::generate()
return; return;
if (nullptr == m_outcome->triangleSourceNodes()) if (nullptr == m_outcome->triangleSourceNodes())
return; return;
if (nullptr == m_outcome->partUvRects())
return;
QElapsedTimer countTimeConsumed; QElapsedTimer countTimeConsumed;
countTimeConsumed.start(); countTimeConsumed.start();
@ -225,10 +227,13 @@ void TextureGenerator::generate()
const auto &triangleVertexUvs = *m_outcome->triangleVertexUvs(); const auto &triangleVertexUvs = *m_outcome->triangleVertexUvs();
const auto &triangleSourceNodes = *m_outcome->triangleSourceNodes(); const auto &triangleSourceNodes = *m_outcome->triangleSourceNodes();
const auto &triangleNormals = m_outcome->triangleNormals; const auto &triangleNormals = m_outcome->triangleNormals;
const auto &partUvRects = *m_outcome->partUvRects();
std::map<QUuid, QColor> partColorMap;
std::map<std::pair<QUuid, QUuid>, const OutcomeNode *> nodeMap; std::map<std::pair<QUuid, QUuid>, const OutcomeNode *> nodeMap;
for (const auto &item: m_outcome->nodes) { for (const auto &item: m_outcome->nodes) {
nodeMap.insert({{item.partId, item.nodeId}, &item}); nodeMap.insert({{item.partId, item.nodeId}, &item});
partColorMap.insert({item.partId, item.color});
} }
auto createImageBeginTime = countTimeConsumed.elapsed(); auto createImageBeginTime = countTimeConsumed.elapsed();
@ -291,6 +296,26 @@ void TextureGenerator::generate()
auto paintTextureBeginTime = countTimeConsumed.elapsed(); auto paintTextureBeginTime = countTimeConsumed.elapsed();
texturePainter.setPen(Qt::NoPen); 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++) { for (auto i = 0u; i < triangleVertexUvs.size(); i++) {
QPainterPath path; QPainterPath path;
const std::vector<QVector2D> &uv = triangleVertexUvs[i]; const std::vector<QVector2D> &uv = triangleVertexUvs[i];

View File

@ -1,7 +1,12 @@
#include <simpleuv/uvunwrapper.h> #include <simpleuv/uvunwrapper.h>
#include <QDebug>
#include <QRectF>
#include "uvunwrap.h" #include "uvunwrap.h"
void uvUnwrap(const Outcome &outcome, std::vector<std::vector<QVector2D>> &triangleVertexUvs, std::set<int> &seamVertices) void uvUnwrap(const Outcome &outcome,
std::vector<std::vector<QVector2D>> &triangleVertexUvs,
std::set<int> &seamVertices,
std::map<QUuid, std::vector<QRectF>> &uvRects)
{ {
const auto &choosenVertices = outcome.vertices; const auto &choosenVertices = outcome.vertices;
const auto &choosenTriangles = outcome.triangles; const auto &choosenTriangles = outcome.triangles;
@ -23,7 +28,7 @@ void uvUnwrap(const Outcome &outcome, std::vector<std::vector<QVector2D>> &trian
inputMesh.vertices.push_back(v); inputMesh.vertices.push_back(v);
} }
std::map<QUuid, int> partIdToPartitionMap; std::map<QUuid, int> partIdToPartitionMap;
int partitions = 0; std::vector<QUuid> partitionPartUuids;
for (decltype(choosenTriangles.size()) i = 0; i < choosenTriangles.size(); ++i) { for (decltype(choosenTriangles.size()) i = 0; i < choosenTriangles.size(); ++i) {
const auto &triangle = choosenTriangles[i]; const auto &triangle = choosenTriangles[i];
const auto &sourceNode = triangleSourceNodes[i]; const auto &sourceNode = triangleSourceNodes[i];
@ -34,9 +39,9 @@ void uvUnwrap(const Outcome &outcome, std::vector<std::vector<QVector2D>> &trian
inputMesh.faces.push_back(f); inputMesh.faces.push_back(f);
auto findPartitionResult = partIdToPartitionMap.find(sourceNode.first); auto findPartitionResult = partIdToPartitionMap.find(sourceNode.first);
if (findPartitionResult == partIdToPartitionMap.end()) { if (findPartitionResult == partIdToPartitionMap.end()) {
++partitions; partitionPartUuids.push_back(sourceNode.first);
partIdToPartitionMap.insert({sourceNode.first, partitions}); partIdToPartitionMap.insert({sourceNode.first, (int)partitionPartUuids.size()});
inputMesh.facePartitions.push_back(partitions); inputMesh.facePartitions.push_back((int)partitionPartUuids.size());
} else { } else {
inputMesh.facePartitions.push_back(findPartitionResult->second); inputMesh.facePartitions.push_back(findPartitionResult->second);
} }
@ -46,6 +51,8 @@ void uvUnwrap(const Outcome &outcome, std::vector<std::vector<QVector2D>> &trian
uvUnwrapper.setMesh(inputMesh); uvUnwrapper.setMesh(inputMesh);
uvUnwrapper.unwrap(); uvUnwrapper.unwrap();
const std::vector<simpleuv::FaceTextureCoords> &resultFaceUvs = uvUnwrapper.getFaceUvs(); const std::vector<simpleuv::FaceTextureCoords> &resultFaceUvs = uvUnwrapper.getFaceUvs();
const std::vector<QRectF> &resultChartRects = uvUnwrapper.getChartRects();
const std::vector<int> &resultChartSourcePartitions = uvUnwrapper.getChartSourcePartitions();
std::map<int, QVector2D> vertexUvMap; std::map<int, QVector2D> vertexUvMap;
for (decltype(choosenTriangles.size()) i = 0; i < choosenTriangles.size(); ++i) { for (decltype(choosenTriangles.size()) i = 0; i < choosenTriangles.size(); ++i) {
const auto &triangle = choosenTriangles[i]; const auto &triangle = choosenTriangles[i];
@ -66,4 +73,13 @@ void uvUnwrap(const Outcome &outcome, std::vector<std::vector<QVector2D>> &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);
}
} }

View File

@ -4,6 +4,9 @@
#include <QVector2D> #include <QVector2D>
#include "outcome.h" #include "outcome.h"
void uvUnwrap(const Outcome &outcome, std::vector<std::vector<QVector2D>> &triangleVertexUvs, std::set<int> &seamVertices); void uvUnwrap(const Outcome &outcome,
std::vector<std::vector<QVector2D>> &triangleVertexUvs,
std::set<int> &seamVertices,
std::map<QUuid, std::vector<QRectF>> &uvRects);
#endif #endif

View File

@ -17,11 +17,21 @@ void UvUnwrapper::setMesh(const Mesh &mesh)
m_mesh = mesh; m_mesh = mesh;
} }
const std::vector<FaceTextureCoords> &UvUnwrapper::getFaceUvs() const std::vector<FaceTextureCoords> &UvUnwrapper::getFaceUvs() const
{ {
return m_faceUvs; return m_faceUvs;
} }
const std::vector<QRectF> &UvUnwrapper::getChartRects() const
{
return m_chartRects;
}
const std::vector<int> &UvUnwrapper::getChartSourcePartitions() const
{
return m_chartSourcePartitions;
}
void UvUnwrapper::buildEdgeToFaceMap(const std::vector<Face> &faces, std::map<std::pair<size_t, size_t>, size_t> &edgeToFaceMap) void UvUnwrapper::buildEdgeToFaceMap(const std::vector<Face> &faces, std::map<std::pair<size_t, size_t>, size_t> &edgeToFaceMap)
{ {
edgeToFaceMap.clear(); edgeToFaceMap.clear();
@ -294,8 +304,11 @@ void UvUnwrapper::makeSeamAndCut(const std::vector<Vertex> &verticies,
void UvUnwrapper::calculateSizeAndRemoveInvalidCharts() void UvUnwrapper::calculateSizeAndRemoveInvalidCharts()
{ {
auto charts = m_charts; auto charts = m_charts;
auto chartSourcePartitions = m_chartSourcePartitions;
m_charts.clear(); 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; float left, top, right, bottom;
left = top = right = bottom = 0; left = top = right = bottom = 0;
calculateFaceTextureBoundingBox(chart.second, left, top, right, bottom); calculateFaceTextureBoundingBox(chart.second, left, top, right, bottom);
@ -315,6 +328,7 @@ void UvUnwrapper::calculateSizeAndRemoveInvalidCharts()
//qDebug() << "width:" << size.first << "height:" << size.second; //qDebug() << "width:" << size.first << "height:" << size.second;
m_chartSizes.push_back(size); m_chartSizes.push_back(size);
m_charts.push_back(chart); m_charts.push_back(chart);
m_chartSourcePartitions.push_back(chartSourcePartitions[chartIndex]);
} }
} }
@ -323,6 +337,7 @@ void UvUnwrapper::packCharts()
ChartPacker chartPacker; ChartPacker chartPacker;
chartPacker.setCharts(m_chartSizes); chartPacker.setCharts(m_chartSizes);
chartPacker.pack(); chartPacker.pack();
m_chartRects.resize(m_chartSizes.size());
const std::vector<std::tuple<float, float, float, float, bool>> &packedResult = chartPacker.getResult(); const std::vector<std::tuple<float, float, float, float, bool>> &packedResult = chartPacker.getResult();
for (decltype(m_charts.size()) i = 0; i < m_charts.size(); ++i) { for (decltype(m_charts.size()) i = 0; i < m_charts.size(); ++i) {
const auto &chartSize = m_chartSizes[i]; const auto &chartSize = m_chartSizes[i];
@ -342,6 +357,10 @@ void UvUnwrapper::packCharts()
auto &width = std::get<2>(result); auto &width = std::get<2>(result);
auto &height = std::get<3>(result); auto &height = std::get<3>(result);
auto &flipped = std::get<4>(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) { if (flipped) {
for (auto &item: chart.second) { for (auto &item: chart.second) {
for (int i = 0; i < 3; ++i) { for (int i = 0; i < 3; ++i) {
@ -388,7 +407,7 @@ void UvUnwrapper::partition()
} }
} }
void UvUnwrapper::unwrapSingleIsland(const std::vector<size_t> &group, bool skipCheckHoles) void UvUnwrapper::unwrapSingleIsland(const std::vector<size_t> &group, int sourcePartition, bool skipCheckHoles)
{ {
if (group.empty()) if (group.empty())
return; return;
@ -424,7 +443,7 @@ void UvUnwrapper::unwrapSingleIsland(const std::vector<size_t> &group, bool skip
return; return;
} }
if (1 == remainingHoleNumAfterFix) { if (1 == remainingHoleNumAfterFix) {
parametrizeSingleGroup(localVertices, localFaces, localToGlobalFacesMap, faceNumBeforeFix); parametrizeSingleGroup(localVertices, localFaces, localToGlobalFacesMap, faceNumBeforeFix, sourcePartition);
return; return;
} }
@ -436,8 +455,8 @@ void UvUnwrapper::unwrapSingleIsland(const std::vector<size_t> &group, bool skip
qDebug() << "Cut mesh failed"; qDebug() << "Cut mesh failed";
return; return;
} }
unwrapSingleIsland(firstGroup, true); unwrapSingleIsland(firstGroup, sourcePartition, true);
unwrapSingleIsland(secondGroup, true); unwrapSingleIsland(secondGroup, sourcePartition, true);
return; return;
} }
} }
@ -445,7 +464,8 @@ void UvUnwrapper::unwrapSingleIsland(const std::vector<size_t> &group, bool skip
void UvUnwrapper::parametrizeSingleGroup(const std::vector<Vertex> &verticies, void UvUnwrapper::parametrizeSingleGroup(const std::vector<Vertex> &verticies,
const std::vector<Face> &faces, const std::vector<Face> &faces,
std::map<size_t, size_t> &localToGlobalFacesMap, std::map<size_t, size_t> &localToGlobalFacesMap,
size_t faceNumToChart) size_t faceNumToChart,
int sourcePartition)
{ {
std::vector<TextureCoord> localVertexUvs; std::vector<TextureCoord> localVertexUvs;
if (!parametrize(verticies, faces, localVertexUvs)) if (!parametrize(verticies, faces, localVertexUvs))
@ -467,6 +487,7 @@ void UvUnwrapper::parametrizeSingleGroup(const std::vector<Vertex> &verticies,
if (chart.first.empty()) if (chart.first.empty())
return; return;
m_charts.push_back(chart); m_charts.push_back(chart);
m_chartSourcePartitions.push_back(sourcePartition);
} }
void UvUnwrapper::unwrap() void UvUnwrapper::unwrap()
@ -478,7 +499,7 @@ void UvUnwrapper::unwrap()
std::vector<std::vector<size_t>> islands; std::vector<std::vector<size_t>> islands;
splitPartitionToIslands(group.second, islands); splitPartitionToIslands(group.second, islands);
for (const auto &island: islands) for (const auto &island: islands)
unwrapSingleIsland(island); unwrapSingleIsland(island, group.first);
} }
calculateSizeAndRemoveInvalidCharts(); calculateSizeAndRemoveInvalidCharts();

View File

@ -2,6 +2,7 @@
#define SIMPLEUV_UV_UNWRAPPER_H #define SIMPLEUV_UV_UNWRAPPER_H
#include <vector> #include <vector>
#include <map> #include <map>
#include <QRectF>
#include <simpleuv/meshdatatype.h> #include <simpleuv/meshdatatype.h>
namespace simpleuv namespace simpleuv
@ -12,16 +13,19 @@ class UvUnwrapper
public: public:
void setMesh(const Mesh &mesh); void setMesh(const Mesh &mesh);
void unwrap(); void unwrap();
const std::vector<FaceTextureCoords> &getFaceUvs(); const std::vector<FaceTextureCoords> &getFaceUvs() const;
const std::vector<QRectF> &getChartRects() const;
const std::vector<int> &getChartSourcePartitions() const;
private: private:
void partition(); void partition();
void splitPartitionToIslands(const std::vector<size_t> &group, std::vector<std::vector<size_t>> &islands); void splitPartitionToIslands(const std::vector<size_t> &group, std::vector<std::vector<size_t>> &islands);
void unwrapSingleIsland(const std::vector<size_t> &group, bool skipCheckHoles=false); void unwrapSingleIsland(const std::vector<size_t> &group, int sourcePartition, bool skipCheckHoles=false);
void parametrizeSingleGroup(const std::vector<Vertex> &verticies, void parametrizeSingleGroup(const std::vector<Vertex> &verticies,
const std::vector<Face> &faces, const std::vector<Face> &faces,
std::map<size_t, size_t> &localToGlobalFacesMap, std::map<size_t, size_t> &localToGlobalFacesMap,
size_t faceNumToChart); size_t faceNumToChart,
int sourcePartition);
bool fixHolesExceptTheLongestRing(const std::vector<Vertex> &verticies, std::vector<Face> &faces, size_t *remainingHoleNum=nullptr); bool fixHolesExceptTheLongestRing(const std::vector<Vertex> &verticies, std::vector<Face> &faces, size_t *remainingHoleNum=nullptr);
void makeSeamAndCut(const std::vector<Vertex> &verticies, void makeSeamAndCut(const std::vector<Vertex> &verticies,
const std::vector<Face> &faces, const std::vector<Face> &faces,
@ -43,6 +47,8 @@ private:
std::map<int, std::vector<size_t>> m_partitions; std::map<int, std::vector<size_t>> m_partitions;
std::vector<std::pair<std::vector<size_t>, std::vector<FaceTextureCoords>>> m_charts; std::vector<std::pair<std::vector<size_t>, std::vector<FaceTextureCoords>>> m_charts;
std::vector<std::pair<float, float>> m_chartSizes; std::vector<std::pair<float, float>> m_chartSizes;
std::vector<QRectF> m_chartRects;
std::vector<int> m_chartSourcePartitions;
}; };
} }