Fix texture generation

master
Jeremy Hu 2018-10-16 08:04:08 +08:00
parent 7e0591de6b
commit 7fa29dcc48
2 changed files with 73 additions and 28 deletions

View File

@ -33,7 +33,7 @@ public:
static int m_textureSize; static int m_textureSize;
private: private:
void prepare(); void prepare();
QPainterPath expandedPainterPath(const QPainterPath &painterPath, int expandSize=3); QPainterPath expandedPainterPath(const QPainterPath &painterPath, int expandSize=7);
private: private:
MeshResultContext *m_resultContext; MeshResultContext *m_resultContext;
QImage *m_resultTextureGuideImage; QImage *m_resultTextureGuideImage;

View File

@ -1,5 +1,6 @@
#include <map> #include <map>
#include <unordered_set> #include <unordered_set>
#include <set>
#include <queue> #include <queue>
#include <simpleuv/uvunwrapper.h> #include <simpleuv/uvunwrapper.h>
#include <simpleuv/parametrize.h> #include <simpleuv/parametrize.h>
@ -129,22 +130,28 @@ bool UvUnwrapper::fixHolesExceptTheLongestRing(const std::vector<Vertex> &vertic
std::map<std::pair<size_t, size_t>, size_t> edgeToFaceMap; std::map<std::pair<size_t, size_t>, size_t> edgeToFaceMap;
buildEdgeToFaceMap(faces, edgeToFaceMap); buildEdgeToFaceMap(faces, edgeToFaceMap);
std::map<size_t, size_t> holeVertexLink; std::map<size_t, std::vector<size_t>> holeVertexLink;
for (const auto &face: faces) { for (const auto &face: faces) {
for (size_t i = 0; i < 3; i++) { for (size_t i = 0; i < 3; i++) {
size_t j = (i + 1) % 3; size_t j = (i + 1) % 3;
auto findOppositeFaceResult = edgeToFaceMap.find({face.indicies[j], face.indicies[i]}); auto findOppositeFaceResult = edgeToFaceMap.find({face.indicies[j], face.indicies[i]});
if (findOppositeFaceResult != edgeToFaceMap.end()) if (findOppositeFaceResult != edgeToFaceMap.end())
continue; continue;
holeVertexLink[face.indicies[j]] = face.indicies[i]; holeVertexLink[face.indicies[j]].push_back(face.indicies[i]);
} }
} }
std::vector<std::pair<std::vector<size_t>, double>> holeRings; std::vector<std::pair<std::vector<size_t>, double>> holeRings;
std::unordered_set<size_t> visited;
while (!holeVertexLink.empty()) { while (!holeVertexLink.empty()) {
bool foundRing = false;
std::vector<size_t> ring; std::vector<size_t> ring;
std::unordered_set<size_t> visited;
std::set<std::pair<size_t, size_t>> visitedPath;
double ringLength = 0; double ringLength = 0;
while (!foundRing) {
ring.clear();
visited.clear();
ringLength = 0;
auto first = holeVertexLink.begin()->first; auto first = holeVertexLink.begin()->first;
auto index = first; auto index = first;
auto prev = first; auto prev = first;
@ -156,22 +163,60 @@ bool UvUnwrapper::fixHolesExceptTheLongestRing(const std::vector<Vertex> &vertic
qDebug() << "Search ring failed"; qDebug() << "Search ring failed";
return false; return false;
} }
index = findLinkResult->second; for (const auto &item: findLinkResult->second) {
if (index == first) { if (item == first) {
foundRing = true;
break; break;
} }
if (visited.find(index) != visited.end()) { }
qDebug() << "Found infinite ring"; if (foundRing)
break;
if (findLinkResult->second.size() > 1) {
bool foundNewPath = false;
for (const auto &item: findLinkResult->second) {
if (visitedPath.find({prev, item}) == visitedPath.end()) {
index = item;
foundNewPath = true;
break;
}
}
if (!foundNewPath) {
qDebug() << "No new path to try";
return false; return false;
} }
visited.insert(index); visitedPath.insert({prev, index});
} else {
index = *findLinkResult->second.begin();
}
if (visited.find(index) != visited.end()) {
while (index != *ring.begin())
ring.erase(ring.begin());
foundRing = true;
break;
}
ring.push_back(index); ring.push_back(index);
visited.insert(index);
ringLength += distanceBetweenVertices(verticies[index], verticies[prev]); ringLength += distanceBetweenVertices(verticies[index], verticies[prev]);
prev = index; prev = index;
} }
}
if (ring.size() < 3) {
qDebug() << "Ring too short, size:" << ring.size();
return false;
}
holeRings.push_back({ring, ringLength}); holeRings.push_back({ring, ringLength});
for (const auto &index: ring) for (size_t i = 0; i < ring.size(); ++i) {
holeVertexLink.erase(index); size_t j = (i + 1) % ring.size();
auto findLinkResult = holeVertexLink.find(ring[i]);
for (auto it = findLinkResult->second.begin(); it != findLinkResult->second.end(); ++it) {
if (*it == ring[j]) {
findLinkResult->second.erase(it);
if (findLinkResult->second.empty())
holeVertexLink.erase(ring[i]);
break;
}
}
}
} }
if (holeRings.size() > 1) { if (holeRings.size() > 1) {