]> git.sur5r.net Git - fstl/blob - src/canvas.cpp
Cross-thread lambda functions fail on win32
[fstl] / src / canvas.cpp
1 #include <QMouseEvent>
2 #include <QDebug>
3
4 #include <cmath>
5
6 #include "canvas.h"
7 #include "backdrop.h"
8 #include "glmesh.h"
9 #include "mesh.h"
10
11 Canvas::Canvas(const QGLFormat& format, QWidget *parent)
12     : QGLWidget(format, parent), mesh(NULL),
13       scale(1), tilt(90), yaw(0), status(" ")
14 {
15     // Nothing to do here
16 }
17
18 Canvas::~Canvas()
19 {
20     delete mesh;
21 }
22
23 void Canvas::load_mesh(Mesh* m)
24 {
25     mesh = new GLMesh(m);
26     center = QVector3D(m->xmin() + m->xmax(),
27                        m->ymin() + m->ymax(),
28                        m->zmin() + m->zmax()) / 2;
29     scale = 2 / sqrt(
30                 pow(m->xmax() - m->xmin(), 2) +
31                 pow(m->ymax() - m->ymin(), 2) +
32                 pow(m->zmax() - m->zmin(), 2));
33     update();
34
35     delete m;
36 }
37
38 void Canvas::set_status(const QString &s)
39 {
40     status = s;
41     update();
42 }
43
44 void Canvas::clear_status()
45 {
46     status = "";
47     update();
48 }
49
50 void Canvas::initializeGL()
51 {
52     mesh_shader.addShaderFromSourceFile(QGLShader::Vertex, ":/gl/mesh.vert");
53     mesh_shader.addShaderFromSourceFile(QGLShader::Fragment, ":/gl/mesh.frag");
54     mesh_shader.link();
55
56     backdrop = new Backdrop();
57 }
58
59 void Canvas::paintEvent(QPaintEvent *event)
60 {
61     Q_UNUSED(event);
62
63     glClearColor(0.0, 0.0, 0.0, 0.0);
64     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
65     glEnable(GL_DEPTH_TEST);
66
67     backdrop->draw();
68     if (mesh)  draw_mesh();
69
70     if (status.isNull())    return;
71
72     QPainter painter(this);
73     painter.setRenderHint(QPainter::Antialiasing);
74     painter.drawText(10, height() - 10, status);
75 }
76
77
78 void Canvas::draw_mesh()
79 {
80     mesh_shader.bind();
81
82     // Load the transform and view matrices into the shader
83     glUniformMatrix4fv(
84                 mesh_shader.uniformLocation("transform_matrix"),
85                 1, GL_FALSE, transform_matrix().data());
86     glUniformMatrix4fv(
87                 mesh_shader.uniformLocation("view_matrix"),
88                 1, GL_FALSE, view_matrix().data());
89
90     // Find and enable the attribute location for vertex position
91     const GLuint vp = mesh_shader.attributeLocation("vertex_position");
92     glEnableVertexAttribArray(vp);
93
94     // Then draw the mesh with that vertex position
95     mesh->draw(vp);
96
97     // Clean up state machine
98     glDisableVertexAttribArray(vp);
99     mesh_shader.release();
100 }
101
102 QMatrix4x4 Canvas::transform_matrix() const
103 {
104     QMatrix4x4 m;
105     m.rotate(tilt, QVector3D(1, 0, 0));
106     m.rotate(yaw,  QVector3D(0, 0, 1));
107     m.scale(scale);
108     m.translate(-center);
109     return m;
110 }
111
112 QMatrix4x4 Canvas::view_matrix() const
113 {
114     QMatrix4x4 m;
115     if (width() > height())
116     {
117         m.scale(-height() / float(width()), 1, 0.5);
118     }
119     else
120     {
121         m.scale(-1, width() / float(height()), 0.5);
122     }
123     return m;
124 }
125
126 void Canvas::mousePressEvent(QMouseEvent* event)
127 {
128     if (event->button() == Qt::LeftButton)
129     {
130         mouse_pos = event->pos();
131         setCursor(Qt::ClosedHandCursor);
132     }
133 }
134
135 void Canvas::mouseReleaseEvent(QMouseEvent* event)
136 {
137     if (event->button() == Qt::LeftButton)
138     {
139         unsetCursor();
140     }
141 }
142
143 void Canvas::mouseMoveEvent(QMouseEvent* event)
144 {
145     if (event->buttons() & Qt::LeftButton)
146     {
147         auto p = event->pos();
148         auto d = p - mouse_pos;
149         yaw = fmod(yaw - d.x(), 360);
150         tilt = fmax(0, fmin(180, tilt - d.y()));
151         mouse_pos = p;
152         update();
153     }
154 }