Compare commits
No commits in common. "e56eed0a16d589e62ae4631310d6562bfc553ac6" and "63074306c2093f0faec3f7cb731978bbfb194ff3" have entirely different histories.
e56eed0a16
...
63074306c2
@ -1,6 +0,0 @@
|
|||||||
<!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>
|
|
35
src/main.cpp
35
src/main.cpp
@ -1,45 +1,16 @@
|
|||||||
#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) {
|
||||||
qWarning("Utilisation : %s [MAILLAGE]", argv[0]);
|
cerr << "Utilisation : " << argv[0] << " [fichier OBJ]" << endl;
|
||||||
return 1;
|
return 1;
|
||||||
} else if (argc == 2) {
|
|
||||||
mesh_processor = new MeshProcessor(argv[1]);
|
|
||||||
}
|
}
|
||||||
QObject::connect(&main_window, &MainWindow::open,
|
MainWindow mw;
|
||||||
[&](const QString &path) {
|
mw.show();
|
||||||
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();
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#include "main_window.h"
|
#include "main_window.h"
|
||||||
#include "mesh_processor.h"
|
#include "mesh_processing.h"
|
||||||
|
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
#include <QFileDialog>
|
#include <QFileDialog>
|
||||||
@ -7,15 +7,13 @@
|
|||||||
|
|
||||||
MainWindow::MainWindow(QWidget *parent)
|
MainWindow::MainWindow(QWidget *parent)
|
||||||
:QMainWindow(parent),
|
:QMainWindow(parent),
|
||||||
toolbar(this),
|
mesh_viewer(this),
|
||||||
mesh_viewer(this) {
|
toolbar(this) {
|
||||||
connect(&mesh_viewer, &MeshViewer::initialized, [&]() {
|
connect(&mesh_viewer, &MeshViewer::initialized, this, &MainWindow::meshViewerInitialized);
|
||||||
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…", [&](){
|
||||||
emit open(QFileDialog::getOpenFileName(this, "Ouvrir un maillage"));
|
open(QFileDialog::getOpenFileName(this, "Ouvrir un fichier OBJ"));
|
||||||
});
|
});
|
||||||
// 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,3 +31,35 @@ 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);
|
||||||
|
}
|
||||||
|
@ -11,17 +11,21 @@
|
|||||||
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);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
#include "mesh_processing.h"
|
#include "mesh_processing.h"
|
||||||
#include "util.h"
|
|
||||||
#include <QGenericMatrix>
|
#include <QGenericMatrix>
|
||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
|
|
||||||
|
17
src/mesh_processing.h
Normal file
17
src/mesh_processing.h
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
#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
|
@ -1,84 +0,0 @@
|
|||||||
#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);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,28 +0,0 @@
|
|||||||
#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
|
|
@ -1,6 +0,0 @@
|
|||||||
#include "mesh_processor_painter.h"
|
|
||||||
|
|
||||||
|
|
||||||
void MeshProcessorPainter::paint() {
|
|
||||||
|
|
||||||
}
|
|
@ -1,15 +0,0 @@
|
|||||||
#ifndef MESH_PAINTER_H
|
|
||||||
#define MESH_PAINTER_H
|
|
||||||
|
|
||||||
#include <QObject>
|
|
||||||
|
|
||||||
|
|
||||||
class MeshProcessorPainter {
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public slots:
|
|
||||||
void paint();
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,70 +0,0 @@
|
|||||||
#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);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,25 +0,0 @@
|
|||||||
#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
|
|
@ -1,9 +1,40 @@
|
|||||||
#include "mesh_viewer.h"
|
#include "mesh_viewer.h"
|
||||||
|
|
||||||
#include <tgmath.h>
|
#include <tgmath.h>
|
||||||
#include <QOpenGLShader>
|
#include <utility>
|
||||||
#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) {
|
||||||
@ -17,48 +48,96 @@ 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() {
|
||||||
QOpenGLFunctions *glf = context()->functions();
|
// initializeOpenGLFunctions();
|
||||||
#ifdef QT_DEBUG
|
|
||||||
const QSurfaceFormat &format = context()->format();
|
|
||||||
qDebug("MeshViewer: OpenGL %s%d.%d %s",
|
|
||||||
format.renderableType() == QSurfaceFormat::OpenGLES ? "ES " : "",
|
|
||||||
format.majorVersion(), format.minorVersion(),
|
|
||||||
format.profile() == QSurfaceFormat::CoreProfile ? "core profile"
|
|
||||||
: (format.profile() == QSurfaceFormat::CompatibilityProfile ? "compatibility profile"
|
|
||||||
: ""));
|
|
||||||
QOpenGLDebugLogger *logger = new QOpenGLDebugLogger(this);
|
|
||||||
if (!logger->initialize()) {
|
|
||||||
qDebug("OpenGL debug output unavailable");
|
|
||||||
}
|
|
||||||
connect(logger, &QOpenGLDebugLogger::messageLogged,
|
|
||||||
[](const QOpenGLDebugMessage &message) {
|
|
||||||
qDebug() << "OpenGL:" << message.message();
|
|
||||||
});
|
|
||||||
logger->startLogging();
|
|
||||||
#endif
|
|
||||||
if (!program.addShaderFromSourceFile(QOpenGLShader::Vertex,
|
|
||||||
":/shader.vert")) {
|
|
||||||
qFatal("%s", program.log().toUtf8().constData());
|
|
||||||
}
|
|
||||||
if (!program.addShaderFromSourceFile(QOpenGLShader::Fragment,
|
|
||||||
":/shader.frag")) {
|
|
||||||
qFatal("%s", program.log().toUtf8().constData());
|
|
||||||
}
|
|
||||||
if (!program.link()) {
|
|
||||||
qFatal("%s", program.log().toUtf8().constData());
|
|
||||||
}
|
|
||||||
program.bind();
|
|
||||||
|
|
||||||
program.setUniformValue("alpha", (GLfloat) 1);
|
GLint major, minor;
|
||||||
program.setUniformValue("wf_col", WIREFRAME_COLOR);
|
glGetIntegerv(GL_MAJOR_VERSION, &major);
|
||||||
|
glGetIntegerv(GL_MINOR_VERSION, &minor);
|
||||||
|
qDebug("OpenGL version %d.%d", major, minor);
|
||||||
|
|
||||||
glf->glClearColor(1, 1, 1, 0);
|
glEnable(GL_DEBUG_OUTPUT);
|
||||||
|
glDebugMessageCallback(opengl_debug_cb, 0);
|
||||||
|
|
||||||
glf->glEnable(GL_DEPTH_TEST);
|
/* Compile the vertex shader. */
|
||||||
glf->glEnable(GL_MULTISAMPLE);
|
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);
|
||||||
|
|
||||||
qDebug("MeshViewer: initialization complete");
|
|
||||||
emit initialized();
|
emit initialized();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -66,7 +145,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);
|
||||||
program.setUniformValue("proj", projection);
|
glUniformMatrix4fv(proj_attr, 1, GL_FALSE, projection.data());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -75,30 +154,81 @@ 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;
|
||||||
program.bind();
|
glUniformMatrix4fv(view_attr, 1, GL_FALSE, view.data());
|
||||||
program.setUniformValue("view", view);
|
for (const OpenGLMesh m : meshes) {
|
||||||
for (MeshView &m : meshes) {
|
glUniformMatrix4fv(model_attr, 1, GL_FALSE, m.mat.data());
|
||||||
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void MeshViewer::addMesh(const MyMesh &mesh) {
|
OpenGLMesh *MeshViewer::addOpenGLMesh(size_t nverts, const GLfloat *verts, QMatrix4x4 mat, QColor col) {
|
||||||
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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void MeshViewer::removeMesh(const MyMesh &mesh) {
|
OpenGLMesh *MeshViewer::addOpenGLMeshFromOpenMesh(MyMesh* mesh, QMatrix4x4 mat, QColor col) {
|
||||||
makeCurrent();
|
GLfloat *verts = new GLfloat[mesh->n_faces() * 3 * 6];
|
||||||
meshes.remove_if([&](const MeshView &mv) {
|
size_t i = 0;
|
||||||
return &mv.mesh == &mesh;
|
|
||||||
});
|
for (MyMesh::FaceHandle face : mesh->faces()) {
|
||||||
doneCurrent();
|
for (MyMesh::VertexHandle vec : mesh->fv_range(face)) {
|
||||||
update();
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -3,8 +3,6 @@
|
|||||||
|
|
||||||
#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>
|
||||||
@ -21,26 +19,37 @@
|
|||||||
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);
|
||||||
|
|
||||||
public slots:
|
private:
|
||||||
void addMesh(const MyMesh &mesh);
|
QList<OpenGLMesh> meshes;
|
||||||
void removeMesh(const MyMesh &mesh);
|
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:
|
protected:
|
||||||
virtual void mousePressEvent(QMouseEvent *e);
|
virtual void mousePressEvent(QMouseEvent *e);
|
||||||
|
@ -4,8 +4,6 @@
|
|||||||
#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 {
|
||||||
@ -15,13 +13,7 @@ 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;
|
||||||
@ -29,4 +21,20 @@ 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
|
||||||
|
@ -1,13 +0,0 @@
|
|||||||
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);
|
|
||||||
}
|
|
@ -1,13 +0,0 @@
|
|||||||
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
23
src/util.h
@ -1,23 +0,0 @@
|
|||||||
#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
9
tp.pro
@ -16,17 +16,12 @@ 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_view.h
|
HEADERS += src/mesh_processing.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_view.cpp
|
SOURCES += src/mesh_processing.cpp
|
||||||
SOURCES += src/mesh_processor.cpp
|
|
||||||
|
Loading…
Reference in New Issue
Block a user