2021-09-20 20:36:29 +02:00
|
|
|
#include "mesh_viewer.h"
|
|
|
|
|
|
|
|
#include <tgmath.h>
|
2021-10-02 22:51:20 +02:00
|
|
|
#include <QOpenGLShader>
|
|
|
|
#include <QOpenGLDebugLogger>
|
|
|
|
#include <QtGlobal>
|
2021-09-20 20:36:29 +02:00
|
|
|
|
|
|
|
|
|
|
|
MeshViewer::MeshViewer(QWidget *parent) : QOpenGLWidget(parent) {
|
|
|
|
setMouseTracking(true);
|
|
|
|
setFocus();
|
2021-11-27 14:11:18 +01:00
|
|
|
updateViewMatrix();
|
2021-09-20 20:36:29 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-11-13 17:53:21 +01:00
|
|
|
void MeshViewer::updateViewMatrix() {
|
2021-11-27 14:11:18 +01:00
|
|
|
view = zoom * rot * trans;
|
2021-11-13 17:53:21 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-09-24 23:03:48 +02:00
|
|
|
QSize MeshViewer::sizeHint() const {
|
|
|
|
return QSize(640, 480);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-09-20 20:36:29 +02:00
|
|
|
void MeshViewer::initializeGL() {
|
2021-10-02 22:51:20 +02:00
|
|
|
QOpenGLFunctions *glf = context()->functions();
|
|
|
|
#ifdef QT_DEBUG
|
2021-10-03 00:11:29 +02:00
|
|
|
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"
|
|
|
|
: ""));
|
2021-10-02 22:51:20 +02:00
|
|
|
QOpenGLDebugLogger *logger = new QOpenGLDebugLogger(this);
|
|
|
|
if (!logger->initialize()) {
|
|
|
|
qDebug("OpenGL debug output unavailable");
|
2021-09-20 20:36:29 +02:00
|
|
|
}
|
2021-10-02 22:51:20 +02:00
|
|
|
connect(logger, &QOpenGLDebugLogger::messageLogged,
|
|
|
|
[](const QOpenGLDebugMessage &message) {
|
2021-10-03 00:11:29 +02:00
|
|
|
qDebug() << "OpenGL:" << message.message();
|
2021-10-02 22:51:20 +02:00
|
|
|
});
|
|
|
|
logger->startLogging();
|
|
|
|
#endif
|
2021-10-03 00:11:29 +02:00
|
|
|
if (!program.addShaderFromSourceFile(QOpenGLShader::Vertex,
|
|
|
|
":/shader.vert")) {
|
|
|
|
qFatal("%s", program.log().toUtf8().constData());
|
2021-09-20 20:36:29 +02:00
|
|
|
}
|
2021-10-03 00:11:29 +02:00
|
|
|
if (!program.addShaderFromSourceFile(QOpenGLShader::Fragment,
|
|
|
|
":/shader.frag")) {
|
|
|
|
qFatal("%s", program.log().toUtf8().constData());
|
2021-10-02 22:51:20 +02:00
|
|
|
}
|
|
|
|
if (!program.link()) {
|
2021-10-03 00:11:29 +02:00
|
|
|
qFatal("%s", program.log().toUtf8().constData());
|
2021-10-02 22:51:20 +02:00
|
|
|
}
|
|
|
|
program.bind();
|
2021-09-20 20:36:29 +02:00
|
|
|
|
2021-10-02 22:51:20 +02:00
|
|
|
program.setUniformValue("alpha", (GLfloat) 1);
|
|
|
|
program.setUniformValue("wf_col", WIREFRAME_COLOR);
|
2021-09-20 20:36:29 +02:00
|
|
|
|
2021-10-02 22:51:20 +02:00
|
|
|
glf->glClearColor(1, 1, 1, 0);
|
2021-09-20 20:36:29 +02:00
|
|
|
|
2021-10-02 22:51:20 +02:00
|
|
|
glf->glEnable(GL_DEPTH_TEST);
|
|
|
|
glf->glEnable(GL_MULTISAMPLE);
|
2021-09-20 20:36:29 +02:00
|
|
|
|
2021-10-03 00:11:29 +02:00
|
|
|
qDebug("MeshViewer: initialization complete");
|
2021-11-18 14:55:03 +01:00
|
|
|
is_initialized = true;
|
2021-09-20 20:36:29 +02:00
|
|
|
emit initialized();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void MeshViewer::resizeGL(int w, int h) {
|
2021-11-13 17:53:21 +01:00
|
|
|
proj.setToIdentity();
|
|
|
|
proj.perspective(FOV, (float) w/h, .01, 100);
|
|
|
|
program.setUniformValue("proj", proj);
|
|
|
|
update();
|
2021-09-20 20:36:29 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void MeshViewer::paintGL() {
|
2021-10-22 14:28:54 +02:00
|
|
|
// glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
2021-09-20 20:36:29 +02:00
|
|
|
QMatrix4x4 trans;
|
2021-10-03 00:11:29 +02:00
|
|
|
program.bind();
|
2021-10-02 22:51:20 +02:00
|
|
|
program.setUniformValue("view", view);
|
|
|
|
for (MeshView &m : meshes) {
|
|
|
|
m.paint(program);
|
2021-09-20 20:36:29 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-11-12 17:08:19 +01:00
|
|
|
void MeshViewer::addMesh(const MyMesh &mesh) {
|
2021-10-02 22:51:20 +02:00
|
|
|
Q_ASSERT(isValid());
|
2021-09-20 20:36:29 +02:00
|
|
|
makeCurrent();
|
2021-11-12 17:08:19 +01:00
|
|
|
meshes.emplace_back(mesh, program);
|
2021-09-20 20:36:29 +02:00
|
|
|
doneCurrent();
|
|
|
|
update();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-11-12 17:08:19 +01:00
|
|
|
void MeshViewer::removeMesh(const MyMesh &mesh) {
|
2021-10-02 20:47:02 +02:00
|
|
|
makeCurrent();
|
|
|
|
meshes.remove_if([&](const MeshView &mv) {
|
2021-11-12 17:08:19 +01:00
|
|
|
return &mv.mesh == &mesh;
|
2021-10-02 20:47:02 +02:00
|
|
|
});
|
|
|
|
doneCurrent();
|
|
|
|
update();
|
2021-09-20 20:36:29 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-11-13 17:53:21 +01:00
|
|
|
void MeshViewer::updateForReal() {
|
|
|
|
setEnabled(true);
|
|
|
|
setVisible(true);
|
|
|
|
update();
|
|
|
|
repaint();
|
|
|
|
makeCurrent();
|
|
|
|
paintGL();
|
|
|
|
doneCurrent();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-09-20 20:36:29 +02:00
|
|
|
void MeshViewer::mousePressEvent(QMouseEvent *e) {
|
2021-11-27 11:38:14 +01:00
|
|
|
if (e->button() & Qt::MiddleButton || e->button() & Qt::RightButton) {
|
2021-09-20 20:36:29 +02:00
|
|
|
mouse_pos = e->pos();
|
2021-11-13 17:53:21 +01:00
|
|
|
} else if (e->button() == Qt::LeftButton) {
|
|
|
|
float x = e->x();
|
|
|
|
float y = height() - e->y();
|
|
|
|
float depth;
|
|
|
|
makeCurrent();
|
|
|
|
QOpenGLFunctions *glf = context()->functions();
|
|
|
|
glf->glReadPixels(x, y, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &depth);
|
|
|
|
doneCurrent();
|
|
|
|
QVector3D position {x, y, depth};
|
|
|
|
position = position.unproject(view, proj, rect());
|
|
|
|
emit clicked(QVector3D(position));
|
|
|
|
} else {
|
|
|
|
e->ignore();
|
2021-09-20 20:36:29 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void MeshViewer::mouseReleaseEvent(QMouseEvent *e) {
|
|
|
|
(void) e;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void MeshViewer::mouseMoveEvent(QMouseEvent *e) {
|
2021-11-27 14:11:18 +01:00
|
|
|
QPoint delta = e->pos() - mouse_pos;
|
|
|
|
mouse_pos = e->pos();
|
2021-11-13 13:32:13 +01:00
|
|
|
if (e->buttons() & Qt::MiddleButton) {
|
2021-09-20 20:36:29 +02:00
|
|
|
rot.rotate(delta.x() / 5., 0, 1, 0);
|
|
|
|
rot.rotate(delta.y() / 5., QVector3D(1, 0, 0) * rot);
|
2021-11-13 17:53:21 +01:00
|
|
|
updateViewMatrix();
|
2021-09-20 20:36:29 +02:00
|
|
|
update();
|
|
|
|
}
|
2021-11-27 11:38:14 +01:00
|
|
|
if (e->buttons() & Qt::RightButton) {
|
2021-11-27 14:11:18 +01:00
|
|
|
QMatrix4x4 screen_trans;
|
|
|
|
screen_trans.translate(delta.x() / 1000., -delta.y() / 1000., 0);
|
|
|
|
trans = rot.inverted() * screen_trans * rot * trans;
|
|
|
|
// trans(0, 0) = 1;
|
|
|
|
// trans(0, 1) = 0;
|
|
|
|
// trans(1, 0) = 0;
|
|
|
|
// trans(1, 1) = 1;
|
2021-11-27 11:38:14 +01:00
|
|
|
updateViewMatrix();
|
|
|
|
update();
|
|
|
|
}
|
2021-09-20 20:36:29 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void MeshViewer::wheelEvent(QWheelEvent *e) {
|
2021-11-27 11:38:14 +01:00
|
|
|
zoom(2, 3) -= e->angleDelta().y() / 1000. * zoom(2, 3);
|
|
|
|
zoom.optimize();
|
2021-11-13 17:53:21 +01:00
|
|
|
updateViewMatrix();
|
2021-09-20 20:36:29 +02:00
|
|
|
update();
|
|
|
|
}
|