Fix texture glitchs
parent
5baf139cb6
commit
fc341986c0
|
@ -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);
|
||||
}
|
||||
|
||||
{
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue