#include "mesh_viewer.h" #include #include #include #include MeshViewer::MeshViewer(QWidget *parent) : QOpenGLWidget(parent) { setMouseTracking(true); setFocus(); } void MeshViewer::updateViewMatrix() { view = trans * rot; } QSize MeshViewer::sizeHint() const { return QSize(640, 480); } void MeshViewer::initializeGL() { QOpenGLFunctions *glf = context()->functions(); #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); program.setUniformValue("wf_col", WIREFRAME_COLOR); glf->glClearColor(1, 1, 1, 0); glf->glEnable(GL_DEPTH_TEST); glf->glEnable(GL_MULTISAMPLE); qDebug("MeshViewer: initialization complete"); is_initialized = true; emit initialized(); } void MeshViewer::resizeGL(int w, int h) { proj.setToIdentity(); proj.perspective(FOV, (float) w/h, .01, 100); program.setUniformValue("proj", proj); update(); } void MeshViewer::paintGL() { // glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); QMatrix4x4 trans; program.bind(); program.setUniformValue("view", view); for (MeshView &m : meshes) { m.paint(program); } } void MeshViewer::addMesh(const MyMesh &mesh) { Q_ASSERT(isValid()); makeCurrent(); meshes.emplace_back(mesh, program); doneCurrent(); update(); } void MeshViewer::removeMesh(const MyMesh &mesh) { makeCurrent(); meshes.remove_if([&](const MeshView &mv) { return &mv.mesh == &mesh; }); doneCurrent(); update(); } void MeshViewer::updateForReal() { setEnabled(true); setVisible(true); update(); repaint(); makeCurrent(); paintGL(); doneCurrent(); } void MeshViewer::mousePressEvent(QMouseEvent *e) { if (e->button() == Qt::MiddleButton) { mouse_pos = e->pos(); } 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(); } } void MeshViewer::mouseReleaseEvent(QMouseEvent *e) { (void) e; rot_start = rot; } void MeshViewer::mouseMoveEvent(QMouseEvent *e) { if (e->buttons() & Qt::MiddleButton) { 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); updateViewMatrix(); update(); } } void MeshViewer::wheelEvent(QWheelEvent *e) { trans(2, 3) -= e->angleDelta().y() / 1000. * trans(2, 3); trans.optimize(); updateViewMatrix(); update(); }