From b8404820502fae5098e83d8f109fe5300537fb12 Mon Sep 17 00:00:00 2001 From: Jeremy Hu Date: Sat, 10 Aug 2019 12:24:47 +0930 Subject: [PATCH] New improvement on UV unwrapping Automatically try rotating each island on 5, 15, 20, 25, 30, 35, 40, 45 degrees, and choose the best rotation. --- thirdparty/simpleuv/simpleuv/uvunwrapper.cpp | 49 ++++++++++++++++++++ thirdparty/simpleuv/simpleuv/uvunwrapper.h | 4 +- 2 files changed, 52 insertions(+), 1 deletion(-) diff --git a/thirdparty/simpleuv/simpleuv/uvunwrapper.cpp b/thirdparty/simpleuv/simpleuv/uvunwrapper.cpp index 1b63b809..b6283b49 100644 --- a/thirdparty/simpleuv/simpleuv/uvunwrapper.cpp +++ b/thirdparty/simpleuv/simpleuv/uvunwrapper.cpp @@ -9,10 +9,13 @@ #include #include #include +#include namespace simpleuv { +const std::vector UvUnwrapper::m_rotateDegrees = {5, 15, 20, 25, 30, 35, 40, 45}; + void UvUnwrapper::setMesh(const Mesh &mesh) { m_mesh = mesh; @@ -370,6 +373,52 @@ void UvUnwrapper::calculateSizeAndRemoveInvalidCharts() QVector2D(item.coords[1].uv[0], item.coords[1].uv[1]), QVector2D(item.coords[2].uv[0], item.coords[2].uv[1])); } + if (m_enableRotation) { + QVector3D center(size.first * 0.5, size.second * 0.5, 0); + float minRectArea = size.first * size.second; + float minRectLeft = 0; + float minRectTop = 0; + bool rotated = false; + float choosenDegree = 0; + for (const auto °ree: m_rotateDegrees) { + QMatrix4x4 matrix; + matrix.rotate(degree, 0, 0, 1); + std::vector rotatedUvs; + for (auto &item: chart.second) { + FaceTextureCoords rotatedCoords; + for (int i = 0; i < 3; ++i) { + QVector3D point(item.coords[i].uv[0], item.coords[i].uv[1], 0); + point -= center; + point = matrix * point; + rotatedCoords.coords[i].uv[0] = point.x(); + rotatedCoords.coords[i].uv[1] = point.y(); + } + rotatedUvs.push_back(rotatedCoords); + } + left = top = right = bottom = 0; + calculateFaceTextureBoundingBox(rotatedUvs, left, top, right, bottom); + std::pair newSize = {right - left, bottom - top}; + float newRectArea = newSize.first * newSize.second; + if (newRectArea < minRectArea) { + minRectArea = newRectArea; + size = newSize; + minRectLeft = left; + minRectTop = top; + choosenDegree = degree; + rotated = true; + chart.second = rotatedUvs; + } + } + if (rotated) { + //qDebug() << "Choosen degree:" << choosenDegree; + for (auto &item: chart.second) { + for (int i = 0; i < 3; ++i) { + item.coords[i].uv[0] -= minRectLeft; + item.coords[i].uv[1] -= minRectTop; + } + } + } + } //qDebug() << "left:" << left << "top:" << top << "right:" << right << "bottom:" << bottom; //qDebug() << "width:" << size.first << "height:" << size.second; float ratioOfSurfaceAreaAndUvArea = uvArea > 0 ? surfaceArea / uvArea : 1.0; diff --git a/thirdparty/simpleuv/simpleuv/uvunwrapper.h b/thirdparty/simpleuv/simpleuv/uvunwrapper.h index 14c60a4d..5b648fb9 100644 --- a/thirdparty/simpleuv/simpleuv/uvunwrapper.h +++ b/thirdparty/simpleuv/simpleuv/uvunwrapper.h @@ -57,10 +57,12 @@ private: std::vector m_chartRects; std::vector m_chartSourcePartitions; bool m_segmentByNormal = true; - float m_segmentDotProductThreshold = -0.5; //120 degrees + float m_segmentDotProductThreshold = 0.0; //90 degrees float m_texelSizePerUnit = 1.0; float m_resultTextureSize = 0; bool m_segmentPreferMorePieces = true; + bool m_enableRotation = true; + static const std::vector m_rotateDegrees; }; }