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::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->setPartUvRects(partUvRects);
}
{

View File

@ -6,6 +6,7 @@
#include <QUuid>
#include <QColor>
#include <QVector2D>
#include <QRectF>
#include "bonemark.h"
#define MAX_WEIGHT_NUM 4
@ -86,6 +87,18 @@ public:
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:
bool m_hasTriangleSourceNodes = false;
std::vector<std::pair<QUuid, QUuid>> m_triangleSourceNodes;
@ -98,6 +111,9 @@ private:
bool m_hasTriangleTangents = false;
std::vector<QVector3D> m_triangleTangents;
bool m_hasPartUvRects = false;
std::map<QUuid, std::vector<QRectF>> m_partUvRects;
};
#endif

View File

@ -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<QUuid, QColor> partColorMap;
std::map<std::pair<QUuid, QUuid>, 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<QVector2D> &uv = triangleVertexUvs[i];

View File

@ -1,7 +1,12 @@
#include <simpleuv/uvunwrapper.h>
#include <QDebug>
#include <QRectF>
#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 &choosenTriangles = outcome.triangles;
@ -23,7 +28,7 @@ void uvUnwrap(const Outcome &outcome, std::vector<std::vector<QVector2D>> &trian
inputMesh.vertices.push_back(v);
}
std::map<QUuid, int> partIdToPartitionMap;
int partitions = 0;
std::vector<QUuid> 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<std::vector<QVector2D>> &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<std::vector<QVector2D>> &trian
uvUnwrapper.setMesh(inputMesh);
uvUnwrapper.unwrap();
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;
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<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 "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

View File

@ -17,11 +17,21 @@ void UvUnwrapper::setMesh(const Mesh &mesh)
m_mesh = mesh;
}
const std::vector<FaceTextureCoords> &UvUnwrapper::getFaceUvs()
const std::vector<FaceTextureCoords> &UvUnwrapper::getFaceUvs() const
{
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)
{
edgeToFaceMap.clear();
@ -294,8 +304,11 @@ void UvUnwrapper::makeSeamAndCut(const std::vector<Vertex> &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<std::tuple<float, float, float, float, bool>> &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<size_t> &group, bool skipCheckHoles)
void UvUnwrapper::unwrapSingleIsland(const std::vector<size_t> &group, int sourcePartition, bool skipCheckHoles)
{
if (group.empty())
return;
@ -424,7 +443,7 @@ void UvUnwrapper::unwrapSingleIsland(const std::vector<size_t> &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<size_t> &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<size_t> &group, bool skip
void UvUnwrapper::parametrizeSingleGroup(const std::vector<Vertex> &verticies,
const std::vector<Face> &faces,
std::map<size_t, size_t> &localToGlobalFacesMap,
size_t faceNumToChart)
size_t faceNumToChart,
int sourcePartition)
{
std::vector<TextureCoord> localVertexUvs;
if (!parametrize(verticies, faces, localVertexUvs))
@ -467,6 +487,7 @@ void UvUnwrapper::parametrizeSingleGroup(const std::vector<Vertex> &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<std::vector<size_t>> islands;
splitPartitionToIslands(group.second, islands);
for (const auto &island: islands)
unwrapSingleIsland(island);
unwrapSingleIsland(island, group.first);
}
calculateSizeAndRemoveInvalidCharts();

View File

@ -2,6 +2,7 @@
#define SIMPLEUV_UV_UNWRAPPER_H
#include <vector>
#include <map>
#include <QRectF>
#include <simpleuv/meshdatatype.h>
namespace simpleuv
@ -12,16 +13,19 @@ class UvUnwrapper
public:
void setMesh(const Mesh &mesh);
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:
void partition();
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,
const std::vector<Face> &faces,
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);
void makeSeamAndCut(const std::vector<Vertex> &verticies,
const std::vector<Face> &faces,
@ -43,6 +47,8 @@ private:
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<float, float>> m_chartSizes;
std::vector<QRectF> m_chartRects;
std::vector<int> m_chartSourcePartitions;
};
}