]> git.sur5r.net Git - fstl/blobdiff - src/canvas.cpp
Allow dropping of files onto window
[fstl] / src / canvas.cpp
index 91db4d71ebd33ae83e9dfd6fcf6606408c54627b..dd645a538838f790a1ea61e75ffbe67f3762187b 100644 (file)
@@ -10,7 +10,7 @@
 
 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
 }
@@ -30,6 +30,12 @@ void Canvas::load_mesh(Mesh* m)
                 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;
+
     update();
 
     delete m;
@@ -41,8 +47,16 @@ void Canvas::set_status(const QString &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();
@@ -61,10 +75,11 @@ void Canvas::paintEvent(QPaintEvent *event)
     backdrop->draw();
     if (mesh)  draw_mesh();
 
+    if (status.isNull())    return;
+
     QPainter painter(this);
     painter.setRenderHint(QPainter::Antialiasing);
-    if (!status.isNull())
-        painter.drawText(10, height() - 10, status);
+    painter.drawText(10, height() - 10, status);
 }
 
 
@@ -80,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);
@@ -107,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);
@@ -127,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();
     }
@@ -135,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();
 }