Use Eigen to do vector math on UV

master
Jeremy Hu 2019-08-10 23:12:08 +09:30
parent b840482050
commit dacff70eaa
9 changed files with 102 additions and 80 deletions

View File

@ -506,6 +506,7 @@ SOURCES += thirdparty/simpleuv/simpleuv/triangulate.cpp
HEADERS += thirdparty/simpleuv/simpleuv/triangulate.h HEADERS += thirdparty/simpleuv/simpleuv/triangulate.h
HEADERS += thirdparty/simpleuv/simpleuv/meshdatatype.h HEADERS += thirdparty/simpleuv/simpleuv/meshdatatype.h
SOURCES += thirdparty/simpleuv/simpleuv/meshdatatype.cpp
SOURCES += thirdparty/simpleuv/thirdparty/squeezer/maxrects.c SOURCES += thirdparty/simpleuv/thirdparty/squeezer/maxrects.c
HEADERS += thirdparty/simpleuv/thirdparty/squeezer/maxrects.h HEADERS += thirdparty/simpleuv/thirdparty/squeezer/maxrects.h

View File

@ -59,7 +59,7 @@ void uvUnwrap(const Outcome &outcome,
uvUnwrapper.unwrap(); uvUnwrapper.unwrap();
qDebug() << "Texture size:" << uvUnwrapper.textureSize(); qDebug() << "Texture size:" << uvUnwrapper.textureSize();
const std::vector<simpleuv::FaceTextureCoords> &resultFaceUvs = uvUnwrapper.getFaceUvs(); const std::vector<simpleuv::FaceTextureCoords> &resultFaceUvs = uvUnwrapper.getFaceUvs();
const std::vector<QRectF> &resultChartRects = uvUnwrapper.getChartRects(); const std::vector<simpleuv::Rect> &resultChartRects = uvUnwrapper.getChartRects();
const std::vector<int> &resultChartSourcePartitions = uvUnwrapper.getChartSourcePartitions(); const std::vector<int> &resultChartSourcePartitions = uvUnwrapper.getChartSourcePartitions();
std::map<int, QVector2D> vertexUvMap; std::map<int, QVector2D> vertexUvMap;
for (decltype(choosenTriangles.size()) i = 0; i < choosenTriangles.size(); ++i) { for (decltype(choosenTriangles.size()) i = 0; i < choosenTriangles.size(); ++i) {
@ -88,6 +88,6 @@ void uvUnwrap(const Outcome &outcome,
qDebug() << "Invalid UV chart source partition:" << source; qDebug() << "Invalid UV chart source partition:" << source;
continue; continue;
} }
uvRects[partitionPartUuids[source - 1]].push_back(rect); uvRects[partitionPartUuids[source - 1]].push_back({rect.left, rect.top, rect.width, rect.height});
} }
} }

View File

@ -3,7 +3,6 @@
extern "C" { extern "C" {
#include <maxrects.h> #include <maxrects.h>
} }
#include <QDebug>
namespace simpleuv namespace simpleuv
{ {
@ -33,7 +32,7 @@ bool ChartPacker::tryPack(float textureSize)
int width = textureSize * m_floatToIntFactor; int width = textureSize * m_floatToIntFactor;
int height = width; int height = width;
if (m_tryNum > 50) { if (m_tryNum > 50) {
qDebug() << "Try the " << m_tryNum << "nth times pack with factor:" << m_textureSizeFactor << " size:" << width << "x" << height; //qDebug() << "Try the " << m_tryNum << "nth times pack with factor:" << m_textureSizeFactor << " size:" << width << "x" << height;
} }
for (const auto &chartSize: m_chartSizes) { for (const auto &chartSize: m_chartSizes) {
maxRectsSize r; maxRectsSize r;
@ -93,7 +92,7 @@ float ChartPacker::pack()
break; break;
m_textureSizeFactor += m_textureSizeGrowFactor; m_textureSizeFactor += m_textureSizeGrowFactor;
if (m_tryNum >= m_maxTryNum) { if (m_tryNum >= m_maxTryNum) {
qDebug() << "Tried too many times:" << m_tryNum; //qDebug() << "Tried too many times:" << m_tryNum;
break; break;
} }
} }

View File

@ -0,0 +1,26 @@
#include <simpleuv/meshdatatype.h>
#include <Eigen/Dense>
namespace simpleuv
{
float dotProduct(const Vector3 &first, const Vector3 &second)
{
Eigen::Vector3d v(first.xyz[0], first.xyz[1], first.xyz[2]);
Eigen::Vector3d w(second.xyz[0], second.xyz[1], second.xyz[2]);
return v.dot(w);
}
Vector3 crossProduct(const Vector3 &first, const Vector3 &second)
{
Eigen::Vector3d v(first.xyz[0], first.xyz[1], first.xyz[2]);
Eigen::Vector3d w(second.xyz[0], second.xyz[1], second.xyz[2]);
auto u = v.cross(w);
Vector3 result;
result.xyz[0] = u.x();
result.xyz[1] = u.y();
result.xyz[2] = u.z();
return result;
}
}

View File

@ -13,6 +13,14 @@ struct Vector3
typedef Vector3 Vertex; typedef Vector3 Vertex;
struct Rect
{
float left;
float top;
float width;
float height;
};
struct Face struct Face
{ {
size_t indices[3]; size_t indices[3];
@ -36,6 +44,9 @@ struct Mesh
std::vector<int> facePartitions; std::vector<int> facePartitions;
}; };
float dotProduct(const Vector3 &first, const Vector3 &second);
Vector3 crossProduct(const Vector3 &first, const Vector3 &second);
} }
#endif #endif

View File

@ -4,7 +4,6 @@
#include <igl/harmonic.h> #include <igl/harmonic.h>
#include <igl/map_vertices_to_circle.h> #include <igl/map_vertices_to_circle.h>
#include <simpleuv/parametrize.h> #include <simpleuv/parametrize.h>
#include <QDebug>
namespace simpleuv namespace simpleuv
{ {
@ -56,7 +55,7 @@ bool extractResult(const std::vector<Vertex> &verticies, const Eigen::MatrixXd &
return true; return true;
}; };
if ((decltype(verticies.size()))V_uv.size() < verticies.size() * 2) { if ((decltype(verticies.size()))V_uv.size() < verticies.size() * 2) {
qDebug() << "Invalid V_uv.size:" << V_uv.size() << "Expected:" << verticies.size() * 2; //qDebug() << "Invalid V_uv.size:" << V_uv.size() << "Expected:" << verticies.size() * 2;
return false; return false;
} }
for (decltype(verticies.size()) i = 0; i < verticies.size(); i++) { for (decltype(verticies.size()) i = 0; i < verticies.size(); i++) {

View File

@ -1,63 +1,63 @@
#include <simpleuv/triangulate.h> #include <simpleuv/triangulate.h>
#include <QVector3D> #include <Eigen/Dense>
#include <cmath> #include <cmath>
namespace simpleuv namespace simpleuv
{ {
static QVector3D norm(const QVector3D &p1, const QVector3D &p2, const QVector3D &p3) static Eigen::Vector3d norm(const Eigen::Vector3d &p1, const Eigen::Vector3d &p2, const Eigen::Vector3d &p3)
{ {
auto side1 = p2 - p1; auto side1 = p2 - p1;
auto side2 = p3 - p1; auto side2 = p3 - p1;
auto perp = QVector3D::crossProduct(side1, side2); auto perp = side1.cross(side2);
return perp.normalized(); return perp.normalized();
} }
static float angle360(const QVector3D &a, const QVector3D &b, const QVector3D &direct) static float angle360(const Eigen::Vector3d &a, const Eigen::Vector3d &b, const Eigen::Vector3d &direct)
{ {
auto angle = atan2(QVector3D::crossProduct(a, b).length(), QVector3D::dotProduct(a, b)) * 180.0 / 3.1415926; auto angle = atan2((a.cross(b)).norm(), a.dot(b)) * 180.0 / 3.1415926;
auto c = QVector3D::crossProduct(a, b); auto c = a.cross(b);
if (QVector3D::dotProduct(c, direct) < 0) { if (c.dot(direct) < 0) {
angle += 180; angle += 180;
} }
return angle; return angle;
} }
static QVector3D vertexToQVector3D(const Vertex &vertex) static Eigen::Vector3d vertexToEigenVector3d(const Vertex &vertex)
{ {
return QVector3D(vertex.xyz[0], vertex.xyz[1], vertex.xyz[2]); return Eigen::Vector3d(vertex.xyz[0], vertex.xyz[1], vertex.xyz[2]);
} }
static bool pointInTriangle(const QVector3D &a, const QVector3D &b, const QVector3D &c, const QVector3D &p) static bool pointInTriangle(const Eigen::Vector3d &a, const Eigen::Vector3d &b, const Eigen::Vector3d &c, const Eigen::Vector3d &p)
{ {
auto u = b - a; auto u = b - a;
auto v = c - a; auto v = c - a;
auto w = p - a; auto w = p - a;
auto vXw = QVector3D::crossProduct(v, w); auto vXw = v.cross(w);
auto vXu = QVector3D::crossProduct(v, u); auto vXu = v.cross(u);
if (QVector3D::dotProduct(vXw, vXu) < 0.0) { if (vXw.dot(vXu) < 0.0) {
return false; return false;
} }
auto uXw = QVector3D::crossProduct(u, w); auto uXw = u.cross(w);
auto uXv = QVector3D::crossProduct(u, v); auto uXv = u.cross(v);
if (QVector3D::dotProduct(uXw, uXv) < 0.0) { if (uXw.dot(uXv) < 0.0) {
return false; return false;
} }
auto denom = uXv.length(); auto denom = uXv.norm();
auto r = vXw.length() / denom; auto r = vXw.norm() / denom;
auto t = uXw.length() / denom; auto t = uXw.norm() / denom;
return r + t <= 1.0; return r + t <= 1.0;
} }
static QVector3D ringNorm(const std::vector<Vertex> &vertices, const std::vector<size_t> &ring) static Eigen::Vector3d ringNorm(const std::vector<Vertex> &vertices, const std::vector<size_t> &ring)
{ {
QVector3D normal; Eigen::Vector3d normal;
for (size_t i = 0; i < ring.size(); ++i) { for (size_t i = 0; i < ring.size(); ++i) {
auto j = (i + 1) % ring.size(); auto j = (i + 1) % ring.size();
auto k = (i + 2) % ring.size(); auto k = (i + 2) % ring.size();
const auto &enter = vertexToQVector3D(vertices[ring[i]]); const auto &enter = vertexToEigenVector3d(vertices[ring[i]]);
const auto &cone = vertexToQVector3D(vertices[ring[j]]); const auto &cone = vertexToEigenVector3d(vertices[ring[j]]);
const auto &leave = vertexToQVector3D(vertices[ring[k]]); const auto &leave = vertexToEigenVector3d(vertices[ring[k]]);
normal += norm(enter, cone, leave); normal += norm(enter, cone, leave);
} }
return normal.normalized(); return normal.normalized();
@ -68,20 +68,20 @@ void triangulate(const std::vector<Vertex> &vertices, std::vector<Face> &faces,
if (ring.size() < 3) if (ring.size() < 3)
return; return;
std::vector<size_t> fillRing = ring; std::vector<size_t> fillRing = ring;
QVector3D direct = ringNorm(vertices, fillRing); Eigen::Vector3d direct = ringNorm(vertices, fillRing);
while (fillRing.size() > 3) { while (fillRing.size() > 3) {
bool newFaceGenerated = false; bool newFaceGenerated = false;
for (decltype(fillRing.size()) i = 0; i < fillRing.size(); ++i) { for (decltype(fillRing.size()) i = 0; i < fillRing.size(); ++i) {
auto j = (i + 1) % fillRing.size(); auto j = (i + 1) % fillRing.size();
auto k = (i + 2) % fillRing.size(); auto k = (i + 2) % fillRing.size();
const auto &enter = vertexToQVector3D(vertices[fillRing[i]]); const auto &enter = vertexToEigenVector3d(vertices[fillRing[i]]);
const auto &cone = vertexToQVector3D(vertices[fillRing[j]]); const auto &cone = vertexToEigenVector3d(vertices[fillRing[j]]);
const auto &leave = vertexToQVector3D(vertices[fillRing[k]]); const auto &leave = vertexToEigenVector3d(vertices[fillRing[k]]);
auto angle = angle360(cone - enter, leave - cone, direct); auto angle = angle360(cone - enter, leave - cone, direct);
if (angle >= 1.0 && angle <= 179.0) { if (angle >= 1.0 && angle <= 179.0) {
bool isEar = true; bool isEar = true;
for (size_t x = 0; x < fillRing.size() - 3; ++x) { for (size_t x = 0; x < fillRing.size() - 3; ++x) {
auto fourth = vertexToQVector3D(vertices[(i + 3 + k) % fillRing.size()]); auto fourth = vertexToEigenVector3d(vertices[(i + 3 + k) % fillRing.size()]);
if (pointInTriangle(enter, cone, leave, fourth)) { if (pointInTriangle(enter, cone, leave, fourth)) {
isEar = false; isEar = false;
break; break;

View File

@ -7,9 +7,8 @@
#include <simpleuv/parametrize.h> #include <simpleuv/parametrize.h>
#include <simpleuv/chartpacker.h> #include <simpleuv/chartpacker.h>
#include <simpleuv/triangulate.h> #include <simpleuv/triangulate.h>
#include <QDebug> #include <Eigen/Dense>
#include <QVector3D> #include <Eigen/Geometry>
#include <QMatrix4x4>
namespace simpleuv namespace simpleuv
{ {
@ -26,7 +25,7 @@ const std::vector<FaceTextureCoords> &UvUnwrapper::getFaceUvs() const
return m_faceUvs; return m_faceUvs;
} }
const std::vector<QRectF> &UvUnwrapper::getChartRects() const const std::vector<Rect> &UvUnwrapper::getChartRects() const
{ {
return m_chartRects; return m_chartRects;
} }
@ -109,13 +108,6 @@ 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)
{ {
@ -189,7 +181,7 @@ bool UvUnwrapper::fixHolesExceptTheLongestRing(const std::vector<Vertex> &vertic
while (true) { while (true) {
auto findLinkResult = holeVertexLink.find(index); auto findLinkResult = holeVertexLink.find(index);
if (findLinkResult == holeVertexLink.end()) { if (findLinkResult == holeVertexLink.end()) {
qDebug() << "Search ring failed"; //qDebug() << "Search ring failed";
return false; return false;
} }
for (const auto &item: findLinkResult->second) { for (const auto &item: findLinkResult->second) {
@ -210,7 +202,7 @@ bool UvUnwrapper::fixHolesExceptTheLongestRing(const std::vector<Vertex> &vertic
} }
} }
if (!foundNewPath) { if (!foundNewPath) {
qDebug() << "No new path to try"; //qDebug() << "No new path to try";
return false; return false;
} }
visitedPath.insert({prev, index}); visitedPath.insert({prev, index});
@ -230,7 +222,7 @@ bool UvUnwrapper::fixHolesExceptTheLongestRing(const std::vector<Vertex> &vertic
} }
} }
if (ring.size() < 3) { if (ring.size() < 3) {
qDebug() << "Ring too short, size:" << ring.size(); //qDebug() << "Ring too short, size:" << ring.size();
return false; return false;
} }
holeRings.push_back({ring, ringLength}); holeRings.push_back({ring, ringLength});
@ -319,18 +311,18 @@ void UvUnwrapper::makeSeamAndCut(const std::vector<Vertex> &verticies,
} }
} }
float UvUnwrapper::areaOf3dTriangle(const QVector3D &a, const QVector3D &b, const QVector3D &c) float UvUnwrapper::areaOf3dTriangle(const Eigen::Vector3d &a, const Eigen::Vector3d &b, const Eigen::Vector3d &c)
{ {
auto ab = b - a; auto ab = b - a;
auto ac = c - a; auto ac = c - a;
return 0.5 * QVector3D::crossProduct(ab, ac).length(); return 0.5 * (ab.cross(ac)).norm();
} }
float UvUnwrapper::areaOf2dTriangle(const QVector2D &a, const QVector2D &b, const QVector2D &c) float UvUnwrapper::areaOf2dTriangle(const Eigen::Vector2d &a, const Eigen::Vector2d &b, const Eigen::Vector2d &c)
{ {
return areaOf3dTriangle(QVector3D(a.x(), a.y(), 0), return areaOf3dTriangle(Eigen::Vector3d(a.x(), a.y(), 0),
QVector3D(b.x(), b.y(), 0), Eigen::Vector3d(b.x(), b.y(), 0),
QVector3D(c.x(), c.y(), 0)); Eigen::Vector3d(c.x(), c.y(), 0));
} }
void UvUnwrapper::calculateSizeAndRemoveInvalidCharts() void UvUnwrapper::calculateSizeAndRemoveInvalidCharts()
@ -347,19 +339,19 @@ void UvUnwrapper::calculateSizeAndRemoveInvalidCharts()
std::pair<float, float> size = {right - left, bottom - top}; std::pair<float, float> size = {right - left, bottom - top};
if (size.first <= 0 || std::isnan(size.first) || std::isinf(size.first) || if (size.first <= 0 || std::isnan(size.first) || std::isinf(size.first) ||
size.second <= 0 || std::isnan(size.second) || std::isinf(size.second)) { size.second <= 0 || std::isnan(size.second) || std::isinf(size.second)) {
qDebug() << "Found invalid chart size:" << size.first << "x" << size.second; //qDebug() << "Found invalid chart size:" << size.first << "x" << size.second;
continue; continue;
} }
float surfaceArea = 0; float surfaceArea = 0;
for (const auto &item: chart.first) { for (const auto &item: chart.first) {
const auto &face = m_mesh.faces[item]; const auto &face = m_mesh.faces[item];
surfaceArea += areaOf3dTriangle(QVector3D(m_mesh.vertices[face.indices[0]].xyz[0], surfaceArea += areaOf3dTriangle(Eigen::Vector3d(m_mesh.vertices[face.indices[0]].xyz[0],
m_mesh.vertices[face.indices[0]].xyz[1], m_mesh.vertices[face.indices[0]].xyz[1],
m_mesh.vertices[face.indices[0]].xyz[2]), m_mesh.vertices[face.indices[0]].xyz[2]),
QVector3D(m_mesh.vertices[face.indices[1]].xyz[0], Eigen::Vector3d(m_mesh.vertices[face.indices[1]].xyz[0],
m_mesh.vertices[face.indices[1]].xyz[1], m_mesh.vertices[face.indices[1]].xyz[1],
m_mesh.vertices[face.indices[1]].xyz[2]), m_mesh.vertices[face.indices[1]].xyz[2]),
QVector3D(m_mesh.vertices[face.indices[2]].xyz[0], Eigen::Vector3d(m_mesh.vertices[face.indices[2]].xyz[0],
m_mesh.vertices[face.indices[2]].xyz[1], m_mesh.vertices[face.indices[2]].xyz[1],
m_mesh.vertices[face.indices[2]].xyz[2])); m_mesh.vertices[face.indices[2]].xyz[2]));
} }
@ -369,25 +361,24 @@ void UvUnwrapper::calculateSizeAndRemoveInvalidCharts()
item.coords[i].uv[0] -= left; item.coords[i].uv[0] -= left;
item.coords[i].uv[1] -= top; item.coords[i].uv[1] -= top;
} }
uvArea += areaOf2dTriangle(QVector2D(item.coords[0].uv[0], item.coords[0].uv[1]), uvArea += areaOf2dTriangle(Eigen::Vector2d(item.coords[0].uv[0], item.coords[0].uv[1]),
QVector2D(item.coords[1].uv[0], item.coords[1].uv[1]), Eigen::Vector2d(item.coords[1].uv[0], item.coords[1].uv[1]),
QVector2D(item.coords[2].uv[0], item.coords[2].uv[1])); Eigen::Vector2d(item.coords[2].uv[0], item.coords[2].uv[1]));
} }
if (m_enableRotation) { if (m_enableRotation) {
QVector3D center(size.first * 0.5, size.second * 0.5, 0); Eigen::Vector3d center(size.first * 0.5, size.second * 0.5, 0);
float minRectArea = size.first * size.second; float minRectArea = size.first * size.second;
float minRectLeft = 0; float minRectLeft = 0;
float minRectTop = 0; float minRectTop = 0;
bool rotated = false; bool rotated = false;
float choosenDegree = 0;
for (const auto &degree: m_rotateDegrees) { for (const auto &degree: m_rotateDegrees) {
QMatrix4x4 matrix; Eigen::Matrix3d matrix;
matrix.rotate(degree, 0, 0, 1); matrix = Eigen::AngleAxisd(degree * 180.0 / 3.1415926, Eigen::Vector3d::UnitZ());
std::vector<FaceTextureCoords> rotatedUvs; std::vector<FaceTextureCoords> rotatedUvs;
for (auto &item: chart.second) { for (auto &item: chart.second) {
FaceTextureCoords rotatedCoords; FaceTextureCoords rotatedCoords;
for (int i = 0; i < 3; ++i) { for (int i = 0; i < 3; ++i) {
QVector3D point(item.coords[i].uv[0], item.coords[i].uv[1], 0); Eigen::Vector3d point(item.coords[i].uv[0], item.coords[i].uv[1], 0);
point -= center; point -= center;
point = matrix * point; point = matrix * point;
rotatedCoords.coords[i].uv[0] = point.x(); rotatedCoords.coords[i].uv[0] = point.x();
@ -404,13 +395,11 @@ void UvUnwrapper::calculateSizeAndRemoveInvalidCharts()
size = newSize; size = newSize;
minRectLeft = left; minRectLeft = left;
minRectTop = top; minRectTop = top;
choosenDegree = degree;
rotated = true; rotated = true;
chart.second = rotatedUvs; chart.second = rotatedUvs;
} }
} }
if (rotated) { if (rotated) {
//qDebug() << "Choosen degree:" << choosenDegree;
for (auto &item: chart.second) { for (auto &item: chart.second) {
for (int i = 0; i < 3; ++i) { for (int i = 0; i < 3; ++i) {
item.coords[i].uv[0] -= minRectLeft; item.coords[i].uv[0] -= minRectLeft;
@ -537,7 +526,7 @@ void UvUnwrapper::unwrapSingleIsland(const std::vector<size_t> &group, int sourc
decltype(localFaces.size()) faceNumBeforeFix = localFaces.size(); decltype(localFaces.size()) faceNumBeforeFix = localFaces.size();
size_t remainingHoleNumAfterFix = 0; size_t remainingHoleNumAfterFix = 0;
if (!fixHolesExceptTheLongestRing(localVertices, localFaces, &remainingHoleNumAfterFix)) { if (!fixHolesExceptTheLongestRing(localVertices, localFaces, &remainingHoleNumAfterFix)) {
qDebug() << "fixHolesExceptTheLongestRing failed"; //qDebug() << "fixHolesExceptTheLongestRing failed";
return; return;
} }
if (1 == remainingHoleNumAfterFix) { if (1 == remainingHoleNumAfterFix) {
@ -550,7 +539,7 @@ void UvUnwrapper::unwrapSingleIsland(const std::vector<size_t> &group, int sourc
std::vector<size_t> secondGroup; std::vector<size_t> secondGroup;
makeSeamAndCut(localVertices, localFaces, localToGlobalFacesMap, firstGroup, secondGroup); makeSeamAndCut(localVertices, localFaces, localToGlobalFacesMap, firstGroup, secondGroup);
if (firstGroup.empty() || secondGroup.empty()) { if (firstGroup.empty() || secondGroup.empty()) {
qDebug() << "Cut mesh failed"; //qDebug() << "Cut mesh failed";
return; return;
} }
unwrapSingleIsland(firstGroup, sourcePartition, true); unwrapSingleIsland(firstGroup, sourcePartition, true);

View File

@ -2,10 +2,8 @@
#define SIMPLEUV_UV_UNWRAPPER_H #define SIMPLEUV_UV_UNWRAPPER_H
#include <vector> #include <vector>
#include <map> #include <map>
#include <QRectF>
#include <simpleuv/meshdatatype.h> #include <simpleuv/meshdatatype.h>
#include <QVector3D> #include <Eigen/Dense>
#include <QVector2D>
namespace simpleuv namespace simpleuv
{ {
@ -16,7 +14,7 @@ public:
void setMesh(const Mesh &mesh); void setMesh(const Mesh &mesh);
void unwrap(); void unwrap();
const std::vector<FaceTextureCoords> &getFaceUvs() const; const std::vector<FaceTextureCoords> &getFaceUvs() const;
const std::vector<QRectF> &getChartRects() const; const std::vector<Rect> &getChartRects() const;
const std::vector<int> &getChartSourcePartitions() const; const std::vector<int> &getChartSourcePartitions() const;
float textureSize() const; float textureSize() const;
@ -40,9 +38,8 @@ 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); float areaOf3dTriangle(const Eigen::Vector3d &a, const Eigen::Vector3d &b, const Eigen::Vector3d &c);
float areaOf3dTriangle(const QVector3D &a, const QVector3D &b, const QVector3D &c); float areaOf2dTriangle(const Eigen::Vector2d &a, const Eigen::Vector2d &b, const Eigen::Vector2d &c);
float areaOf2dTriangle(const QVector2D &a, const QVector2D &b, const QVector2D &c);
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,
@ -54,7 +51,7 @@ private:
std::vector<std::pair<std::vector<size_t>, std::vector<FaceTextureCoords>>> m_charts; std::vector<std::pair<std::vector<size_t>, std::vector<FaceTextureCoords>>> m_charts;
std::vector<std::pair<float, float>> m_chartSizes; std::vector<std::pair<float, float>> m_chartSizes;
std::vector<std::pair<float, float>> m_scaledChartSizes; std::vector<std::pair<float, float>> m_scaledChartSizes;
std::vector<QRectF> m_chartRects; std::vector<Rect> m_chartRects;
std::vector<int> m_chartSourcePartitions; std::vector<int> m_chartSourcePartitions;
bool m_segmentByNormal = true; bool m_segmentByNormal = true;
float m_segmentDotProductThreshold = 0.0; //90 degrees float m_segmentDotProductThreshold = 0.0; //90 degrees