]> git.sur5r.net Git - fstl/blob - src/canvas.cpp
1539469949155de9eeb1b824bc97d2037134dbf0
[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), zoom(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     initializeGLFunctions();
53
54     mesh_shader.addShaderFromSourceFile(QGLShader::Vertex, ":/gl/mesh.vert");
55     mesh_shader.addShaderFromSourceFile(QGLShader::Fragment, ":/gl/mesh.frag");
56     mesh_shader.link();
57
58     backdrop = new Backdrop();
59 }
60
61 void Canvas::paintEvent(QPaintEvent *event)
62 {
63     Q_UNUSED(event);
64
65     glClearColor(0.0, 0.0, 0.0, 0.0);
66     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
67     glEnable(GL_DEPTH_TEST);
68
69     backdrop->draw();
70     if (mesh)  draw_mesh();
71
72     if (status.isNull())    return;
73
74     QPainter painter(this);
75     painter.setRenderHint(QPainter::Antialiasing);
76     painter.drawText(10, height() - 10, status);
77 }
78
79
80 void Canvas::draw_mesh()
81 {
82     mesh_shader.bind();
83
84     // Load the transform and view matrices into the shader
85     glUniformMatrix4fv(
86                 mesh_shader.uniformLocation("transform_matrix"),
87                 1, GL_FALSE, transform_matrix().data());
88     glUniformMatrix4fv(
89                 mesh_shader.uniformLocation("view_matrix"),
90                 1, GL_FALSE, view_matrix().data());
91
92     // Find and enable the attribute location for vertex position
93     const GLuint vp = mesh_shader.attributeLocation("vertex_position");
94     glEnableVertexAttribArray(vp);
95
96     // Then draw the mesh with that vertex position
97     mesh->draw(vp);
98
99     // Clean up state machine
100     glDisableVertexAttribArray(vp);
101     mesh_shader.release();
102 }
103
104 QMatrix4x4 Canvas::transform_matrix() const
105 {
106     QMatrix4x4 m;
107     m.rotate(tilt, QVector3D(1, 0, 0));
108     m.rotate(yaw,  QVector3D(0, 0, 1));
109     m.scale(scale);
110     m.translate(-center);
111     return m;
112 }
113
114 QMatrix4x4 Canvas::view_matrix() const
115 {
116     QMatrix4x4 m;
117     if (width() > height())
118     {
119         m.scale(-height() / float(width()), 1, 0.5);
120     }
121     else
122     {
123         m.scale(-1, width() / float(height()), 0.5);
124     }
125     m.scale(zoom, zoom, 1);
126     return m;
127 }
128
129 void Canvas::mousePressEvent(QMouseEvent* event)
130 {
131     if (event->button() == Qt::LeftButton ||
132         event->button() == Qt::RightButton)
133     {
134         mouse_pos = event->pos();
135         setCursor(Qt::ClosedHandCursor);
136     }
137 }
138
139 void Canvas::mouseReleaseEvent(QMouseEvent* event)
140 {
141     if (event->button() == Qt::LeftButton ||
142         event->button() == Qt::RightButton)
143     {
144         unsetCursor();
145     }
146 }
147
148 void Canvas::mouseMoveEvent(QMouseEvent* event)
149 {
150     auto p = event->pos();
151     auto d = p - mouse_pos;
152
153     if (event->buttons() & Qt::LeftButton)
154     {
155         yaw = fmod(yaw - d.x(), 360);
156         tilt = fmax(0, fmin(180, tilt - d.y()));
157         update();
158     }
159     else if (event->buttons() & Qt::RightButton)
160     {
161         qDebug() << d;
162         center = transform_matrix().inverted() *
163                  view_matrix().inverted() *
164                  QVector3D(-d.x() / (0.5*width()),
165                             d.y() / (0.5*height()), 0);
166         update();
167     }
168     mouse_pos = p;
169 }
170
171 void Canvas::wheelEvent(QWheelEvent *event)
172 {
173     if (event->delta() < 0)
174     {
175         for (int i=0; i > event->delta(); --i)
176             zoom *= 1.001;
177     }
178     else if (event->delta() > 0)
179     {
180         for (int i=0; i < event->delta(); ++i)
181             zoom /= 1.001;
182     }
183     update();
184 }