11 Canvas::Canvas(const QGLFormat& format, QWidget *parent)
12 : QGLWidget(format, parent), mesh(NULL),
13 scale(1), zoom(1), tilt(90), yaw(0), status(" ")
23 void Canvas::load_mesh(Mesh* m)
26 center = QVector3D(m->xmin() + m->xmax(),
27 m->ymin() + m->ymax(),
28 m->zmin() + m->zmax()) / 2;
30 pow(m->xmax() - m->xmin(), 2) +
31 pow(m->ymax() - m->ymin(), 2) +
32 pow(m->zmax() - m->zmin(), 2));
34 // Reset other camera parameters
44 void Canvas::set_status(const QString &s)
50 void Canvas::clear_status()
56 void Canvas::initializeGL()
58 initializeGLFunctions();
60 mesh_shader.addShaderFromSourceFile(QGLShader::Vertex, ":/gl/mesh.vert");
61 mesh_shader.addShaderFromSourceFile(QGLShader::Fragment, ":/gl/mesh.frag");
64 backdrop = new Backdrop();
67 void Canvas::paintEvent(QPaintEvent *event)
71 glClearColor(0.0, 0.0, 0.0, 0.0);
72 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
73 glEnable(GL_DEPTH_TEST);
76 if (mesh) draw_mesh();
78 if (status.isNull()) return;
80 QPainter painter(this);
81 painter.setRenderHint(QPainter::Antialiasing);
82 painter.drawText(10, height() - 10, status);
86 void Canvas::draw_mesh()
90 // Load the transform and view matrices into the shader
92 mesh_shader.uniformLocation("transform_matrix"),
93 1, GL_FALSE, transform_matrix().data());
95 mesh_shader.uniformLocation("view_matrix"),
96 1, GL_FALSE, view_matrix().data());
98 // Compensate for z-flattening when zooming
99 glUniform1f(mesh_shader.uniformLocation("zoom"), 1/zoom);
101 // Find and enable the attribute location for vertex position
102 const GLuint vp = mesh_shader.attributeLocation("vertex_position");
103 glEnableVertexAttribArray(vp);
105 // Then draw the mesh with that vertex position
108 // Clean up state machine
109 glDisableVertexAttribArray(vp);
110 mesh_shader.release();
113 QMatrix4x4 Canvas::transform_matrix() const
116 m.rotate(tilt, QVector3D(1, 0, 0));
117 m.rotate(yaw, QVector3D(0, 0, 1));
119 m.translate(-center);
123 QMatrix4x4 Canvas::view_matrix() const
126 if (width() > height())
128 m.scale(-height() / float(width()), 1, 0.5);
132 m.scale(-1, width() / float(height()), 0.5);
134 m.scale(zoom, zoom, 1);
138 void Canvas::mousePressEvent(QMouseEvent* event)
140 if (event->button() == Qt::LeftButton ||
141 event->button() == Qt::RightButton)
143 mouse_pos = event->pos();
144 setCursor(Qt::ClosedHandCursor);
148 void Canvas::mouseReleaseEvent(QMouseEvent* event)
150 if (event->button() == Qt::LeftButton ||
151 event->button() == Qt::RightButton)
157 void Canvas::mouseMoveEvent(QMouseEvent* event)
159 auto p = event->pos();
160 auto d = p - mouse_pos;
162 if (event->buttons() & Qt::LeftButton)
164 yaw = fmod(yaw - d.x(), 360);
165 tilt = fmax(0, fmin(180, tilt - d.y()));
168 else if (event->buttons() & Qt::RightButton)
170 center = transform_matrix().inverted() *
171 view_matrix().inverted() *
172 QVector3D(-d.x() / (0.5*width()),
173 d.y() / (0.5*height()), 0);
179 void Canvas::wheelEvent(QWheelEvent *event)
181 // Find GL position before the zoom operation
182 // (to zoom about mouse cursor)
183 auto p = event->pos();
184 QVector3D v(1 - p.x() / (0.5*width()),
185 p.y() / (0.5*height()) - 1, 0);
186 QVector3D a = transform_matrix().inverted() *
187 view_matrix().inverted() * v;
189 if (event->delta() < 0)
191 for (int i=0; i > event->delta(); --i)
194 else if (event->delta() > 0)
196 for (int i=0; i < event->delta(); ++i)
200 // Then find the cursor's GL position post-zoom and adjust center.
201 QVector3D b = transform_matrix().inverted() *
202 view_matrix().inverted() * v;