Compare commits

...

4 Commits

Author SHA1 Message Date
e56eed0a16 fix open button 2021-10-03 00:24:20 +02:00
31a97e7c2e fix the rendering 2021-10-03 00:11:29 +02:00
7601caaada code is all clean now (but still broken) 2021-10-02 22:51:20 +02:00
d74f80530b break everything 2021-10-02 20:47:02 +02:00
19 changed files with 410 additions and 290 deletions

6
resources.qrc Normal file
View File

@ -0,0 +1,6 @@
<!DOCTYPE RCC><RCC version="1.0">
<qresource>
<file alias="shader.vert">src/shader.vert</file>
<file alias="shader.frag">src/shader.frag</file>
</qresource>
</RCC>

View File

@ -1,16 +1,45 @@
#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::OpenGL);
#ifndef QT_DEBUG
qDebug("Debug build");
format.setOption(QSurfaceFormat::DebugContext);
#endif
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) {
mesh_viewer->removeMesh(mesh_processor->mesh);
delete mesh_processor;
}
mesh_processor = new MeshProcessor(path);
mesh_viewer->addMesh(mesh_processor->mesh);
});
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>
@ -7,13 +7,15 @@
MainWindow::MainWindow(QWidget *parent) MainWindow::MainWindow(QWidget *parent)
:QMainWindow(parent), :QMainWindow(parent),
mesh_viewer(this), toolbar(this),
toolbar(this) { mesh_viewer(this) {
connect(&mesh_viewer, &MeshViewer::initialized, this, &MainWindow::meshViewerInitialized); 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…", [&](){ 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);
@ -31,35 +33,3 @@ MainWindow::MainWindow(QWidget *parent)
a->setEnabled(false); a->setEnabled(false);
} }
} }
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() {
if (qApp->arguments().size() == 2) {
open(qApp->arguments().at(1));
}
open_action->setEnabled(true);
}

View File

@ -11,21 +11,17 @@
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;
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

70
src/mesh_view.cpp Normal file
View File

@ -0,0 +1,70 @@
#include "mesh_view.h"
#include <QOpenGLContext>
#include <QOpenGLFunctions_2_1>
MeshView::MeshView(const MyMesh &mesh, QOpenGLShaderProgram &program)
: buffer(QOpenGLBuffer::VertexBuffer),
nverts(mesh.n_faces() * 3),
mesh(mesh) {
QVector<GLfloat> verts(nverts * 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++;
}
}
vao.create();
{QOpenGLVertexArrayObject::Binder binder(&vao);
buffer.create();
buffer.bind();
buffer.setUsagePattern(QOpenGLBuffer::StreamDraw);
buffer.allocate(verts.constData(), nverts * 6 * sizeof (GLfloat));
program.setAttributeBuffer("pos", GL_FLOAT, 0, 3, 6 * sizeof (GLfloat));
program.enableAttributeArray("pos");
program.setAttributeBuffer("col", GL_FLOAT, 3 * sizeof (GLfloat), 3, 6 * sizeof (GLfloat));
program.enableAttributeArray("col");
}
}
MeshView::~MeshView() {
vao.destroy();
buffer.destroy();
}
void MeshView::paint(QOpenGLShaderProgram &program) {
QOpenGLContext *ctx = QOpenGLContext::currentContext();
QOpenGLExtraFunctions *glf = ctx->extraFunctions();
QOpenGLFunctions_2_1 *glf21 = nullptr;
glf21 = ctx->versionFunctions<QOpenGLFunctions_2_1>();
if (!glf21)
qFatal("Failed to get OpenGL 2.1 functions");
program.setUniformValue("model", mesh.transform);
{QOpenGLVertexArrayObject::Binder binder(&vao);
/* Mesh */
glf->glEnable(GL_POLYGON_OFFSET_FILL);
glf->glPolygonOffset(1.0, 2);
glf->glDrawArrays(GL_TRIANGLES, 0, nverts);
glf21->glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
glf->glDisable(GL_POLYGON_OFFSET_FILL);
/* Wireframe */
program.setUniformValue("wireframe", 1);
glf->glDrawArrays(GL_TRIANGLES, 0, nverts);
glf21->glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glf->glLineWidth(2);
program.setUniformValue("wireframe", 0);
}
}

25
src/mesh_view.h Normal file
View File

@ -0,0 +1,25 @@
#ifndef MESH_VIEW_H
#define MESH_VIEW_H
#include "my_mesh.h"
#include <QOpenGLExtraFunctions>
#include <QOpenGLShaderProgram>
#include <QOpenGLVertexArrayObject>
#include <QOpenGLBuffer>
class MeshView {
QOpenGLVertexArrayObject vao;
QOpenGLBuffer buffer;
size_t nverts;
public:
const MyMesh &mesh;
MeshView(const MyMesh &mesh, QOpenGLShaderProgram &program);
~MeshView();
void paint(QOpenGLShaderProgram &program);
};
#endif

View File

@ -1,40 +1,9 @@
#include "mesh_viewer.h" #include "mesh_viewer.h"
#include <tgmath.h> #include <tgmath.h>
#include <utility> #include <QOpenGLShader>
#include <QOpenGLDebugLogger>
#include <QtGlobal>
const GLchar *vertex_shader_source = R"glsl(
attribute vec3 pos;
attribute vec3 col;
varying vec3 frag_col;
uniform mat4 proj;
uniform mat4 view;
uniform mat4 model;
void main() {
gl_Position = proj * view * model * vec4(pos, 1.0);
frag_col = col;
}
)glsl";
const GLchar *fragment_shader_source = R"glsl(
varying vec3 frag_col;
uniform vec3 wf_col;
uniform bool wireframe;
uniform float alpha;
void main() {
if (!wireframe)
// gl_FragColor = vec4(wf_col, alpha);
gl_FragColor = vec4(.5, .5, .5, 1);
else
gl_FragColor = vec4(frag_col, alpha);
}
)glsl";
MeshViewer::MeshViewer(QWidget *parent) : QOpenGLWidget(parent) { MeshViewer::MeshViewer(QWidget *parent) : QOpenGLWidget(parent) {
@ -48,96 +17,48 @@ QSize MeshViewer::sizeHint() const {
} }
void GLAPIENTRY
opengl_debug_cb(GLenum source,
GLenum type,
GLuint id,
GLenum severity,
GLsizei length,
const GLchar* message,
const void* userParam) {
(void) source;
(void) type;
(void) id;
(void) severity;
(void) length;
(void) userParam;
qDebug() << "OpenGL debug output:" << message;
}
void MeshViewer::initializeGL() { void MeshViewer::initializeGL() {
// initializeOpenGLFunctions(); QOpenGLFunctions *glf = context()->functions();
#ifdef QT_DEBUG
GLint major, minor; const QSurfaceFormat &format = context()->format();
glGetIntegerv(GL_MAJOR_VERSION, &major); qDebug("MeshViewer: OpenGL %s%d.%d %s",
glGetIntegerv(GL_MINOR_VERSION, &minor); format.renderableType() == QSurfaceFormat::OpenGLES ? "ES " : "",
qDebug("OpenGL version %d.%d", major, minor); format.majorVersion(), format.minorVersion(),
format.profile() == QSurfaceFormat::CoreProfile ? "core profile"
glEnable(GL_DEBUG_OUTPUT); : (format.profile() == QSurfaceFormat::CompatibilityProfile ? "compatibility profile"
glDebugMessageCallback(opengl_debug_cb, 0); : ""));
QOpenGLDebugLogger *logger = new QOpenGLDebugLogger(this);
/* Compile the vertex shader. */ if (!logger->initialize()) {
GLuint vertex_shader = glCreateShader(GL_VERTEX_SHADER); qDebug("OpenGL debug output unavailable");
glShaderSource(vertex_shader, 1, &vertex_shader_source, NULL);
glCompileShader(vertex_shader);
GLint status;
glGetShaderiv(vertex_shader, GL_COMPILE_STATUS, &status);
if (status != GL_TRUE) {
char log[1024];
glGetShaderInfoLog(vertex_shader, sizeof log, NULL, log);
fprintf(stderr, "Failed to compile the vertex shader: %s\n", log);
exit(1);
} }
connect(logger, &QOpenGLDebugLogger::messageLogged,
/* Compile the fragment shader. */ [](const QOpenGLDebugMessage &message) {
GLuint fragment_shader = glCreateShader(GL_FRAGMENT_SHADER); qDebug() << "OpenGL:" << message.message();
glShaderSource(fragment_shader, 1, &fragment_shader_source, NULL); });
glCompileShader(fragment_shader); logger->startLogging();
glGetShaderiv(fragment_shader, GL_COMPILE_STATUS, &status); #endif
if (status != GL_TRUE) { if (!program.addShaderFromSourceFile(QOpenGLShader::Vertex,
char log[1024]; ":/shader.vert")) {
glGetShaderInfoLog(fragment_shader, sizeof log, NULL, log); qFatal("%s", program.log().toUtf8().constData());
fprintf(stderr, "Failed to compile the fragment shader: %s\n", log);
exit(1);
} }
if (!program.addShaderFromSourceFile(QOpenGLShader::Fragment,
/* Link the shader program. */ ":/shader.frag")) {
GLuint shader_program = glCreateProgram(); qFatal("%s", program.log().toUtf8().constData());
glAttachShader(shader_program, vertex_shader);
glAttachShader(shader_program, fragment_shader);
glBindFragDataLocation(shader_program, 0, "out_color");
glLinkProgram(shader_program);
glGetProgramiv(shader_program, GL_LINK_STATUS, &status);
if (status != GL_TRUE) {
char log[1024];
glGetProgramInfoLog(shader_program, sizeof log, NULL, log);
fprintf(stderr, "Failed to link the shader program: %s\n", log);
exit(1);
} }
if (!program.link()) {
qFatal("%s", program.log().toUtf8().constData());
}
program.bind();
/* Use it. */ program.setUniformValue("alpha", (GLfloat) 1);
glUseProgram(shader_program); program.setUniformValue("wf_col", WIREFRAME_COLOR);
/* Get the position attribute. */ glf->glClearColor(1, 1, 1, 0);
pos_attr = glGetAttribLocation(shader_program, "pos");
col_attr = glGetAttribLocation(shader_program, "col");
proj_attr = glGetUniformLocation(shader_program, "proj"); glf->glEnable(GL_DEPTH_TEST);
view_attr = glGetUniformLocation(shader_program, "view"); glf->glEnable(GL_MULTISAMPLE);
model_attr = glGetUniformLocation(shader_program, "model");
wf_col_attr = glGetUniformLocation(shader_program, "wf_col");
wireframe_attr = glGetUniformLocation(shader_program, "wireframe");
alpha_attr = glGetUniformLocation(shader_program, "alpha");
glUniform1f(alpha_attr, 1);
glUniform3f(wf_col_attr, WIREFRAME_COLOR);
glClearColor(1, 1, 1, 0);
glEnable(GL_DEPTH_TEST);
glEnable(GL_MULTISAMPLE);
qDebug("MeshViewer: initialization complete");
emit initialized(); emit initialized();
} }
@ -145,7 +66,7 @@ void MeshViewer::initializeGL() {
void MeshViewer::resizeGL(int w, int h) { void MeshViewer::resizeGL(int w, int h) {
QMatrix4x4 projection; QMatrix4x4 projection;
projection.perspective(FOV, (float) w/h, .01, 100); projection.perspective(FOV, (float) w/h, .01, 100);
glUniformMatrix4fv(proj_attr, 1, GL_FALSE, projection.data()); program.setUniformValue("proj", projection);
} }
@ -154,81 +75,30 @@ void MeshViewer::paintGL() {
QMatrix4x4 trans; QMatrix4x4 trans;
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()); program.bind();
for (const OpenGLMesh m : meshes) { program.setUniformValue("view", view);
glUniformMatrix4fv(model_attr, 1, GL_FALSE, m.mat.data()); for (MeshView &m : meshes) {
m.paint(program);
/* 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) {
Q_ASSERT(isValid());
makeCurrent(); makeCurrent();
meshes.emplace_back(mesh, program);
GLuint vao, vbo;
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,26 @@
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;
QOpenGLShaderProgram program;
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

13
src/shader.frag Normal file
View File

@ -0,0 +1,13 @@
varying vec3 frag_col;
uniform vec3 wf_col;
uniform bool wireframe;
uniform float alpha;
void main() {
if (wireframe)
gl_FragColor = vec4(wf_col, alpha);
else
// gl_FragColor = vec4(frag_col, alpha);
gl_FragColor = vec4(.5, .5, .5, alpha);
}

13
src/shader.vert Normal file
View File

@ -0,0 +1,13 @@
attribute vec3 pos;
attribute vec3 col;
varying vec3 frag_col;
uniform mat4 proj;
uniform mat4 view;
uniform mat4 model;
void main() {
gl_Position = proj * view * model * vec4(pos, 1.0);
frag_col = col;
}

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

9
tp.pro
View File

@ -16,12 +16,17 @@ win32 {
LIBS += $$PWD/libs/OpenMesh/libwin/OpenMeshCore.lib LIBS += $$PWD/libs/OpenMesh/libwin/OpenMeshCore.lib
} }
RESOURCES = resources.qrc
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