Skip to content

Commit

Permalink
Prepare for 1.0.0-beta.3
Browse files Browse the repository at this point in the history
- Remesh isolated meshes separately
- Improve quad extractor
- Add edge scaling setting for generating low poly
- Add rough progress reporting (Windows only)
- Generate quad dominated mesh
  • Loading branch information
huxingyi committed Sep 24, 2020
1 parent a44aeb7 commit e0cf976
Show file tree
Hide file tree
Showing 8 changed files with 533 additions and 265 deletions.
7 changes: 7 additions & 0 deletions CHANGELOGS.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
1.0.0-beta.3
- Remesh isolated meshes separately
- Improve quad extractor
- Add edge scaling setting for generating low poly
- Add rough progress reporting (Windows only)
- Generate quad dominated mesh

1.0.0-beta.2
- Fix holes
- Replace Poly budget with density setting
Expand Down
3 changes: 0 additions & 3 deletions autoremesher.pro
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,6 @@ QT += core widgets opengl network
win32 {
QT += winextras
}

DEFINES += AUTO_REMESHER_DEV

CONFIG += release
CONFIG(release, debug|release) DEFINES += NDEBUG
DEFINES += AUTO_REMESHER_DEBUG
Expand Down
32 changes: 5 additions & 27 deletions src/AutoRemesher/autoremesher.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -325,39 +325,17 @@ bool AutoRemesher::remesh()
m_remeshedVertices.push_back(it);
}
for (const auto &it: quads) {
m_remeshedQuads.push_back({
vertexStartIndex + it[0],
vertexStartIndex + it[1],
vertexStartIndex + it[2],
vertexStartIndex + it[3]
});
std::vector<size_t> quad;
quad.reserve(it.size());
for (const auto &v: it)
quad.push_back(vertexStartIndex + v);
m_remeshedQuads.push_back(quad);
}
}

#if AUTO_REMESHER_DEBUG
qDebug() << "Remesh done";
#endif
#if AUTO_REMESHER_DEV
{
FILE *fp = fopen("autoremesher-debug.obj", "wb");
for (size_t i = 0; i < m_remeshedVertices.size(); ++i) {
const auto &v = m_remeshedVertices[i];
fprintf(fp, "v %f %f %f\n", v.x(), v.y(), v.z());
}
for (size_t i = 0; i < m_remeshedQuads.size(); ++i) {
const auto &f = m_remeshedQuads[i];
fprintf(fp, "f %zu %zu %zu %zu\n",
1 + f[0],
1 + f[1],
1 + f[2],
1 + f[3]);
}
fclose(fp);
}
#endif
#if AUTO_REMESHER_DEBUG
qDebug() << "Remesh debug result saved";
#endif

if (nullptr != m_progressHandler)
m_progressHandler(m_tag, 1.0);
Expand Down
627 changes: 436 additions & 191 deletions src/AutoRemesher/quadextractor.cpp

Large diffs are not rendered by default.

24 changes: 13 additions & 11 deletions src/AutoRemesher/quadextractor.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ class QuadExtractor

const std::vector<std::vector<size_t>> &remeshedQuads()
{
return m_remeshedQuads;
return m_remeshedPolygons;
}

bool extract();
Expand All @@ -58,10 +58,11 @@ class QuadExtractor
const std::vector<std::vector<size_t>> *m_triangles = nullptr;
const std::vector<std::vector<Vector2>> *m_triangleUvs = nullptr;
std::vector<Vector3> m_remeshedVertices;
std::vector<std::vector<size_t>> m_remeshedQuads;
std::set<std::pair<size_t, size_t>> m_goodQuadHalfEdges;
std::unordered_set<size_t> m_tVertices;

std::vector<std::vector<size_t>> m_remeshedPolygons;
std::vector<std::vector<size_t>> m_triangleHoles;
std::set<std::pair<size_t, size_t>> m_halfEdges;
std::unordered_map<size_t, std::pair<size_t, size_t>> m_tVertices;

void extractConnections(std::vector<Vector3> *crossPoints,
std::vector<size_t> *sourceTriangles,
std::set<std::pair<size_t, size_t>> *connections);
Expand All @@ -81,19 +82,20 @@ class QuadExtractor
std::unordered_map<size_t, std::unordered_set<size_t>> &edgeConnectMap,
std::vector<std::vector<size_t>> *quads);
void simplifyGraph(std::unordered_map<size_t, std::unordered_set<size_t>> &graph);
void fixFlippedFaces();
bool removeIsolatedFaces();
bool removeNonManifoldFaces();
void makeTedge(const std::vector<size_t> &triangle);
void fixHoles();
void searchBoundaries(const std::set<std::pair<size_t, size_t>> &halfEdges,
std::vector<std::vector<size_t>> *loops);
void fixHoleWithQuads(std::vector<size_t> &hole, bool checkScore=true);
void recordGoodQuads();
bool testPointInTriangle(const std::vector<Vector3> &points,
const std::vector<size_t> &triangle,
const std::vector<size_t> &testPoints);
void connectTvertices();
void buildVertexNeighborMap(std::unordered_map<size_t, std::vector<size_t>> *vertexNeighborMap);
void connectTwoTvertices(size_t startVertex, const std::vector<size_t> &path);
bool connectTwoTvertices(size_t startVertex, const std::pair<size_t, size_t> &startHalfEdge,
size_t stopVertex, const std::pair<size_t, size_t> &stopHalfEdge,
const std::vector<size_t> &path);
void fixNonQuads();
void fixTriangleHoles();
};

}
Expand Down
18 changes: 17 additions & 1 deletion src/mainwindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@
#include <QTextStream>
#include <QFile>
#include <QComboBox>
#include <QLabel>
#include <QUuid>
#ifdef Q_OS_WIN32
#include <QWinTaskbarButton>
Expand Down Expand Up @@ -185,6 +184,18 @@ MainWindow::MainWindow()

//m_modelTypeSelectBox->setCurrentIndex(AutoRemesher::ModelType::HardSurface == m_modelType ? 1 : 0);

QLabel *edgeScalingLabel = new QLabel(tr("Edge scaling:"));

m_edgeScalingSelectBox = new QComboBox;
m_edgeScalingSelectBox->addItem(tr("1.0"));
m_edgeScalingSelectBox->addItem(tr("2.0"));
m_edgeScalingSelectBox->addItem(tr("3.0"));
m_edgeScalingSelectBox->addItem(tr("4.0"));
m_edgeScalingSelectBox->setCurrentIndex((int)m_targetScaling - 1);
connect(m_edgeScalingSelectBox, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, [&](int index) {
m_targetScaling = (float)(index + 1);
});

SpinnableAwesomeButton *loadModelButton = new SpinnableAwesomeButton();
loadModelButton->setAwesomeIcon(QChar(fa::folderopeno));
connect(loadModelButton->button(), &QPushButton::clicked, this, &MainWindow::loadModel);
Expand All @@ -200,6 +211,9 @@ MainWindow::MainWindow()

toolLayout->addStretch();
toolLayout->addWidget(m_targetTriangleCountWidget);
toolLayout->addSpacing(5);
toolLayout->addWidget(edgeScalingLabel);
toolLayout->addWidget(m_edgeScalingSelectBox);
//toolLayout->addWidget(m_targetScalingWidget);
//toolLayout->addWidget(m_modelTypeSelectBox);
toolLayout->addSpacing(10);
Expand Down Expand Up @@ -247,6 +261,7 @@ void MainWindow::updateButtonStates()
m_loadModelButton->showSpinner(false);
//m_targetScalingWidget->setEnabled(true);
m_targetTriangleCountWidget->setEnabled(true);
m_edgeScalingSelectBox->setEnabled(true);
//m_modelTypeSelectBox->setEnabled(true);
if (nullptr != m_remeshedQuads) {
m_saveMeshButton->show();
Expand All @@ -258,6 +273,7 @@ void MainWindow::updateButtonStates()
m_saveMeshButton->hide();
//m_targetScalingWidget->setDisabled(true);
m_targetTriangleCountWidget->setDisabled(true);
m_edgeScalingSelectBox->setDisabled(true);
//m_modelTypeSelectBox->setDisabled(true);
}
}
Expand Down
5 changes: 3 additions & 2 deletions src/mainwindow.h
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ private slots:
bool m_inProgress = false;
bool m_saved = true;
float m_targetDensity = 0.0;
float m_targetScaling = 3.0;
float m_targetScaling = 2.0;
AutoRemesher::ModelType m_modelType = AutoRemesher::ModelType::Organic;
std::vector<AutoRemesher::Vector3> m_originalVertices;
std::vector<std::vector<size_t>> m_originalTriangles;
Expand All @@ -96,7 +96,8 @@ private slots:
SpinnableAwesomeButton *m_saveMeshButton = nullptr;
FloatNumberWidget *m_targetTriangleCountWidget = nullptr;
FloatNumberWidget *m_targetScalingWidget = nullptr;
QComboBox *m_modelTypeSelectBox = nullptr;
//QComboBox *m_modelTypeSelectBox = nullptr;
QComboBox *m_edgeScalingSelectBox = nullptr;
#ifdef Q_OS_WIN32
QWinTaskbarButton *m_taskbarButton = nullptr;
#endif
Expand Down
82 changes: 52 additions & 30 deletions src/rendermeshgenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,17 +83,29 @@ void RenderMeshGenerator::generate()
normalizeVertices();

std::vector<AutoRemesher::Vector3> vertexNormals(m_vertices->size());
std::vector<AutoRemesher::Vector3> faceCenters(m_faces->size());
std::vector<AutoRemesher::Vector3> faceNormals(m_faces->size());
for (size_t i = 0; i < m_faces->size(); ++i) {
const auto &sourceFace = (*m_faces)[i];
auto normal = AutoRemesher::Vector3::normal((*m_vertices)[sourceFace[0]],
(*m_vertices)[sourceFace[1]],
(*m_vertices)[sourceFace[2]]);
if (sourceFace.size() == 4) {
normal += AutoRemesher::Vector3::normal((*m_vertices)[sourceFace[2]],
(*m_vertices)[sourceFace[3]],
(*m_vertices)[sourceFace[0]]);
normal.normalize();

AutoRemesher::Vector3 center;
for (const auto &it: sourceFace) {
center += (*m_vertices)[it];
}
center /= sourceFace.size();
faceCenters[i] = center;

AutoRemesher::Vector3 normal;
for (size_t corner = 0; corner < sourceFace.size(); ++corner) {
size_t nextCorner = (corner + 1) % sourceFace.size();
normal += AutoRemesher::Vector3::normal(center,
(*m_vertices)[sourceFace[corner]],
(*m_vertices)[sourceFace[nextCorner]]);
}
normal.normalize();

faceNormals[i] = normal;

for (size_t j = 0; j < sourceFace.size(); ++j)
vertexNormals[sourceFace[j]] += normal;
}
Expand All @@ -104,13 +116,11 @@ void RenderMeshGenerator::generate()
int edgeVertexCount = 0;
for (size_t i = 0; i < m_faces->size(); ++i) {
const auto &sourceFace = (*m_faces)[i];
if (sourceFace.size() == 4) {
vertexNum += 6;
edgeVertexCount += 12;
} else if (sourceFace.size() == 3) {
if (3 == sourceFace.size())
vertexNum += 3;
edgeVertexCount += 6;
}
else
vertexNum += sourceFace.size() * 3;
edgeVertexCount += sourceFace.size() * 2;
}
PbrShaderVertex *triangleVertices = new PbrShaderVertex[vertexNum];
PbrShaderVertex *edgeVertices = new PbrShaderVertex[edgeVertexCount];
Expand All @@ -121,12 +131,14 @@ void RenderMeshGenerator::generate()
vertexNum = 0;
edgeVertexCount = 0;

auto addTriangle = [&](const std::vector<size_t> &sourceFace, size_t startIndex) {
for (size_t j = 0; j < 3; ++j) {
auto addTriangle = [&](const std::vector<size_t> &sourceFace,
size_t startIndex,
const AutoRemesher::Vector3 &normal,
const AutoRemesher::Vector3 &center) {
for (size_t j = 0; j < 2; ++j) {
auto &v = triangleVertices[vertexNum++];
auto index = sourceFace[(startIndex + j) % sourceFace.size()];
const auto &src = (*m_vertices)[index];
const auto &normal = vertexNormals[index];
v.posX = (float)src.x();
v.posY = (float)src.y();
v.posZ = (float)src.z();
Expand All @@ -139,6 +151,19 @@ void RenderMeshGenerator::generate()
v.roughness = 1.0f;
v.alpha = 1.0f;
}

auto &v = triangleVertices[vertexNum++];
v.posX = (float)center.x();
v.posY = (float)center.y();
v.posZ = (float)center.z();
v.normX = (float)normal.x();
v.normY = (float)normal.y();
v.normZ = (float)normal.z();
v.colorR = 1.0f;
v.colorG = 1.0f;
v.colorB = 1.0f;
v.roughness = 1.0f;
v.alpha = 1.0f;
};

auto addEdge = [&](const std::vector<size_t> &sourceFace, size_t startIndex) {
Expand All @@ -163,19 +188,16 @@ void RenderMeshGenerator::generate()

for (size_t i = 0; i < m_faces->size(); ++i) {
const auto &sourceFace = (*m_faces)[i];
if (sourceFace.size() == 4) {
addTriangle(sourceFace, 0);
addEdge(sourceFace, 0);
addEdge(sourceFace, 1);

addTriangle(sourceFace, 2);
addEdge(sourceFace, 2);
addEdge(sourceFace, 3);
} else if (sourceFace.size() == 3) {
addTriangle(sourceFace, 0);
addEdge(sourceFace, 0);
addEdge(sourceFace, 1);
addEdge(sourceFace, 2);
if (sourceFace.size() == 3) {
for (size_t j = 0; j < sourceFace.size(); ++j) {
addEdge(sourceFace, j);
}
addTriangle(sourceFace, 0, faceNormals[i], (*m_vertices)[sourceFace[2]]);
continue;
}
for (size_t j = 0; j < sourceFace.size(); ++j) {
addEdge(sourceFace, j);
addTriangle(sourceFace, j, faceNormals[i], faceCenters[i]);
}
}

Expand Down

0 comments on commit e0cf976

Please sign in to comment.