Use Eigen to do vector math on UV
parent
b840482050
commit
dacff70eaa
|
@ -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
|
||||||
|
|
|
@ -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});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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
|
||||||
|
|
|
@ -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++) {
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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 °ree: m_rotateDegrees) {
|
for (const auto °ree: 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);
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue