X-Git-Url: https://git.sur5r.net/?p=fstl;a=blobdiff_plain;f=src%2Fcanvas.cpp;h=b42a2be85957b2679696a0029c4371019c0a9f22;hp=dd645a538838f790a1ea61e75ffbe67f3762187b;hb=refs%2Fheads%2Fupstream;hpb=967d178c4343c689c728571bb10d5c94ab8d9d13 diff --git a/src/canvas.cpp b/src/canvas.cpp index dd645a5..4da41a7 100644 --- a/src/canvas.cpp +++ b/src/canvas.cpp @@ -1,41 +1,89 @@ #include -#include #include #include "canvas.h" #include "backdrop.h" +#include "axis.h" #include "glmesh.h" #include "mesh.h" -Canvas::Canvas(const QGLFormat& format, QWidget *parent) - : QGLWidget(format, parent), mesh(NULL), - scale(1), zoom(1), tilt(90), yaw(0), status(" ") +const float Canvas::P_PERSPECTIVE = 0.25f; +const float Canvas::P_ORTHOGRAPHIC = 0.0f; + +Canvas::Canvas(const QSurfaceFormat& format, QWidget *parent) + : QOpenGLWidget(parent), mesh(nullptr), + scale(1), zoom(1), tilt(90), yaw(0), + anim(this, "perspective"), status(" "), + meshInfo("") { - // Nothing to do here + setFormat(format); + QFile styleFile(":/qt/style.qss"); + styleFile.open( QFile::ReadOnly ); + setStyleSheet(styleFile.readAll()); + + anim.setDuration(100); } Canvas::~Canvas() { + makeCurrent(); delete mesh; + delete mesh_vertshader; + delete backdrop; + delete axis; + doneCurrent(); +} + +void Canvas::view_anim(float v) +{ + anim.setStartValue(perspective); + anim.setEndValue(v); + anim.start(); +} + +void Canvas::view_perspective(float p, bool animate){ + if(animate) + { + view_anim(p); + } + else + { + set_perspective(p); + } +} + +void Canvas::draw_axes(bool d) +{ + drawAxes = d; + update(); +} + +void Canvas::invert_zoom(bool d) +{ + invertZoom = d; + update(); } -void Canvas::load_mesh(Mesh* m) +void Canvas::load_mesh(Mesh* m, bool is_reload) { + delete mesh; mesh = new GLMesh(m); - center = QVector3D(m->xmin() + m->xmax(), - m->ymin() + m->ymax(), - m->zmin() + m->zmax()) / 2; - scale = 2 / sqrt( - pow(m->xmax() - m->xmin(), 2) + - pow(m->ymax() - m->ymin(), 2) + - pow(m->zmax() - m->zmin(), 2)); - - // Reset other camera parameters - zoom = 1; - yaw = 0; - tilt = 90; + QVector3D lower(m->xmin(), m->ymin(), m->zmin()); + QVector3D upper(m->xmax(), m->ymax(), m->zmax()); + if (!is_reload) + { + center = (lower + upper) / 2; + scale = 2 / (upper - lower).length(); + // Reset other camera parameters + zoom = 1; + yaw = 0; + tilt = 90; + } + meshInfo = QStringLiteral("Triangles: %1\nX: [%2, %3]\nY: [%4, %5]\nZ: [%6, %7]").arg(m->triCount()); + for(int dIdx = 0; dIdx < 3; dIdx++) meshInfo = meshInfo.arg(lower[dIdx]).arg(upper[dIdx]); + axis->setScale(lower, upper); update(); delete m; @@ -47,6 +95,18 @@ void Canvas::set_status(const QString &s) update(); } +void Canvas::set_perspective(float p) +{ + perspective = p; + update(); +} + +void Canvas::set_drawMode(enum DrawMode mode) +{ + drawMode = mode; + update(); +} + void Canvas::clear_status() { status = ""; @@ -55,72 +115,107 @@ void Canvas::clear_status() void Canvas::initializeGL() { - initializeGLFunctions(); + initializeOpenGLFunctions(); - mesh_shader.addShaderFromSourceFile(QGLShader::Vertex, ":/gl/mesh.vert"); - mesh_shader.addShaderFromSourceFile(QGLShader::Fragment, ":/gl/mesh.frag"); + mesh_vertshader = new QOpenGLShader(QOpenGLShader::Vertex); + mesh_vertshader->compileSourceFile(":/gl/mesh.vert"); + mesh_shader.addShader(mesh_vertshader); + mesh_shader.addShaderFromSourceFile(QOpenGLShader::Fragment, ":/gl/mesh.frag"); mesh_shader.link(); + mesh_wireframe_shader.addShader(mesh_vertshader); + mesh_wireframe_shader.addShaderFromSourceFile(QOpenGLShader::Fragment, ":/gl/mesh_wireframe.frag"); + mesh_wireframe_shader.link(); + mesh_surfaceangle_shader.addShader(mesh_vertshader); + mesh_surfaceangle_shader.addShaderFromSourceFile(QOpenGLShader::Fragment, ":/gl/mesh_surfaceangle.frag"); + mesh_surfaceangle_shader.link(); backdrop = new Backdrop(); + axis = new Axis(); } -void Canvas::paintEvent(QPaintEvent *event) -{ - Q_UNUSED(event); +void Canvas::paintGL() +{ glClearColor(0.0, 0.0, 0.0, 0.0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glEnable(GL_DEPTH_TEST); - backdrop->draw(); if (mesh) draw_mesh(); - - if (status.isNull()) return; + if (drawAxes) axis->draw(transform_matrix(), view_matrix(), + orient_matrix(), aspect_matrix(), width() / float(height())); QPainter painter(this); painter.setRenderHint(QPainter::Antialiasing); - painter.drawText(10, height() - 10, status); + float textHeight = painter.fontInfo().pointSize(); + if (drawAxes) painter.drawText(QRect(10, textHeight, width(), height()), meshInfo); + painter.drawText(10, height() - textHeight, status); } - void Canvas::draw_mesh() { - mesh_shader.bind(); + QOpenGLShaderProgram* selected_mesh_shader = NULL; + if(drawMode == wireframe) + { + selected_mesh_shader = &mesh_wireframe_shader; + glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + } + else + { + if(drawMode == shaded) + { + selected_mesh_shader = &mesh_shader; + } + else + { + selected_mesh_shader = &mesh_surfaceangle_shader; + } + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + } + + selected_mesh_shader->bind(); // Load the transform and view matrices into the shader glUniformMatrix4fv( - mesh_shader.uniformLocation("transform_matrix"), + selected_mesh_shader->uniformLocation("transform_matrix"), 1, GL_FALSE, transform_matrix().data()); glUniformMatrix4fv( - mesh_shader.uniformLocation("view_matrix"), + selected_mesh_shader->uniformLocation("view_matrix"), 1, GL_FALSE, view_matrix().data()); // Compensate for z-flattening when zooming - glUniform1f(mesh_shader.uniformLocation("zoom"), 1/zoom); + glUniform1f(selected_mesh_shader->uniformLocation("zoom"), 1/zoom); // Find and enable the attribute location for vertex position - const GLuint vp = mesh_shader.attributeLocation("vertex_position"); + const GLuint vp = selected_mesh_shader->attributeLocation("vertex_position"); glEnableVertexAttribArray(vp); // Then draw the mesh with that vertex position mesh->draw(vp); + // Reset draw mode for the background and anything else that needs to be drawn + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + // Clean up state machine glDisableVertexAttribArray(vp); - mesh_shader.release(); + selected_mesh_shader->release(); } - -QMatrix4x4 Canvas::transform_matrix() const +QMatrix4x4 Canvas::orient_matrix() const { QMatrix4x4 m; m.rotate(tilt, QVector3D(1, 0, 0)); m.rotate(yaw, QVector3D(0, 0, 1)); + //We want the x axis to the right, and the z axis up + m.scale(-1, 1, -1); + return m; +} +QMatrix4x4 Canvas::transform_matrix() const +{ + QMatrix4x4 m = orient_matrix(); m.scale(scale); m.translate(-center); return m; } - -QMatrix4x4 Canvas::view_matrix() const +QMatrix4x4 Canvas::aspect_matrix() const { QMatrix4x4 m; if (width() > height()) @@ -131,7 +226,13 @@ QMatrix4x4 Canvas::view_matrix() const { m.scale(-1, width() / float(height()), 0.5); } + return m; +} +QMatrix4x4 Canvas::view_matrix() const +{ + QMatrix4x4 m = aspect_matrix(); m.scale(zoom, zoom, 1); + m(3, 2) = perspective; return m; } @@ -159,10 +260,11 @@ void Canvas::mouseMoveEvent(QMouseEvent* event) auto p = event->pos(); auto d = p - mouse_pos; + if (event->buttons() & Qt::LeftButton) { yaw = fmod(yaw - d.x(), 360); - tilt = fmax(0, fmin(180, tilt - d.y())); + tilt = fmod(tilt - d.y(), 360); update(); } else if (event->buttons() & Qt::RightButton) @@ -180,21 +282,27 @@ void Canvas::wheelEvent(QWheelEvent *event) { // Find GL position before the zoom operation // (to zoom about mouse cursor) - auto p = event->pos(); + auto p = event->position(); QVector3D v(1 - p.x() / (0.5*width()), p.y() / (0.5*height()) - 1, 0); QVector3D a = transform_matrix().inverted() * view_matrix().inverted() * v; - if (event->delta() < 0) + if (event->angleDelta().y() < 0) { - for (int i=0; i > event->delta(); --i) - zoom *= 1.001; + for (int i=0; i > event->angleDelta().y(); --i) + if (invertZoom) + zoom /= 1.001; + else + zoom *= 1.001; } - else if (event->delta() > 0) + else if (event->angleDelta().y() > 0) { - for (int i=0; i < event->delta(); ++i) - zoom /= 1.001; + for (int i=0; i < event->angleDelta().y(); ++i) + if (invertZoom) + zoom *= 1.001; + else + zoom /= 1.001; } // Then find the cursor's GL position post-zoom and adjust center. @@ -203,3 +311,8 @@ void Canvas::wheelEvent(QWheelEvent *event) center += b - a; update(); } + +void Canvas::resizeGL(int width, int height) +{ + glViewport(0, 0, width, height); +}