From 03da9c5cf9fb6a0572814cd5332e5438cc21b00c Mon Sep 17 00:00:00 2001 From: ccolin Date: Mon, 4 Jan 2021 17:37:49 +0100 Subject: [PATCH] replace the orbital cam by a free flying cam --- src/opengl_widget.cc | 80 +++++++++++++++++++++++++++++++++++--------- src/opengl_widget.hh | 16 +++++++-- 2 files changed, 78 insertions(+), 18 deletions(-) diff --git a/src/opengl_widget.cc b/src/opengl_widget.cc index 582bf3e..92166ac 100644 --- a/src/opengl_widget.cc +++ b/src/opengl_widget.cc @@ -24,13 +24,21 @@ OpenGLWidget *OpenGLWidget::instance = nullptr; OpenGLWidget::OpenGLWidget(QWidget *parent) - :QOpenGLWidget(parent) { + :QOpenGLWidget(parent), + move_timer(this) { OpenGLWidget::instance = this; QSurfaceFormat format; format.setProfile(QSurfaceFormat::CoreProfile); format.setDepthBufferSize(24); format.setSamples(4); setFormat(format); + setFocusPolicy(Qt::StrongFocus); + trans.translate(0, -10, -10); + rot.rotate(30, QVector3D(1, 0, 0)); + rot_start = rot; + move_timer.setTimerType(Qt::PreciseTimer); + connect(&move_timer, &QTimer::timeout, this, &OpenGLWidget::move); + move_timer.start(16); } @@ -179,9 +187,7 @@ void OpenGLWidget::paintGL() { glEnable(GL_CULL_FACE); glEnable(GL_DEPTH_TEST); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - QMatrix4x4 trans; - trans.translate(0, 0, -cam_dist); - QMatrix4x4 view = trans * rot; + QMatrix4x4 view = rot * trans; glDepthMask(GL_FALSE); glDepthFunc(GL_LEQUAL); @@ -230,18 +236,62 @@ void OpenGLWidget::mouseReleaseEvent(QMouseEvent *e) { void OpenGLWidget::mouseMoveEvent(QMouseEvent *e) { - if (e->buttons() & Qt::LeftButton) { - QPoint delta = e->pos() - mouse_pos; - rot = rot_start; - rot.rotate(delta.x() / 5., 0, 1, 0); - rot.rotate(delta.y() / 5., QVector3D(1, 0, 0) * rot); - update(); - } + if (!(e->buttons() & Qt::LeftButton)) return; + QPoint delta = e->pos() - mouse_pos; + rot = rot_start; + rot.rotate(delta.x() / 5., 0, 1, 0); + rot.rotate(delta.y() / 5., QVector3D(1, 0, 0) * rot); + update(); } -void OpenGLWidget::wheelEvent(QWheelEvent *e) { - cam_dist -= e->angleDelta().y() / 1000. * cam_dist; +bool OpenGLWidget::keyEvent(QKeyEvent *e, bool press) { + if (e->isAutoRepeat()) return false; + /* would do wasd if qt had proper support for layout-independent + input, but it doesnt :< */ + switch (e->key()) { + case Qt::Key_Up: + move_forward = press; + break; + case Qt::Key_Down: + move_back = press; + break; + case Qt::Key_Left: + move_left = press; + break; + case Qt::Key_Right: + move_right = press; + break; + default: + return false; + } + update(); + return true; +} + + +void OpenGLWidget::keyPressEvent(QKeyEvent *e) { + if (!keyEvent(e, true)) QOpenGLWidget::keyPressEvent(e); +} + + +void OpenGLWidget::keyReleaseEvent(QKeyEvent *e) { + if (!keyEvent(e, false)) QOpenGLWidget::keyReleaseEvent(e); +} + + +void OpenGLWidget::focusOutEvent(QFocusEvent *e) { + Q_UNUSED(e); + move_forward = move_back = move_left = move_right = false; +} + + +void OpenGLWidget::move() { + QMatrix4x4 rotation = rot.inverted(); + if (move_forward) trans.translate(-(rotation * QVector3D(0, 0, -1))); + if (move_back) trans.translate(-(rotation * QVector3D(0, 0, 1))); + if (move_left) trans.translate(-(rotation * QVector3D(-1, 0, 0))); + if (move_right) trans.translate(-(rotation * QVector3D(1, 0, 0))); update(); } @@ -261,9 +311,7 @@ QOpenGLShaderProgram *OpenGLWidget::getLineProgram() { bool OpenGLWidget::project(const QVector3D &p, QPoint &point) const { - QMatrix4x4 trans; - trans.translate(0, 0, -cam_dist); - QMatrix4x4 view = trans * rot; + QMatrix4x4 view = rot * trans; QVector3D projected = proj * view * p; if (projected.x() < -1 || projected.x() > 1 || projected.y() < -1 || projected.y() > 1 diff --git a/src/opengl_widget.hh b/src/opengl_widget.hh index abe226f..65c09b2 100644 --- a/src/opengl_widget.hh +++ b/src/opengl_widget.hh @@ -9,6 +9,7 @@ #include #include #include +#include #define FOV 70 @@ -26,8 +27,13 @@ class OpenGLWidget : public QOpenGLWidget, public QOpenGLExtraFunctions { Q_OBJECT QMatrix4x4 rot, rot_start, proj; - GLfloat cam_dist = 1; + QMatrix4x4 trans; QPoint mouse_pos; + QTimer move_timer; + bool move_forward = false; + bool move_back = false; + bool move_left = false; + bool move_right = false; QOpenGLShaderProgram main_program; QOpenGLShaderProgram skybox_program; @@ -39,14 +45,20 @@ class OpenGLWidget : public QOpenGLWidget, public QOpenGLExtraFunctions { void loadSkybox(); void loadGround(); + bool keyEvent(QKeyEvent *e, bool press); const Painter *painter = nullptr; +private slots: + void move(); + protected: virtual void mousePressEvent(QMouseEvent *e); virtual void mouseReleaseEvent(QMouseEvent *e); virtual void mouseMoveEvent(QMouseEvent *e); - virtual void wheelEvent(QWheelEvent *e); + virtual void keyPressEvent(QKeyEvent *e); + virtual void keyReleaseEvent(QKeyEvent *e); + virtual void focusOutEvent(QFocusEvent *e); public: static OpenGLWidget *instance;