break everything

This commit is contained in:
papush! 2021-10-02 20:47:02 +02:00
parent 63074306c2
commit d74f80530b
16 changed files with 338 additions and 169 deletions

View File

@ -1,16 +1,39 @@
#include "main_window.h" #include "main_window.h"
#include "mesh_processor.h"
#include <iostream> #include <iostream>
#include <QSurfaceFormat>
#include <QApplication> #include <QApplication>
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
using namespace std; using namespace std;
QSurfaceFormat format;
format.setRenderableType(QSurfaceFormat::RenderableType::OpenGL);
format.setMajorVersion(2);
format.setMinorVersion(1);
QSurfaceFormat::setDefaultFormat(format);
QApplication app(argc, argv); QApplication app(argc, argv);
MeshProcessor *mesh_processor = nullptr;
MainWindow main_window;
MeshViewer *mesh_viewer = &main_window.mesh_viewer;
QObject::connect(mesh_viewer, &MeshViewer::initialized,
[&]() {
if (mesh_processor) {
mesh_viewer->addMesh(mesh_processor->mesh);
}
});
if (argc > 2) { if (argc > 2) {
cerr << "Utilisation: " << argv[0] << " [fichier OBJ]" << endl; qWarning("Utilisation: %s [MAILLAGE]", argv[0]);
return 1; return 1;
} else if (argc == 2) {
mesh_processor = new MeshProcessor(argv[1]);
} }
MainWindow mw; // QObject::connect(&main_window, &MainWindow::open,
mw.show(); // [&](const QString &path) {
// if (mesh_processor) delete mesh_processor;
// mesh_processor = new MeshProcessor(path);
// });
main_window.show();
return app.exec(); return app.exec();
} }

View File

@ -1,5 +1,5 @@
#include "main_window.h" #include "main_window.h"
#include "mesh_processing.h" #include "mesh_processor.h"
#include <QApplication> #include <QApplication>
#include <QFileDialog> #include <QFileDialog>
@ -13,7 +13,7 @@ MainWindow::MainWindow(QWidget *parent)
setCentralWidget(&mesh_viewer); setCentralWidget(&mesh_viewer);
addToolBar(Qt::RightToolBarArea, &toolbar); addToolBar(Qt::RightToolBarArea, &toolbar);
open_action = toolbar.addAction("Ouvrir…", [&](){ open_action = toolbar.addAction("Ouvrir…", [&](){
open(QFileDialog::getOpenFileName(this, "Ouvrir un fichier OBJ")); 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);
@ -33,33 +33,6 @@ MainWindow::MainWindow(QWidget *parent)
} }
void MainWindow::open(const QString &path) {
OpenMesh::IO::Options options;
options.set(OpenMesh::IO::Options::VertexColor);
if (!OpenMesh::IO::read_mesh(mesh, path.toUtf8().constData(), options)) {
qWarning() << "Failed to read" << path;
return;
}
for (const VertexHandle &vh : mesh.vertices()) {
mesh.set_color(vh, MyMesh::Color(0, 0, 0));
}
for (HalfedgeHandle border : findBorders(mesh)) {
setBorderColor(mesh, border, {1, 0, 0});
fillHoleDumb(mesh, border);
}
if (glm != nullptr) mesh_viewer.removeOpenGLMesh(glm);
glm = mesh_viewer.addOpenGLMeshFromOpenMesh(&mesh);
for (QAction *a : toolbar_actions) {
a->setEnabled(true);
}
}
void MainWindow::meshViewerInitialized() { void MainWindow::meshViewerInitialized() {
if (qApp->arguments().size() == 2) {
open(qApp->arguments().at(1));
}
open_action->setEnabled(true); open_action->setEnabled(true);
} }

View File

@ -11,21 +11,20 @@
class MainWindow : public QMainWindow { class MainWindow : public QMainWindow {
Q_OBJECT Q_OBJECT
public:
MainWindow(QWidget *parent=nullptr);
void open(const QString &path);
private slots:
void meshViewerInitialized();
private:
MyMesh mesh;
MeshViewer mesh_viewer;
OpenGLMesh *glm = nullptr;
QToolBar toolbar; QToolBar toolbar;
QAction *open_action; QAction *open_action;
QList<QAction *> toolbar_actions; QList<QAction *> toolbar_actions;
private slots:
void meshViewerInitialized();
signals:
void open(const QString &path);
public:
MeshViewer mesh_viewer;
MainWindow(QWidget *parent=nullptr);
}; };

View File

@ -1,4 +1,5 @@
#include "mesh_processing.h" #include "mesh_processing.h"
#include "util.h"
#include <QGenericMatrix> #include <QGenericMatrix>
#include <unordered_set> #include <unordered_set>

View File

@ -1,17 +0,0 @@
#ifndef MESH_PROCESSING_H
#define MESH_PROCESSING_H
#include "my_mesh.h"
#include <vector>
std::vector<HalfedgeHandle> findBorders(MyMesh &mesh);
void setBorderColor(MyMesh &mesh, const HalfedgeHandle &border,
MyMesh::Color color);
void fillHoleDumb(MyMesh &mesh, HalfedgeHandle &border);
#endif

84
src/mesh_processor.cpp Normal file
View File

@ -0,0 +1,84 @@
#include "mesh_processor.h"
#include "util.h"
#include <QGenericMatrix>
#include <unordered_set>
static std::vector<HalfedgeHandle> findHoles(MyMesh &mesh) {
std::vector<HalfedgeHandle> holes;
std::set<HalfedgeHandle> ignore;
for (HalfedgeHandle it : mesh.halfedges()) {
if (mesh.is_boundary(it)
&& ignore.find(it) == ignore.end()) {
holes.push_back(it);
ignore.insert(it);
for (HalfedgeHandle it2 : HalfedgeLoopRange(mesh, it)) {
ignore.insert(it2);
}
}
}
return holes;
}
MeshProcessor::MeshProcessor(const QString &path) {
OpenMesh::IO::Options options;
options.set(OpenMesh::IO::Options::VertexColor);
if (!OpenMesh::IO::read_mesh(mesh, path.toUtf8().constData(), options)) {
qWarning() << "Failed to read" << path;
return;
}
for (const VertexHandle &vh : mesh.vertices()) {
mesh.set_color(vh, MyMesh::Color(0, 0, 0));
}
holes = findHoles(mesh);
highlightHoles();
fillHoles();
}
static void setHoleBoundaryColor(MyMesh &mesh,
const HalfedgeHandle &hole,
MyMesh::Color color) {
for (HalfedgeHandle it : HalfedgeLoopRange(mesh, hole)) {
mesh.set_color(mesh.to_vertex_handle(it), color);
}
}
void MeshProcessor::highlightHoles() {
for (auto hole : holes) {
setHoleBoundaryColor(mesh, hole, {1, 0, 0});
}
}
void fillHoleDumb(MyMesh &mesh, HalfedgeHandle &hole) {
mesh.request_vertex_status();
mesh.request_edge_status();
mesh.request_face_status();
Point center(0, 0, 0);
size_t length = 0;
for (HalfedgeHandle it : HalfedgeLoopRange(mesh, hole)) {
VertexHandle vert = mesh.to_vertex_handle(it);
center += mesh.point(vert);
length++;
}
center /= length;
VertexHandle center_handle = mesh.new_vertex_dirty(center);
for (HalfedgeHandle it = hole;
mesh.to_vertex_handle(it) != center_handle;) {
HalfedgeHandle next = mesh.next_halfedge_handle(it);
mesh.add_face(mesh.from_vertex_handle(it),
mesh.to_vertex_handle(it),
center_handle);
it = next;
}
}
void MeshProcessor::fillHoles() {
for (auto hole : holes) {
fillHoleDumb(mesh, hole);
}
}

28
src/mesh_processor.h Normal file
View File

@ -0,0 +1,28 @@
#ifndef MESH_PROCESSING_H
#define MESH_PROCESSING_H
#include "my_mesh.h"
#include "mesh_processor_painter.h"
#include <vector>
#include <QObject>
class MeshProcessor : public QObject {
Q_OBJECT
std::vector<HalfedgeHandle> holes;
// friend class MeshProcessorPainter;
public:
MyMesh mesh;
MeshProcessor(const QString &path);
public slots:
void highlightHoles();
void fillHoles();
};
#endif

View File

@ -0,0 +1,6 @@
#include "mesh_processor_painter.h"
void MeshProcessorPainter::paint() {
}

View File

@ -0,0 +1,15 @@
#ifndef MESH_PAINTER_H
#define MESH_PAINTER_H
#include <QObject>
class MeshProcessorPainter {
Q_OBJECT
public slots:
void paint();
};
#endif

73
src/mesh_view.cpp Normal file
View File

@ -0,0 +1,73 @@
#include "mesh_view.h"
#include <QOpenGLFunctions_2_1>
MeshView::MeshView(QOpenGLExtraFunctions *glf, const MyMesh &mesh,
int pos_attr, int col_attr)
: glf(glf),
mesh(mesh) {
GLfloat *verts = new GLfloat[mesh.n_faces() * 3 * 6];
size_t i = 0;
for (const FaceHandle face : mesh.faces()) {
for (const VertexHandle vec : mesh.fv_range(face)) {
verts[6*i + 0] = mesh.point(vec)[0];
verts[6*i + 1] = mesh.point(vec)[1];
verts[6*i + 2] = mesh.point(vec)[2];
verts[6*i + 3] = mesh.color.red();
verts[6*i + 4] = mesh.color.green();
verts[6*i + 5] = mesh.color.blue();
i++;
}
}
delete[] verts;
GLuint vao, vbo;
glf->glGenVertexArrays(1, &vao);
glf->glGenBuffers(1, &vbo);
glf->glBindVertexArray(vao);
glf->glBindBuffer(GL_ARRAY_BUFFER, vbo);
glf->glBufferData(GL_ARRAY_BUFFER, nverts * 6 * sizeof (GLfloat), verts, GL_DYNAMIC_DRAW);
glf->glVertexAttribPointer(pos_attr, 3, GL_FLOAT, GL_FALSE, 6 * sizeof (GLfloat), 0);
glf->glEnableVertexAttribArray(pos_attr);
glf->glVertexAttribPointer(col_attr, 3, GL_FLOAT, GL_FALSE, 6 * sizeof (GLfloat),
(const void *) (3 * sizeof (GLfloat)));
glf->glEnableVertexAttribArray(col_attr);
glf->glBindVertexArray(0);
}
MeshView::~MeshView() {
glf->glDeleteVertexArrays(1, &vao);
glf->glDeleteBuffers(1, &vbo);
}
void MeshView::paint(QOpenGLContext *ctx,
int model_attr, int wireframe_attr) const {
void (*glPolygonMode)(GLenum, GLenum) = nullptr;
glPolygonMode = (typeof glPolygonMode) ctx->getProcAddress("glPolygonMode");
if (!glPolygonMode)
qWarning("glPolygonMode not available");
glf->glUniformMatrix4fv(model_attr, 1, GL_FALSE,
mesh.transform.constData());
/* Mesh */
glf->glBindVertexArray(vao);
glf->glEnable(GL_POLYGON_OFFSET_FILL);
glf->glPolygonOffset(1.0, 2);
glf->glDrawArrays(GL_TRIANGLES, 0, nverts);
if (glPolygonMode) glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
glf->glDisable(GL_POLYGON_OFFSET_FILL);
/* Wireframe */
glf->glUniform1f(wireframe_attr, 1);
glf->glDrawArrays(GL_TRIANGLES, 0, nverts);
if (glPolygonMode) glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glf->glLineWidth(3);
glf->glUniform1f(wireframe_attr, 0);
}

26
src/mesh_view.h Normal file
View File

@ -0,0 +1,26 @@
#ifndef MESH_VIEW_H
#define MESH_VIEW_H
#include "my_mesh.h"
#include <QOpenGLExtraFunctions>
#include <QOpenGLContext>
class MeshView {
GLuint vao;
GLuint vbo;
size_t nverts;
QOpenGLExtraFunctions *glf;
public:
const MyMesh &mesh;
MeshView(QOpenGLExtraFunctions *glf, const MyMesh &mesh,
int pos_attr, int col_attr);
~MeshView();
void paint(QOpenGLContext *ctx,
int model_attr, int wireframe_attr) const;
};
#endif

View File

@ -1,7 +1,7 @@
#include "mesh_viewer.h" #include "mesh_viewer.h"
#include <tgmath.h> #include <tgmath.h>
#include <utility> #include <algorithm>
const GLchar *vertex_shader_source = R"glsl( const GLchar *vertex_shader_source = R"glsl(
@ -69,10 +69,9 @@ opengl_debug_cb(GLenum source,
void MeshViewer::initializeGL() { void MeshViewer::initializeGL() {
// initializeOpenGLFunctions(); // initializeOpenGLFunctions();
GLint major, minor; qDebug("OpenGL version %d.%d",
glGetIntegerv(GL_MAJOR_VERSION, &major); context()->format().majorVersion(),
glGetIntegerv(GL_MINOR_VERSION, &minor); context()->format().minorVersion());
qDebug("OpenGL version %d.%d", major, minor);
glEnable(GL_DEBUG_OUTPUT); glEnable(GL_DEBUG_OUTPUT);
glDebugMessageCallback(opengl_debug_cb, 0); glDebugMessageCallback(opengl_debug_cb, 0);
@ -138,6 +137,7 @@ void MeshViewer::initializeGL() {
glEnable(GL_DEPTH_TEST); glEnable(GL_DEPTH_TEST);
glEnable(GL_MULTISAMPLE); glEnable(GL_MULTISAMPLE);
qDebug("Mesh viewer initialized");
emit initialized(); emit initialized();
} }
@ -155,80 +155,28 @@ void MeshViewer::paintGL() {
trans.translate(0, 0, -cam_dist); trans.translate(0, 0, -cam_dist);
QMatrix4x4 view = trans * rot; QMatrix4x4 view = trans * rot;
glUniformMatrix4fv(view_attr, 1, GL_FALSE, view.data()); glUniformMatrix4fv(view_attr, 1, GL_FALSE, view.data());
for (const OpenGLMesh m : meshes) { for (const MeshView m : meshes) {
glUniformMatrix4fv(model_attr, 1, GL_FALSE, m.mat.data()); m.paint(context(), model_attr, wireframe_attr);
/* Mesh */
glBindVertexArray(m.vao);
glEnable(GL_POLYGON_OFFSET_FILL);
glPolygonOffset(1.0, 2);
glDrawArrays(GL_TRIANGLES, 0, m.nverts);
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
glDisable(GL_POLYGON_OFFSET_FILL);
/* Wireframe */
glUniform1f(wireframe_attr, 1);
glDrawArrays(GL_TRIANGLES, 0, m.nverts);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glLineWidth(3);
glUniform1f(wireframe_attr, 0);
} }
} }
OpenGLMesh *MeshViewer::addOpenGLMesh(size_t nverts, const GLfloat *verts, QMatrix4x4 mat, QColor col) { void MeshViewer::addMesh(const MyMesh &mesh) {
makeCurrent(); makeCurrent();
meshes.emplace_back(context()->extraFunctions(), mesh,
GLuint vao, vbo; pos_attr, col_attr);
glGenVertexArrays(1, &vao);
glGenBuffers(1, &vbo);
glBindVertexArray(vao);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, nverts * 6 * sizeof (GLfloat), verts, GL_DYNAMIC_DRAW);
glVertexAttribPointer(pos_attr, 3, GL_FLOAT, GL_FALSE, 6 * sizeof (GLfloat), 0);
glEnableVertexAttribArray(pos_attr);
glVertexAttribPointer(col_attr, 3, GL_FLOAT, GL_FALSE, 6 * sizeof (GLfloat),
(const void *) (3 * sizeof (GLfloat)));
glEnableVertexAttribArray(col_attr);
glBindVertexArray(0);
meshes.append({vao, vbo, nverts, mat, col});
doneCurrent(); doneCurrent();
update(); update();
return &meshes.last();
} }
OpenGLMesh *MeshViewer::addOpenGLMeshFromOpenMesh(MyMesh* mesh, QMatrix4x4 mat, QColor col) { void MeshViewer::removeMesh(const MyMesh &mesh) {
GLfloat *verts = new GLfloat[mesh->n_faces() * 3 * 6]; makeCurrent();
size_t i = 0; meshes.remove_if([&](const MeshView &mv) {
return &mv.mesh == &mesh;
for (MyMesh::FaceHandle face : mesh->faces()) { });
for (MyMesh::VertexHandle vec : mesh->fv_range(face)) { doneCurrent();
verts[6*i + 0] = mesh->point(vec)[0]; update();
verts[6*i + 1] = mesh->point(vec)[1];
verts[6*i + 2] = mesh->point(vec)[2];
verts[6*i + 3] = mesh->color(vec)[0];
verts[6*i + 4] = mesh->color(vec)[1];
verts[6*i + 5] = mesh->color(vec)[2];
i++;
}
}
OpenGLMesh *ret = addOpenGLMesh(i, verts, mat, col);
delete[] verts;
return ret;
}
void MeshViewer::removeOpenGLMesh(OpenGLMesh *mesh) {
glDeleteVertexArrays(1, &mesh->vao);
glDeleteBuffers(1, &mesh->vbo);
for (int i = 0; i < meshes.size(); i++) {
if (&meshes[i] == mesh) meshes.removeAt(i);
}
} }

View File

@ -3,6 +3,8 @@
#define GL_GLEXT_PROTOTYPES #define GL_GLEXT_PROTOTYPES
#include "my_mesh.h" #include "my_mesh.h"
#include "mesh_view.h"
#include <list>
#include <QMatrix4x4> #include <QMatrix4x4>
#include <QColor> #include <QColor>
#include <QDebug> #include <QDebug>
@ -19,37 +21,27 @@
using namespace OpenMesh; using namespace OpenMesh;
struct OpenGLMesh {
GLuint vao;
GLuint vbo;
size_t nverts;
QMatrix4x4 mat;
QColor col;
};
class MeshViewer : public QOpenGLWidget { class MeshViewer : public QOpenGLWidget {
Q_OBJECT Q_OBJECT
std::list<MeshView> meshes;
GLint pos_attr, col_attr, proj_attr, view_attr, model_attr;
GLint wf_col_attr, wireframe_attr, alpha_attr;
QMatrix4x4 proj;
QMatrix4x4 rot, rot_start;
GLfloat cam_dist = 1;
QPoint mouse_pos;
public: public:
MeshViewer(QWidget *parent=nullptr); MeshViewer(QWidget *parent=nullptr);
virtual QSize sizeHint() const override; virtual QSize sizeHint() const override;
void initializeGL() override; void initializeGL() override;
void resizeGL(int w, int h) override; void resizeGL(int w, int h) override;
void paintGL() override; void paintGL() override;
OpenGLMesh *addOpenGLMesh(size_t nverts, const GLfloat *verts, QMatrix4x4 mat=QMatrix4x4(), QColor col={153, 153, 153});
OpenGLMesh *addOpenGLMeshFromOpenMesh(MyMesh* _mesh, QMatrix4x4 mat=QMatrix4x4(), QColor col={153, 153, 153});
void removeOpenGLMesh(OpenGLMesh *mesh);
void setOpenGLMeshMatrix(OpenGLMesh *mv, QMatrix4x4 mat);
private: public slots:
QList<OpenGLMesh> meshes; void addMesh(const MyMesh &mesh);
GLint pos_attr, col_attr, proj_attr, view_attr, model_attr; void removeMesh(const MyMesh &mesh);
GLint wf_col_attr, wireframe_attr, alpha_attr;
QMatrix4x4 proj;
QMatrix4x4 rot, rot_start;
GLfloat cam_dist = 1;
QPoint mouse_pos;
protected: protected:
virtual void mousePressEvent(QMouseEvent *e); virtual void mousePressEvent(QMouseEvent *e);

View File

@ -4,6 +4,8 @@
#include <OpenMesh/Core/IO/MeshIO.hh> #include <OpenMesh/Core/IO/MeshIO.hh>
#include <OpenMesh/Core/Mesh/PolyMesh_ArrayKernelT.hh> #include <OpenMesh/Core/Mesh/PolyMesh_ArrayKernelT.hh>
#include <OpenMesh/Core/Geometry/VectorT.hh> #include <OpenMesh/Core/Geometry/VectorT.hh>
#include <QMatrix4x4>
#include <QColor>
struct MyTraits : public OpenMesh::DefaultTraits { struct MyTraits : public OpenMesh::DefaultTraits {
@ -13,7 +15,13 @@ struct MyTraits : public OpenMesh::DefaultTraits {
EdgeAttributes(OpenMesh::Attributes::Color); EdgeAttributes(OpenMesh::Attributes::Color);
typedef OpenMesh::Vec3f Color; typedef OpenMesh::Vec3f Color;
}; };
typedef OpenMesh::PolyMesh_ArrayKernelT<MyTraits> MyMesh;
class MyMesh : public OpenMesh::PolyMesh_ArrayKernelT<MyTraits> {
public:
QMatrix4x4 transform;
QColor color;
};
typedef MyMesh::FaceHandle FaceHandle; typedef MyMesh::FaceHandle FaceHandle;
typedef MyMesh::VertexHandle VertexHandle; typedef MyMesh::VertexHandle VertexHandle;
typedef MyMesh::HalfedgeHandle HalfedgeHandle; typedef MyMesh::HalfedgeHandle HalfedgeHandle;
@ -21,20 +29,4 @@ typedef MyMesh::EdgeHandle EdgeHandle;
typedef MyMesh::Point Point; typedef MyMesh::Point Point;
class HalfedgeLoopRange {
MyMesh &mesh;
const HalfedgeHandle &start;
public:
HalfedgeLoopRange(MyMesh &mesh, const HalfedgeHandle &start)
:mesh(mesh), start(start) {}
MyMesh::HalfedgeLoopIter begin() {
return mesh.hl_begin(start);
}
MyMesh::HalfedgeLoopIter end() {
return mesh.hl_end(start);
}
};
#endif #endif

23
src/util.h Normal file
View File

@ -0,0 +1,23 @@
#ifndef UTIL_H
#define UTIL_H
#include "my_mesh.h"
class HalfedgeLoopRange {
MyMesh &mesh;
const HalfedgeHandle &start;
public:
HalfedgeLoopRange(MyMesh &mesh, const HalfedgeHandle &start)
:mesh(mesh), start(start) {}
MyMesh::HalfedgeLoopIter begin() {
return mesh.hl_begin(start);
}
MyMesh::HalfedgeLoopIter end() {
return mesh.hl_end(start);
}
};
#endif

7
tp.pro
View File

@ -19,9 +19,12 @@ win32 {
HEADERS += src/my_mesh.h HEADERS += src/my_mesh.h
HEADERS += src/main_window.h HEADERS += src/main_window.h
HEADERS += src/mesh_viewer.h HEADERS += src/mesh_viewer.h
HEADERS += src/mesh_processing.h HEADERS += src/mesh_view.h
HEADERS += src/mesh_processor.h
HEADERS += src/util.h
SOURCES += src/main.cpp SOURCES += src/main.cpp
SOURCES += src/main_window.cpp SOURCES += src/main_window.cpp
SOURCES += src/mesh_viewer.cpp SOURCES += src/mesh_viewer.cpp
SOURCES += src/mesh_processing.cpp SOURCES += src/mesh_view.cpp
SOURCES += src/mesh_processor.cpp