X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=src%2Fcanvas.cpp;h=dd645a538838f790a1ea61e75ffbe67f3762187b;hb=refs%2Fheads%2Fupstream-master;hp=346890751b80e02fb2b2af22332d43017d1b042f;hpb=97cf902b8751a7709f4f92bc34efd3ef0060104e;p=fstl diff --git a/src/canvas.cpp b/src/canvas.cpp index 3468907..dd645a5 100644 --- a/src/canvas.cpp +++ b/src/canvas.cpp @@ -1,13 +1,16 @@ #include #include +#include + #include "canvas.h" +#include "backdrop.h" #include "glmesh.h" #include "mesh.h" Canvas::Canvas(const QGLFormat& format, QWidget *parent) : QGLWidget(format, parent), mesh(NULL), - scale(1), tilt(90), yaw(0) + scale(1), zoom(1), tilt(90), yaw(0), status(" ") { // Nothing to do here } @@ -28,28 +31,58 @@ void Canvas::load_mesh(Mesh* m) pow(m->ymax() - m->ymin(), 2) + pow(m->zmax() - m->zmin(), 2)); + // Reset other camera parameters + zoom = 1; + yaw = 0; + tilt = 90; + update(); delete m; } +void Canvas::set_status(const QString &s) +{ + status = s; + update(); +} + +void Canvas::clear_status() +{ + status = ""; + update(); +} + void Canvas::initializeGL() { + initializeGLFunctions(); + mesh_shader.addShaderFromSourceFile(QGLShader::Vertex, ":/gl/mesh.vert"); mesh_shader.addShaderFromSourceFile(QGLShader::Fragment, ":/gl/mesh.frag"); mesh_shader.link(); - glClearColor(0.0, 0.0, 0.0, 0.0); - glEnable(GL_DEPTH_TEST); + backdrop = new Backdrop(); } -void Canvas::paintGL() +void Canvas::paintEvent(QPaintEvent *event) { + Q_UNUSED(event); + + 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; + + QPainter painter(this); + painter.setRenderHint(QPainter::Antialiasing); + painter.drawText(10, height() - 10, status); } + void Canvas::draw_mesh() { mesh_shader.bind(); @@ -62,6 +95,9 @@ void Canvas::draw_mesh() mesh_shader.uniformLocation("view_matrix"), 1, GL_FALSE, view_matrix().data()); + // Compensate for z-flattening when zooming + glUniform1f(mesh_shader.uniformLocation("zoom"), 1/zoom); + // Find and enable the attribute location for vertex position const GLuint vp = mesh_shader.attributeLocation("vertex_position"); glEnableVertexAttribArray(vp); @@ -89,18 +125,20 @@ QMatrix4x4 Canvas::view_matrix() const QMatrix4x4 m; if (width() > height()) { - m.scale(height() / float(width()), 1, 0.5); + m.scale(-height() / float(width()), 1, 0.5); } else { - m.scale(1, width() / float(height()), 0.5); + m.scale(-1, width() / float(height()), 0.5); } + m.scale(zoom, zoom, 1); return m; } void Canvas::mousePressEvent(QMouseEvent* event) { - if (event->button() == Qt::LeftButton) + if (event->button() == Qt::LeftButton || + event->button() == Qt::RightButton) { mouse_pos = event->pos(); setCursor(Qt::ClosedHandCursor); @@ -109,7 +147,8 @@ void Canvas::mousePressEvent(QMouseEvent* event) void Canvas::mouseReleaseEvent(QMouseEvent* event) { - if (event->button() == Qt::LeftButton) + if (event->button() == Qt::LeftButton || + event->button() == Qt::RightButton) { unsetCursor(); } @@ -117,13 +156,50 @@ void Canvas::mouseReleaseEvent(QMouseEvent* event) void Canvas::mouseMoveEvent(QMouseEvent* event) { + auto p = event->pos(); + auto d = p - mouse_pos; + if (event->buttons() & Qt::LeftButton) { - auto p = event->pos(); - auto d = p - mouse_pos; - yaw = fmod(yaw + d.x(), 360); + yaw = fmod(yaw - d.x(), 360); tilt = fmax(0, fmin(180, tilt - d.y())); - mouse_pos = p; update(); } + else if (event->buttons() & Qt::RightButton) + { + center = transform_matrix().inverted() * + view_matrix().inverted() * + QVector3D(-d.x() / (0.5*width()), + d.y() / (0.5*height()), 0); + update(); + } + mouse_pos = p; +} + +void Canvas::wheelEvent(QWheelEvent *event) +{ + // Find GL position before the zoom operation + // (to zoom about mouse cursor) + auto p = event->pos(); + 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) + { + for (int i=0; i > event->delta(); --i) + zoom *= 1.001; + } + else if (event->delta() > 0) + { + for (int i=0; i < event->delta(); ++i) + zoom /= 1.001; + } + + // Then find the cursor's GL position post-zoom and adjust center. + QVector3D b = transform_matrix().inverted() * + view_matrix().inverted() * v; + center += b - a; + update(); }