archivage initial
This commit is contained in:
16
src/main.cpp
Normal file
16
src/main.cpp
Normal file
@ -0,0 +1,16 @@
|
||||
#include "main_window.h"
|
||||
#include <iostream>
|
||||
#include <QApplication>
|
||||
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
using namespace std;
|
||||
QApplication app(argc, argv);
|
||||
if (argc > 2) {
|
||||
cerr << "Utilisation : " << argv[0] << " [fichier OBJ]" << endl;
|
||||
return 1;
|
||||
}
|
||||
MainWindow mw;
|
||||
mw.show();
|
||||
return app.exec();
|
||||
}
|
56
src/main_window.cpp
Normal file
56
src/main_window.cpp
Normal file
@ -0,0 +1,56 @@
|
||||
#include "main_window.h"
|
||||
|
||||
#include <QApplication>
|
||||
#include <QFileDialog>
|
||||
|
||||
|
||||
MainWindow::MainWindow(QWidget *parent)
|
||||
:QMainWindow(parent),
|
||||
mesh_viewer(this),
|
||||
toolbar(this) {
|
||||
connect(&mesh_viewer, &MeshViewer::initialized, this, &MainWindow::meshViewerInitialized);
|
||||
setCentralWidget(&mesh_viewer);
|
||||
addToolBar(Qt::RightToolBarArea, &toolbar);
|
||||
open_action = toolbar.addAction("Ouvrir…", [&](){
|
||||
open(QFileDialog::getOpenFileName(this, "Ouvrir un fichier OBJ"));
|
||||
});
|
||||
// toolbar_actions.append(toolbar.addAction("Fractionner", [&](){
|
||||
// QVector<QPair<MyMesh::Point, MyMesh>> fragments = shatter(mesh);
|
||||
// mesh_viewer.removeOpenGLMesh(glm);
|
||||
// for (auto &[pos, fragment] : fragments) {
|
||||
// fragment.triangulate();
|
||||
// QMatrix4x4 mat;
|
||||
// float scale = 1.2;
|
||||
// mat.translate(pos[0] * scale, pos[1] * scale, pos[2] * scale);
|
||||
// mesh_viewer.addOpenGLMeshFromOpenMesh(&fragment, mat);
|
||||
// }
|
||||
// }));
|
||||
open_action->setEnabled(false);
|
||||
for (QAction *a : toolbar_actions) {
|
||||
a->setEnabled(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void MainWindow::open(const QString &path) {
|
||||
if (!OpenMesh::IO::read_mesh(mesh, path.toUtf8().constData())) {
|
||||
qWarning() << "Failed to read" << path;
|
||||
return;
|
||||
}
|
||||
for (const VertexHandle &vh : mesh.vertices()) {
|
||||
mesh.set_color(vh, MyMesh::Color(.5, .5, .5));
|
||||
}
|
||||
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);
|
||||
}
|
32
src/main_window.h
Normal file
32
src/main_window.h
Normal file
@ -0,0 +1,32 @@
|
||||
#ifndef MAIN_WINDOW_H
|
||||
#define MAIN_WINDOW_H
|
||||
|
||||
#include <QMainWindow>
|
||||
#include <QToolBar>
|
||||
|
||||
#include "mesh_viewer.h"
|
||||
#include "my_mesh.h"
|
||||
|
||||
|
||||
class MainWindow : public QMainWindow {
|
||||
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;
|
||||
QAction *open_action;
|
||||
QList<QAction *> toolbar_actions;
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif
|
261
src/mesh_viewer.cpp
Normal file
261
src/mesh_viewer.cpp
Normal file
@ -0,0 +1,261 @@
|
||||
#include "mesh_viewer.h"
|
||||
|
||||
#include <tgmath.h>
|
||||
#include <utility>
|
||||
|
||||
|
||||
const GLchar *vertex_shader_source = R"glsl(
|
||||
#version 150 core
|
||||
|
||||
in vec3 pos;
|
||||
in vec3 col;
|
||||
|
||||
out 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(
|
||||
#version 150 core
|
||||
|
||||
in vec3 frag_col;
|
||||
out vec4 final_col;
|
||||
|
||||
uniform vec3 wf_col;
|
||||
uniform bool wireframe;
|
||||
uniform float alpha;
|
||||
|
||||
void main() {
|
||||
if (wireframe)
|
||||
final_col = vec4(wf_col, alpha);
|
||||
else
|
||||
final_col = vec4(frag_col, alpha);
|
||||
}
|
||||
)glsl";
|
||||
|
||||
|
||||
MeshViewer::MeshViewer(QWidget *parent) : QOpenGLWidget(parent) {
|
||||
setMouseTracking(true);
|
||||
setFocus();
|
||||
}
|
||||
|
||||
|
||||
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() {
|
||||
// initializeOpenGLFunctions();
|
||||
|
||||
GLint major, minor;
|
||||
glGetIntegerv(GL_MAJOR_VERSION, &major);
|
||||
glGetIntegerv(GL_MINOR_VERSION, &minor);
|
||||
qDebug("OpenGL version %d.%d", major, minor);
|
||||
|
||||
glEnable(GL_DEBUG_OUTPUT);
|
||||
glDebugMessageCallback(opengl_debug_cb, 0);
|
||||
|
||||
/* Compile the vertex shader. */
|
||||
GLuint vertex_shader = glCreateShader(GL_VERTEX_SHADER);
|
||||
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);
|
||||
}
|
||||
|
||||
/* Compile the fragment shader. */
|
||||
GLuint fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
|
||||
glShaderSource(fragment_shader, 1, &fragment_shader_source, NULL);
|
||||
glCompileShader(fragment_shader);
|
||||
glGetShaderiv(fragment_shader, GL_COMPILE_STATUS, &status);
|
||||
if (status != GL_TRUE) {
|
||||
char log[1024];
|
||||
glGetShaderInfoLog(fragment_shader, sizeof log, NULL, log);
|
||||
fprintf(stderr, "Failed to compile the fragment shader: %s\n", log);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Link the shader program. */
|
||||
GLuint shader_program = glCreateProgram();
|
||||
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);
|
||||
}
|
||||
|
||||
/* Use it. */
|
||||
glUseProgram(shader_program);
|
||||
|
||||
/* Get the position attribute. */
|
||||
pos_attr = glGetAttribLocation(shader_program, "pos");
|
||||
col_attr = glGetAttribLocation(shader_program, "col");
|
||||
|
||||
proj_attr = glGetUniformLocation(shader_program, "proj");
|
||||
view_attr = glGetUniformLocation(shader_program, "view");
|
||||
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);
|
||||
|
||||
emit initialized();
|
||||
}
|
||||
|
||||
|
||||
void MeshViewer::resizeGL(int w, int h) {
|
||||
QMatrix4x4 projection;
|
||||
projection.perspective(FOV, (float) w/h, .01, 100);
|
||||
glUniformMatrix4fv(proj_attr, 1, GL_FALSE, projection.data());
|
||||
}
|
||||
|
||||
|
||||
void MeshViewer::paintGL() {
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
QMatrix4x4 trans;
|
||||
trans.translate(0, 0, -cam_dist);
|
||||
QMatrix4x4 view = trans * rot;
|
||||
glUniformMatrix4fv(view_attr, 1, GL_FALSE, view.data());
|
||||
for (const OpenGLMesh m : meshes) {
|
||||
glUniformMatrix4fv(model_attr, 1, GL_FALSE, m.mat.data());
|
||||
|
||||
/* 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(1);
|
||||
glUniform1f(wireframe_attr, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
OpenGLMesh *MeshViewer::addOpenGLMesh(size_t nverts, const GLfloat *verts, QMatrix4x4 mat, QColor col) {
|
||||
makeCurrent();
|
||||
|
||||
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();
|
||||
update();
|
||||
return &meshes.last();
|
||||
}
|
||||
|
||||
|
||||
OpenGLMesh *MeshViewer::addOpenGLMeshFromOpenMesh(MyMesh* mesh, QMatrix4x4 mat, QColor col) {
|
||||
GLfloat *verts = new GLfloat[mesh->n_faces() * 3 * 6];
|
||||
size_t i = 0;
|
||||
|
||||
for (MyMesh::FaceHandle face : mesh->faces()) {
|
||||
for (MyMesh::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(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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void MeshViewer::mousePressEvent(QMouseEvent *e) {
|
||||
if (e->button() == Qt::LeftButton) {
|
||||
mouse_pos = e->pos();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void MeshViewer::mouseReleaseEvent(QMouseEvent *e) {
|
||||
(void) e;
|
||||
rot_start = rot;
|
||||
}
|
||||
|
||||
|
||||
void MeshViewer::mouseMoveEvent(QMouseEvent *e) {
|
||||
if (e->buttons() & Qt::LeftButton) {
|
||||
QPoint delta = e->pos() - mouse_pos;
|
||||
rot = rot_start;
|
||||
rot.rotate(delta.x() / 5., 0, 1, 0);
|
||||
rot.rotate(delta.y() / 5., QVector3D(1, 0, 0) * rot);
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void MeshViewer::wheelEvent(QWheelEvent *e) {
|
||||
cam_dist -= e->angleDelta().y() / 1000. * cam_dist;
|
||||
update();
|
||||
}
|
64
src/mesh_viewer.h
Normal file
64
src/mesh_viewer.h
Normal file
@ -0,0 +1,64 @@
|
||||
#ifndef MESH_VIEWER_H
|
||||
#define MESH_VIEWER_H
|
||||
|
||||
#define GL_GLEXT_PROTOTYPES
|
||||
#include "my_mesh.h"
|
||||
#include <QMatrix4x4>
|
||||
#include <QColor>
|
||||
#include <QDebug>
|
||||
#include <QOpenGLWidget>
|
||||
#include <QOpenGLShaderProgram>
|
||||
#include <QOpenGLFunctions>
|
||||
#include <QMouseEvent>
|
||||
|
||||
|
||||
#define WIREFRAME_COLOR 0, 0, 0
|
||||
#define FOV 70
|
||||
|
||||
|
||||
using namespace OpenMesh;
|
||||
|
||||
|
||||
struct OpenGLMesh {
|
||||
GLuint vao;
|
||||
GLuint vbo;
|
||||
size_t nverts;
|
||||
QMatrix4x4 mat;
|
||||
QColor col;
|
||||
};
|
||||
|
||||
|
||||
class MeshViewer : public QOpenGLWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MeshViewer(QWidget *parent=nullptr);
|
||||
void initializeGL() override;
|
||||
void resizeGL(int w, int h) 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:
|
||||
QList<OpenGLMesh> 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;
|
||||
|
||||
protected:
|
||||
virtual void mousePressEvent(QMouseEvent *e);
|
||||
virtual void mouseReleaseEvent(QMouseEvent *e);
|
||||
virtual void mouseMoveEvent(QMouseEvent *e);
|
||||
virtual void wheelEvent(QWheelEvent *e);
|
||||
|
||||
signals:
|
||||
void initialized();
|
||||
};
|
||||
|
||||
|
||||
#endif
|
19
src/my_mesh.h
Normal file
19
src/my_mesh.h
Normal file
@ -0,0 +1,19 @@
|
||||
#ifndef MY_MESH_H
|
||||
#define MY_MESH_H
|
||||
|
||||
#include <OpenMesh/Core/IO/MeshIO.hh>
|
||||
#include <OpenMesh/Core/Mesh/PolyMesh_ArrayKernelT.hh>
|
||||
#include <OpenMesh/Core/Geometry/VectorT.hh>
|
||||
|
||||
|
||||
struct MyTraits : public OpenMesh::DefaultTraits {
|
||||
VertexAttributes(OpenMesh::Attributes::Normal | OpenMesh::Attributes::Color);
|
||||
HalfedgeAttributes(OpenMesh::Attributes::PrevHalfedge);
|
||||
FaceAttributes(OpenMesh::Attributes::Normal);
|
||||
EdgeAttributes(OpenMesh::Attributes::Color);
|
||||
typedef OpenMesh::Vec3f Color;
|
||||
};
|
||||
typedef OpenMesh::PolyMesh_ArrayKernelT<MyTraits> MyMesh;
|
||||
|
||||
|
||||
#endif
|
Reference in New Issue
Block a user