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