#include <QMouseEvent>
-#include <QDebug>
#include <cmath>
#include "canvas.h"
#include "backdrop.h"
+#include "axis.h"
#include "glmesh.h"
#include "mesh.h"
-Canvas::Canvas(const QGLFormat& format, QWidget *parent)
- : QGLWidget(format, parent), mesh(NULL),
+const float Canvas::P_PERSPECTIVE = 0.25f;
+const float Canvas::P_ORTHOGRAPHIC = 0.0f;
+
+Canvas::Canvas(const QSurfaceFormat& format, QWidget *parent)
+ : QOpenGLWidget(parent), mesh(nullptr),
scale(1), zoom(1), tilt(90), yaw(0),
- perspective(0.25), anim(this, "perspective"), status(" ")
+ anim(this, "perspective"), status(" "),
+ meshInfo("")
{
+ setFormat(format);
QFile styleFile(":/qt/style.qss");
styleFile.open( QFile::ReadOnly );
setStyleSheet(styleFile.readAll());
Canvas::~Canvas()
{
+ makeCurrent();
delete mesh;
+ delete mesh_vertshader;
+ delete backdrop;
+ delete axis;
+ doneCurrent();
}
void Canvas::view_anim(float v)
anim.start();
}
-void Canvas::view_orthographic()
+void Canvas::view_perspective(float p, bool animate){
+ if(animate)
+ {
+ view_anim(p);
+ }
+ else
+ {
+ set_perspective(p);
+ }
+}
+
+void Canvas::draw_axes(bool d)
{
- view_anim(0);
+ drawAxes = d;
+ update();
}
-void Canvas::view_perspective()
+void Canvas::invert_zoom(bool d)
{
- view_anim(0.25);
+ invertZoom = d;
+ update();
}
void Canvas::load_mesh(Mesh* m, bool is_reload)
{
+ delete mesh;
mesh = new GLMesh(m);
-
+ QVector3D lower(m->xmin(), m->ymin(), m->zmin());
+ QVector3D upper(m->xmax(), m->ymax(), m->zmax());
if (!is_reload)
{
- QVector3D lower(m->xmin(), m->ymin(), m->zmin());
- QVector3D upper(m->xmax(), m->ymax(), m->zmax());
center = (lower + upper) / 2;
scale = 2 / (upper - lower).length();
yaw = 0;
tilt = 90;
}
-
+ meshInfo = QStringLiteral("Triangles: %1\nX: [%2, %3]\nY: [%4, %5]\nZ: [%6, %7]").arg(m->triCount());
+ for(int dIdx = 0; dIdx < 3; dIdx++) meshInfo = meshInfo.arg(lower[dIdx]).arg(upper[dIdx]);
+ axis->setScale(lower, upper);
update();
delete m;
update();
}
+void Canvas::set_drawMode(enum DrawMode mode)
+{
+ drawMode = mode;
+ update();
+}
+
void Canvas::clear_status()
{
status = "";
void Canvas::initializeGL()
{
- initializeGLFunctions();
+ initializeOpenGLFunctions();
- mesh_shader.addShaderFromSourceFile(QGLShader::Vertex, ":/gl/mesh.vert");
- mesh_shader.addShaderFromSourceFile(QGLShader::Fragment, ":/gl/mesh.frag");
+ mesh_vertshader = new QOpenGLShader(QOpenGLShader::Vertex);
+ mesh_vertshader->compileSourceFile(":/gl/mesh.vert");
+ mesh_shader.addShader(mesh_vertshader);
+ mesh_shader.addShaderFromSourceFile(QOpenGLShader::Fragment, ":/gl/mesh.frag");
mesh_shader.link();
+ mesh_wireframe_shader.addShader(mesh_vertshader);
+ mesh_wireframe_shader.addShaderFromSourceFile(QOpenGLShader::Fragment, ":/gl/mesh_wireframe.frag");
+ mesh_wireframe_shader.link();
+ mesh_surfaceangle_shader.addShader(mesh_vertshader);
+ mesh_surfaceangle_shader.addShaderFromSourceFile(QOpenGLShader::Fragment, ":/gl/mesh_surfaceangle.frag");
+ mesh_surfaceangle_shader.link();
backdrop = new Backdrop();
+ axis = new Axis();
}
-void Canvas::paintEvent(QPaintEvent *event)
-{
- Q_UNUSED(event);
+void Canvas::paintGL()
+{
glClearColor(0.0, 0.0, 0.0, 0.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_DEPTH_TEST);
-
backdrop->draw();
if (mesh) draw_mesh();
-
- if (status.isNull()) return;
+ if (drawAxes) axis->draw(transform_matrix(), view_matrix(),
+ orient_matrix(), aspect_matrix(), width() / float(height()));
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing);
- painter.drawText(10, height() - 10, status);
+ float textHeight = painter.fontInfo().pointSize();
+ if (drawAxes) painter.drawText(QRect(10, textHeight, width(), height()), meshInfo);
+ painter.drawText(10, height() - textHeight, status);
}
-
void Canvas::draw_mesh()
{
- mesh_shader.bind();
+ QOpenGLShaderProgram* selected_mesh_shader = NULL;
+ if(drawMode == wireframe)
+ {
+ selected_mesh_shader = &mesh_wireframe_shader;
+ glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
+ }
+ else
+ {
+ if(drawMode == shaded)
+ {
+ selected_mesh_shader = &mesh_shader;
+ }
+ else
+ {
+ selected_mesh_shader = &mesh_surfaceangle_shader;
+ }
+ glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+ }
+
+ selected_mesh_shader->bind();
// Load the transform and view matrices into the shader
glUniformMatrix4fv(
- mesh_shader.uniformLocation("transform_matrix"),
+ selected_mesh_shader->uniformLocation("transform_matrix"),
1, GL_FALSE, transform_matrix().data());
glUniformMatrix4fv(
- mesh_shader.uniformLocation("view_matrix"),
+ selected_mesh_shader->uniformLocation("view_matrix"),
1, GL_FALSE, view_matrix().data());
// Compensate for z-flattening when zooming
- glUniform1f(mesh_shader.uniformLocation("zoom"), 1/zoom);
+ glUniform1f(selected_mesh_shader->uniformLocation("zoom"), 1/zoom);
// Find and enable the attribute location for vertex position
- const GLuint vp = mesh_shader.attributeLocation("vertex_position");
+ const GLuint vp = selected_mesh_shader->attributeLocation("vertex_position");
glEnableVertexAttribArray(vp);
// Then draw the mesh with that vertex position
mesh->draw(vp);
+ // Reset draw mode for the background and anything else that needs to be drawn
+ glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+
// Clean up state machine
glDisableVertexAttribArray(vp);
- mesh_shader.release();
+ selected_mesh_shader->release();
}
-
-QMatrix4x4 Canvas::transform_matrix() const
+QMatrix4x4 Canvas::orient_matrix() const
{
QMatrix4x4 m;
m.rotate(tilt, QVector3D(1, 0, 0));
m.rotate(yaw, QVector3D(0, 0, 1));
- m.scale(-scale, scale, -scale);
+ //We want the x axis to the right, and the z axis up
+ m.scale(-1, 1, -1);
+ return m;
+}
+QMatrix4x4 Canvas::transform_matrix() const
+{
+ QMatrix4x4 m = orient_matrix();
+ m.scale(scale);
m.translate(-center);
return m;
}
-
-QMatrix4x4 Canvas::view_matrix() const
+QMatrix4x4 Canvas::aspect_matrix() const
{
QMatrix4x4 m;
if (width() > height())
{
m.scale(-1, width() / float(height()), 0.5);
}
+ return m;
+}
+QMatrix4x4 Canvas::view_matrix() const
+{
+ QMatrix4x4 m = aspect_matrix();
m.scale(zoom, zoom, 1);
m(3, 2) = perspective;
return m;
{
// Find GL position before the zoom operation
// (to zoom about mouse cursor)
- auto p = event->pos();
+ auto p = event->position();
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)
+ if (event->angleDelta().y() < 0)
{
- for (int i=0; i > event->delta(); --i)
- zoom *= 1.001;
+ for (int i=0; i > event->angleDelta().y(); --i)
+ if (invertZoom)
+ zoom /= 1.001;
+ else
+ zoom *= 1.001;
}
- else if (event->delta() > 0)
+ else if (event->angleDelta().y() > 0)
{
- for (int i=0; i < event->delta(); ++i)
- zoom /= 1.001;
+ for (int i=0; i < event->angleDelta().y(); ++i)
+ if (invertZoom)
+ zoom *= 1.001;
+ else
+ zoom /= 1.001;
}
// Then find the cursor's GL position post-zoom and adjust center.