ui rework
This commit is contained in:
parent
b6b07e3260
commit
36891b7589
23
src/main.cpp
23
src/main.cpp
@ -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();
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
@ -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);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
Loading…
Reference in New Issue
Block a user