Segment UV by normal

master
Jeremy Hu 2019-08-09 19:56:31 +09:30
parent bde3c01da0
commit f5a70dfd9e
5 changed files with 30 additions and 1 deletions

View File

@ -10,6 +10,7 @@ void uvUnwrap(const Outcome &outcome,
{ {
const auto &choosenVertices = outcome.vertices; const auto &choosenVertices = outcome.vertices;
const auto &choosenTriangles = outcome.triangles; const auto &choosenTriangles = outcome.triangles;
const auto &choosenTriangleNormals = outcome.triangleNormals;
triangleVertexUvs.resize(choosenTriangles.size(), { triangleVertexUvs.resize(choosenTriangles.size(), {
QVector2D(), QVector2D(), QVector2D() QVector2D(), QVector2D(), QVector2D()
}); });
@ -32,11 +33,17 @@ void uvUnwrap(const Outcome &outcome,
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];
const auto &normal = choosenTriangleNormals[i];
simpleuv::Face f; simpleuv::Face f;
f.indices[0] = triangle[0]; f.indices[0] = triangle[0];
f.indices[1] = triangle[1]; f.indices[1] = triangle[1];
f.indices[2] = triangle[2]; f.indices[2] = triangle[2];
inputMesh.faces.push_back(f); inputMesh.faces.push_back(f);
simpleuv::Vector3 n;
n.xyz[0] = normal.x();
n.xyz[1] = normal.y();
n.xyz[2] = normal.z();
inputMesh.faceNormals.push_back(n);
auto findPartitionResult = partIdToPartitionMap.find(sourceNode.first); auto findPartitionResult = partIdToPartitionMap.find(sourceNode.first);
if (findPartitionResult == partIdToPartitionMap.end()) { if (findPartitionResult == partIdToPartitionMap.end()) {
partitionPartUuids.push_back(sourceNode.first); partitionPartUuids.push_back(sourceNode.first);

View File

@ -25,6 +25,7 @@ private:
size_t m_tryNum = 0; size_t m_tryNum = 0;
float m_textureSizeFactor = 1.0; float m_textureSizeFactor = 1.0;
size_t m_maxTryNum = 100; size_t m_maxTryNum = 100;
float m_texelSizePerUnit = 1.0f;
}; };
} }

View File

@ -6,11 +6,13 @@
namespace simpleuv namespace simpleuv
{ {
struct Vertex struct Vector3
{ {
float xyz[3]; float xyz[3];
}; };
typedef Vector3 Vertex;
struct Face struct Face
{ {
size_t indices[3]; size_t indices[3];
@ -30,6 +32,7 @@ struct Mesh
{ {
std::vector<Vertex> vertices; std::vector<Vertex> vertices;
std::vector<Face> faces; std::vector<Face> faces;
std::vector<Vector3> faceNormals;
std::vector<int> facePartitions; std::vector<int> facePartitions;
}; };

View File

@ -8,6 +8,7 @@
#include <simpleuv/chartpacker.h> #include <simpleuv/chartpacker.h>
#include <simpleuv/triangulate.h> #include <simpleuv/triangulate.h>
#include <QDebug> #include <QDebug>
#include <QVector3D>
namespace simpleuv namespace simpleuv
{ {
@ -60,6 +61,7 @@ void UvUnwrapper::splitPartitionToIslands(const std::vector<size_t> &group, std:
{ {
std::map<std::pair<size_t, size_t>, size_t> edgeToFaceMap; std::map<std::pair<size_t, size_t>, size_t> edgeToFaceMap;
buildEdgeToFaceMap(group, edgeToFaceMap); buildEdgeToFaceMap(group, edgeToFaceMap);
bool segmentByNormal = !m_mesh.faceNormals.empty() && m_segmentByNormal;
std::unordered_set<size_t> processedFaces; std::unordered_set<size_t> processedFaces;
std::queue<size_t> waitFaces; std::queue<size_t> waitFaces;
@ -79,6 +81,12 @@ void UvUnwrapper::splitPartitionToIslands(const std::vector<size_t> &group, std:
auto findOppositeFaceResult = edgeToFaceMap.find({face.indices[j], face.indices[i]}); auto findOppositeFaceResult = edgeToFaceMap.find({face.indices[j], face.indices[i]});
if (findOppositeFaceResult == edgeToFaceMap.end()) if (findOppositeFaceResult == edgeToFaceMap.end())
continue; continue;
if (segmentByNormal) {
if (dotProduct(m_mesh.faceNormals[findOppositeFaceResult->second],
m_mesh.faceNormals[index]) < m_segmentDotProductThreshold) {
continue;
}
}
waitFaces.push(findOppositeFaceResult->second); waitFaces.push(findOppositeFaceResult->second);
} }
island.push_back(index); island.push_back(index);
@ -98,6 +106,13 @@ double UvUnwrapper::distanceBetweenVertices(const Vertex &first, const Vertex &s
return std::sqrt(x*x + y*y + z*z); return std::sqrt(x*x + y*y + z*z);
} }
double UvUnwrapper::dotProduct(const Vertex &first, const Vertex &second)
{
const QVector3D &firstVector = QVector3D(first.xyz[0], first.xyz[1], first.xyz[2]);
const QVector3D &secondVector = QVector3D(second.xyz[0], second.xyz[1], second.xyz[2]);
return QVector3D::dotProduct(firstVector, secondVector);
}
void UvUnwrapper::calculateFaceTextureBoundingBox(const std::vector<FaceTextureCoords> &faceTextureCoords, void UvUnwrapper::calculateFaceTextureBoundingBox(const std::vector<FaceTextureCoords> &faceTextureCoords,
float &left, float &top, float &right, float &bottom) float &left, float &top, float &right, float &bottom)
{ {

View File

@ -37,6 +37,7 @@ private:
void buildEdgeToFaceMap(const std::vector<size_t> &group, std::map<std::pair<size_t, size_t>, size_t> &edgeToFaceMap); void buildEdgeToFaceMap(const std::vector<size_t> &group, std::map<std::pair<size_t, size_t>, size_t> &edgeToFaceMap);
void buildEdgeToFaceMap(const std::vector<Face> &faces, std::map<std::pair<size_t, size_t>, size_t> &edgeToFaceMap); void buildEdgeToFaceMap(const std::vector<Face> &faces, std::map<std::pair<size_t, size_t>, size_t> &edgeToFaceMap);
double distanceBetweenVertices(const Vertex &first, const Vertex &second); double distanceBetweenVertices(const Vertex &first, const Vertex &second);
double dotProduct(const Vertex &first, const Vertex &second);
void triangulateRing(const std::vector<Vertex> &verticies, void triangulateRing(const std::vector<Vertex> &verticies,
std::vector<Face> &faces, const std::vector<size_t> &ring); std::vector<Face> &faces, const std::vector<size_t> &ring);
void calculateFaceTextureBoundingBox(const std::vector<FaceTextureCoords> &faceTextureCoords, void calculateFaceTextureBoundingBox(const std::vector<FaceTextureCoords> &faceTextureCoords,
@ -49,6 +50,8 @@ private:
std::vector<std::pair<float, float>> m_chartSizes; std::vector<std::pair<float, float>> m_chartSizes;
std::vector<QRectF> m_chartRects; std::vector<QRectF> m_chartRects;
std::vector<int> m_chartSourcePartitions; std::vector<int> m_chartSourcePartitions;
bool m_segmentByNormal = true;
float m_segmentDotProductThreshold = 0.00;
}; };
} }