ui rework

This commit is contained in:
papush! 2021-11-25 14:59:13 +01:00
parent b6b07e3260
commit 36891b7589
6 changed files with 142 additions and 75 deletions

View File

@ -5,6 +5,22 @@
#include <QApplication> #include <QApplication>
static MeshProcessor *create_mesh_processor(const QString &path,
MainWindow &main_window) {
MeshViewer &mesh_viewer = main_window.mesh_viewer;
MeshProcessor *mesh_processor = new MeshProcessor(path, mesh_viewer);
QObject::connect(&main_window, &MainWindow::fillHolesDumbClicked,
mesh_processor, &MeshProcessor::fillHolesDumb);
QObject::connect(&main_window, &MainWindow::fillHolesImplicitClicked,
mesh_processor, &MeshProcessor::fillHolesImplicit);
QObject::connect(&main_window, &MainWindow::smoothClicked,
mesh_processor, &MeshProcessor::smooth);
QObject::connect(&main_window, &MainWindow::patchViewToggled,
mesh_processor, &MeshProcessor::setPatchView);
return mesh_processor;
}
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
using namespace std; using namespace std;
QSurfaceFormat format; QSurfaceFormat format;
@ -17,18 +33,17 @@ int main(int argc, char *argv[]) {
QApplication app(argc, argv); QApplication app(argc, argv);
MeshProcessor *mesh_processor = nullptr; MeshProcessor *mesh_processor = nullptr;
MainWindow main_window; MainWindow main_window;
MeshViewer *mesh_viewer = &main_window.mesh_viewer;
if (argc > 2) { if (argc > 2) {
qWarning("Utilisation: %s [MAILLAGE]", argv[0]); qWarning("Utilisation: %s [MAILLAGE]", argv[0]);
return 1; return 1;
} else if (argc == 2) { } else if (argc == 2) {
mesh_processor = new MeshProcessor(argv[1], *mesh_viewer); mesh_processor = create_mesh_processor(argv[1], main_window);
} }
QObject::connect(&main_window, &MainWindow::open, QObject::connect(&main_window, &MainWindow::open,
[&](const QString &path) { [&](const QString &path) {
if (mesh_processor) delete mesh_processor; if (mesh_processor) delete mesh_processor;
mesh_processor = new MeshProcessor(path, mesh_processor = create_mesh_processor
*mesh_viewer); (path, main_window);
}); });
main_window.show(); main_window.show();
return app.exec(); return app.exec();

View File

@ -3,20 +3,21 @@
#include <QApplication> #include <QApplication>
#include <QFileDialog> #include <QFileDialog>
#include <QMenuBar>
#include <QGroupBox>
#include <QPushButton>
MainWindow::MainWindow(QWidget *parent) MainWindow::MainWindow(QWidget *parent)
:QMainWindow(parent), :QMainWindow(parent),
toolbar(this), toolbar(this),
mesh_viewer() { mesh_viewer() {
connect(&mesh_viewer, &MeshViewer::initialized, [&]() {
open_action->setEnabled(true);
});
setCentralWidget(&mesh_viewer); setCentralWidget(&mesh_viewer);
addToolBar(Qt::RightToolBarArea, &toolbar); // addToolBar(Qt::RightToolBarArea, &toolbar);
open_action = toolbar.addAction("Ouvrir…", [&](){
emit open(QFileDialog::getOpenFileName(this, "Ouvrir un maillage")); // open_action = toolbar.addAction("Ouvrir…", [&](){
}); // emit open(QFileDialog::getOpenFileName(this, "Ouvrir un maillage"));
// });
// toolbar_actions.append(toolbar.addAction("Fractionner", [&](){ // toolbar_actions.append(toolbar.addAction("Fractionner", [&](){
// QVector<QPair<MyMesh::Point, MyMesh>> fragments = shatter(mesh); // QVector<QPair<MyMesh::Point, MyMesh>> fragments = shatter(mesh);
// mesh_viewer.removeOpenGLMesh(glm); // mesh_viewer.removeOpenGLMesh(glm);
@ -28,8 +29,62 @@ MainWindow::MainWindow(QWidget *parent)
// mesh_viewer.addOpenGLMeshFromOpenMesh(&fragment, mat); // mesh_viewer.addOpenGLMeshFromOpenMesh(&fragment, mat);
// } // }
// })); // }));
open_action->setEnabled(false);
for (QAction *a : toolbar_actions) { QMenuBar *menu_bar = new QMenuBar();
a->setEnabled(false); setMenuBar(menu_bar);
// File menu
QMenu *file_menu = new QMenu("Fichier");
open_action = file_menu->addAction("Ouvrir…", [&](){
emit open(QFileDialog::getOpenFileName(this, "Ouvrir un maillage"));
});
save_action = file_menu->addAction("Enregistrer sous…", [&]() {
emit save(QFileDialog::getSaveFileName(this,
"Enregistrer un maillage"));
});
menu_bar->addMenu(file_menu);
if (!mesh_viewer.isInitialized()) {
open_action->setEnabled(false);
connect(&mesh_viewer, &MeshViewer::initialized, [&]() {
open_action->setEnabled(true);
});
} }
addToolBar(Qt::RightToolBarArea, &toolbar);
// Hole filling tools
QGroupBox *hole_box = new QGroupBox("Remplissage de trous");
QLayout *hole_vbox = new QVBoxLayout();
hole_box->setLayout(hole_vbox);
QPushButton *fill_holes_dumb = new QPushButton("Remplir bêtement");
connect(fill_holes_dumb, &QPushButton::clicked,
this, &MainWindow::fillHolesDumbClicked);
hole_vbox->addWidget(fill_holes_dumb);
QPushButton *fill_holes_implicit = new QPushButton("Remplir bêtement");
connect(fill_holes_implicit, &QPushButton::clicked,
this, &MainWindow::fillHolesImplicitClicked);
hole_vbox->addWidget(fill_holes_implicit);
toolbar.addWidget(hole_box);
// Smoothing tools
QGroupBox *smooth_box = new QGroupBox("Adoucissement");
QLayout *smooth_vbox = new QVBoxLayout();
smooth_box->setLayout(smooth_vbox);
QPushButton *smooth = new QPushButton("Adoucir");
connect(smooth, &QPushButton::clicked,
this, &MainWindow::smoothClicked);
smooth_vbox->addWidget(smooth);
toolbar.addWidget(smooth_box);
// Curvature tools
QGroupBox *curvature_box = new QGroupBox("Analyse de courbure");
QLayout *curvature_vbox = new QVBoxLayout();
curvature_box->setLayout(curvature_vbox);
QPushButton *patch_mode = new QPushButton(
"Afficher le patch de la sélection");
patch_mode->setCheckable(true);
connect(patch_mode, &QPushButton::toggled,
this, &MainWindow::patchViewToggled);
curvature_vbox->addWidget(patch_mode);
toolbar.addWidget(curvature_box);
} }

View File

@ -3,6 +3,7 @@
#include <QMainWindow> #include <QMainWindow>
#include <QToolBar> #include <QToolBar>
#include <QVBoxLayout>
#include "mesh_viewer.h" #include "mesh_viewer.h"
#include "my_mesh.h" #include "my_mesh.h"
@ -13,10 +14,15 @@ class MainWindow : public QMainWindow {
QToolBar toolbar; QToolBar toolbar;
QAction *open_action; QAction *open_action;
QList<QAction *> toolbar_actions; QAction *save_action;
signals: signals:
void open(const QString &path); void open(const QString &path);
void save(const QString &path);
void fillHolesDumbClicked();
void fillHolesImplicitClicked();
void smoothClicked();
void patchViewToggled(bool checked);
public: public:
MeshViewer mesh_viewer; MeshViewer mesh_viewer;

View File

@ -1,31 +1,13 @@
#include "quad_patch_tesselator.h" #include "quad_patch_tesselator.h"
#include "mesh_processor.h" #include "mesh_processor.h"
#include "util.h" #include "util.h"
#include "hole_filling.h"
#include "smoothing.h" #include "smoothing.h"
#include "curvature.h" #include "curvature.h"
#include <QGenericMatrix> #include <QGenericMatrix>
#include <unordered_set> #include <unordered_set>
static std::vector<std::vector<HalfedgeHandle>> findHoles(MyMesh &mesh) {
std::vector<std::vector<HalfedgeHandle>> holes;
std::set<HalfedgeHandle> ignore;
for (HalfedgeHandle it : mesh.halfedges()) {
if (mesh.is_boundary(it)
&& ignore.find(it) == ignore.end()) {
holes.emplace_back();
holes.back().push_back(it);
ignore.insert(it);
for (HalfedgeHandle it2 : HalfedgeLoopRange<MyMesh>(mesh, it)) {
holes.back().push_back(it2);
ignore.insert(it2);
}
}
}
return holes;
}
MeshProcessor::MeshProcessor(const QString &path, MeshViewer &mesh_viewer) MeshProcessor::MeshProcessor(const QString &path, MeshViewer &mesh_viewer)
:mesh_viewer(mesh_viewer) { :mesh_viewer(mesh_viewer) {
OpenMesh::IO::Options options; OpenMesh::IO::Options options;
@ -34,65 +16,68 @@ MeshProcessor::MeshProcessor(const QString &path, MeshViewer &mesh_viewer)
qWarning() << "Failed to read" << path; qWarning() << "Failed to read" << path;
return; return;
} }
mesh.update_normals(); for (VertexHandle vh : mesh.vertices()) {
// courbure = new Courbures(mesh); mesh.set_color(vh, MyMesh::Color(.5, .5, .5));
// courbure->compute_KH(); }
// courbure->set_K_colors(); courbure = new Courbures(mesh);
mesh.holes = findHoles(mesh); try {
fillHoles(); courbure->compute_KH();
// smooth(mesh); courbure->set_K_colors();
if (mesh_viewer.isInitialized()) { } catch (std::runtime_error &e) {
mesh_viewer.addMesh(mesh); qWarning() << "Curvature computation failed";
} else {
connect(&mesh_viewer, &MeshViewer::initialized,
[&]() { mesh_viewer.addMesh(mesh); });
} }
connect(&mesh_viewer, &MeshViewer::clicked, this, &MeshProcessor::click); connect(&mesh_viewer, &MeshViewer::clicked, this, &MeshProcessor::click);
updateView();
} }
MeshProcessor::~MeshProcessor() { MeshProcessor::~MeshProcessor() {
if (mesh_viewer.isInitialized()) { if (mesh_viewer.isInitialized()) {
mesh_viewer.removeMesh(mesh); mesh_viewer.removeMesh(mesh);
} else {
connect(&mesh_viewer, &MeshViewer::initialized,
[&]() { mesh_viewer.removeMesh(mesh); });
} }
if (courbure) delete courbure; if (courbure) delete courbure;
} }
void fillHoleDumb(MyMesh &mesh, std::vector<HalfedgeHandle> &hole) { void MeshProcessor::updateView() const {
mesh.request_vertex_status(); if (mesh_viewer.isInitialized()) {
mesh.request_edge_status(); mesh_viewer.removeMesh(mesh);
mesh.request_face_status(); mesh_viewer.addMesh(mesh);
mesh_viewer.updateForReal();
Point center(0, 0, 0); } else {
size_t length = 0; connect(&mesh_viewer, &MeshViewer::initialized, [&]() {
for (HalfedgeHandle it : hole) { mesh_viewer.addMesh(mesh);
VertexHandle vert = mesh.to_vertex_handle(it); mesh_viewer.updateForReal();
center += mesh.point(vert); });
length++;
}
center /= length;
VertexHandle center_handle = mesh.new_vertex_dirty(center);
for (HalfedgeHandle it : hole) {
mesh.add_face(mesh.from_vertex_handle(it),
mesh.to_vertex_handle(it),
center_handle);
} }
} }
void MeshProcessor::fillHoles() { void MeshProcessor::fillHolesDumb() {
for (auto hole : mesh.holes) { ::fillHolesDumb(mesh);
fillHoleDumb(mesh, hole); updateView();
} }
void MeshProcessor::fillHolesImplicit() {
::fillHolesImplicit(mesh);
updateView();
}
void MeshProcessor::smooth() {
::smooth(mesh);
updateView();
}
void MeshProcessor::setPatchView(bool on) {
view_patches = on;
} }
void MeshProcessor::click(QVector3D position) { void MeshProcessor::click(QVector3D position) {
if (!view_patches) return;
Eigen::Vector3d pos {position.x(), position.y(), position.z()}; Eigen::Vector3d pos {position.x(), position.y(), position.z()};
MyMesh::VertexIter it = mesh.vertices_begin(); MyMesh::VertexIter it = mesh.vertices_begin();
VertexHandle min_vert = *it; VertexHandle min_vert = *it;

View File

@ -13,6 +13,9 @@ class MeshProcessor : public QObject {
Courbures *courbure = nullptr; Courbures *courbure = nullptr;
MeshViewer &mesh_viewer; MeshViewer &mesh_viewer;
bool view_patches = false;
void updateView() const;
public: public:
MyMesh mesh; MyMesh mesh;
@ -22,7 +25,10 @@ public:
~MeshProcessor(); ~MeshProcessor();
public slots: public slots:
void fillHoles(); void fillHolesDumb();
void fillHolesImplicit();
void smooth();
void setPatchView(bool on);
void click(QVector3D position); void click(QVector3D position);
}; };

View File

@ -17,14 +17,14 @@ struct MyTraits : public OpenMesh::DefaultTraits {
VertexAttributes(OpenMesh::Attributes::Normal | OpenMesh::Attributes::Color); VertexAttributes(OpenMesh::Attributes::Normal | OpenMesh::Attributes::Color);
HalfedgeAttributes(OpenMesh::Attributes::PrevHalfedge); HalfedgeAttributes(OpenMesh::Attributes::PrevHalfedge);
FaceAttributes(OpenMesh::Attributes::Normal); FaceAttributes(OpenMesh::Attributes::Normal);
EdgeAttributes(OpenMesh::Attributes::Color); // EdgeAttributes(OpenMesh::Attributes::Color);
}; };
class MyMesh : public OpenMesh::TriMesh_ArrayKernelT<MyTraits> { class MyMesh : public OpenMesh::TriMesh_ArrayKernelT<MyTraits> {
public: public:
Color default_color {.5, .5, .5};
QMatrix4x4 transform; QMatrix4x4 transform;
std::vector<std::vector<HalfedgeHandle>> holes; std::vector<std::vector<HalfedgeHandle>> holes;
// QColor color = {127, 127, 127};
}; };
typedef MyMesh::FaceHandle FaceHandle; typedef MyMesh::FaceHandle FaceHandle;