From 333eca25eb5a36c898ed2163111923522705f6b5 Mon Sep 17 00:00:00 2001 From: Anakin Date: Thu, 2 Feb 2017 18:01:08 +0100 Subject: [PATCH] use class for camera handling, orbit does not work. Need to figure out why --- QtMeshViewer/Header/CameraInterface.h | 26 ++++ QtMeshViewer/Header/FreeCamera.h | 23 ++++ QtMeshViewer/Header/MoveCamera.h | 22 ++++ QtMeshViewer/Header/OglViewerWidget.h | 20 ++- QtMeshViewer/Header/OrbitCamera.h | 24 ++++ QtMeshViewer/Resources/Resources.qrc | 6 - QtMeshViewer/Resources/StyleSheet.txt | 24 ---- QtMeshViewer/Source/FreeCamera.cpp | 53 ++++++++ QtMeshViewer/Source/MainWindow.cpp | 51 +++----- QtMeshViewer/Source/MoveCamera.cpp | 46 +++++++ QtMeshViewer/Source/OglViewerWidget.cpp | 155 +++++++----------------- QtMeshViewer/Source/OrbitCamera.cpp | 64 ++++++++++ 12 files changed, 329 insertions(+), 185 deletions(-) create mode 100644 QtMeshViewer/Header/CameraInterface.h create mode 100644 QtMeshViewer/Header/FreeCamera.h create mode 100644 QtMeshViewer/Header/MoveCamera.h create mode 100644 QtMeshViewer/Header/OrbitCamera.h create mode 100644 QtMeshViewer/Source/FreeCamera.cpp create mode 100644 QtMeshViewer/Source/MoveCamera.cpp create mode 100644 QtMeshViewer/Source/OrbitCamera.cpp diff --git a/QtMeshViewer/Header/CameraInterface.h b/QtMeshViewer/Header/CameraInterface.h new file mode 100644 index 0000000..0be00db --- /dev/null +++ b/QtMeshViewer/Header/CameraInterface.h @@ -0,0 +1,26 @@ +#pragma once +#include + +class CameraInterface +{ +public: + explicit CameraInterface() {}; + virtual ~CameraInterface() {}; + +// attributes +protected: + QMatrix4x4 m_matrix; + double m_zSpeed = 1.0; + +// functions +public: + virtual void setZoomSpeed(int percent) { m_zSpeed = (double) percent / 100; }; + + virtual void rotateAction(QVector2D diff) = 0; + virtual void moveAction(QVector2D diff) = 0; + virtual void wheelAction(double value) = 0; + virtual void resetView() { m_matrix = QMatrix4x4(); m_zSpeed = 1.0; }; + + virtual void recalculateMatrix() = 0; + virtual QMatrix4x4 getMatrix() { recalculateMatrix(); return m_matrix; }; +}; \ No newline at end of file diff --git a/QtMeshViewer/Header/FreeCamera.h b/QtMeshViewer/Header/FreeCamera.h new file mode 100644 index 0000000..1df642c --- /dev/null +++ b/QtMeshViewer/Header/FreeCamera.h @@ -0,0 +1,23 @@ +#pragma once +#include "CameraInterface.h" + + +class FreeCamera : public CameraInterface +{ +public: + explicit FreeCamera(); + virtual ~FreeCamera(); + +// attributes +private: + QVector3D m_translation; + QQuaternion m_rotation; + +// functions +public: + virtual void rotateAction(QVector2D diff) Q_DECL_OVERRIDE; + virtual void moveAction(QVector2D diff) Q_DECL_OVERRIDE; + virtual void wheelAction(double value) Q_DECL_OVERRIDE; + virtual void recalculateMatrix() Q_DECL_OVERRIDE; + virtual void resetView() Q_DECL_OVERRIDE; +}; \ No newline at end of file diff --git a/QtMeshViewer/Header/MoveCamera.h b/QtMeshViewer/Header/MoveCamera.h new file mode 100644 index 0000000..5a4d7d5 --- /dev/null +++ b/QtMeshViewer/Header/MoveCamera.h @@ -0,0 +1,22 @@ +#pragma once +#include "CameraInterface.h" + + +class MoveCamera : public CameraInterface +{ +public: + explicit MoveCamera(); + virtual ~MoveCamera(); + + // attributes +private: + + + // functions +public: + virtual void rotateAction(QVector2D diff) Q_DECL_OVERRIDE; + virtual void moveAction(QVector2D diff) Q_DECL_OVERRIDE; + virtual void wheelAction(double value) Q_DECL_OVERRIDE; + virtual void recalculateMatrix() Q_DECL_OVERRIDE; + virtual void resetView() Q_DECL_OVERRIDE; +}; \ No newline at end of file diff --git a/QtMeshViewer/Header/OglViewerWidget.h b/QtMeshViewer/Header/OglViewerWidget.h index e0ab083..9452b5e 100644 --- a/QtMeshViewer/Header/OglViewerWidget.h +++ b/QtMeshViewer/Header/OglViewerWidget.h @@ -5,6 +5,7 @@ #include #include "GeometryEngine.h" #include "SettingsWindow.h" +#include "CameraInterface.h" class GeometryEngine; @@ -37,25 +38,16 @@ private: bool headlight = false; } m_light; - SettingsWindow* m_settings; - struct { bool left = false; bool right = false; QVector2D position; } m_mouse; - struct { - bool x = true; - bool y = true; - bool z = true; - } m_rotDirections; - QMatrix4x4 m_projection; - QVector3D m_translation; - QQuaternion m_rotation; + CameraInterface* m_camera; - double m_zSpeed = 1.0; + SettingsWindow* m_settings; // functions private: @@ -81,10 +73,13 @@ protected: // slots public slots: void loadFile(QString name); - void toggleAxis(int axis); + void useFreeCamera(); + void useOrbitCamera(); + void useMoveCamera(); void toggleWireframe(); void toggleLight(); void showSettings(); + void setBGColorOff(QVector3D value); void setBGColorOn(QVector3D value); void setLightColor(QVector3D value); @@ -92,7 +87,6 @@ public slots: void setAmbCoef(double value); void setHeadlight(bool value); void setBackfaceCulling(bool value); - void setZoomSpeed(int percent); }; diff --git a/QtMeshViewer/Header/OrbitCamera.h b/QtMeshViewer/Header/OrbitCamera.h new file mode 100644 index 0000000..5ca1a45 --- /dev/null +++ b/QtMeshViewer/Header/OrbitCamera.h @@ -0,0 +1,24 @@ +#pragma once +#include "CameraInterface.h" + + +class OrbitCamera : public CameraInterface +{ +public: + explicit OrbitCamera(); + virtual ~OrbitCamera(); + + // attributes +private: + double m_phi; + double m_theta; + double m_roh; + + // functions +public: + virtual void rotateAction(QVector2D diff) Q_DECL_OVERRIDE; + virtual void moveAction(QVector2D diff) Q_DECL_OVERRIDE; + virtual void wheelAction(double value) Q_DECL_OVERRIDE; + virtual void recalculateMatrix() Q_DECL_OVERRIDE; + virtual void resetView() Q_DECL_OVERRIDE; +}; \ No newline at end of file diff --git a/QtMeshViewer/Resources/Resources.qrc b/QtMeshViewer/Resources/Resources.qrc index 080db7a..3e856a6 100644 --- a/QtMeshViewer/Resources/Resources.qrc +++ b/QtMeshViewer/Resources/Resources.qrc @@ -15,17 +15,11 @@ info.png about.png open.png - X.png - Y.png - Z.png screenshot.png wireframe.png light_off.png light_on.png solid.png - X_disabled.png - Y_disabled.png - Z_disabled.png settings.png diff --git a/QtMeshViewer/Resources/StyleSheet.txt b/QtMeshViewer/Resources/StyleSheet.txt index 414040a..19fbef5 100644 --- a/QtMeshViewer/Resources/StyleSheet.txt +++ b/QtMeshViewer/Resources/StyleSheet.txt @@ -37,30 +37,6 @@ QToolButton#screenshot { image: url(:/images/toolbar/screenshot.png); } -QToolButton#x { - image: url(:/images/toolbar/X_disabled.png); -} - -QToolButton#x:checked { - image: url(:/images/toolbar/X.png); -} - -QToolButton#y { - image: url(:/images/toolbar/Y_disabled.png); -} - -QToolButton#y:checked { - image: url(:/images/toolbar/Y.png); -} - -QToolButton#z { - image: url(:/images/toolbar/Z_disabled.png); -} - -QToolButton#z:checked { - image: url(:/images/toolbar/Z.png); -} - QToolButton#wireframe { image: url(:/images/toolbar/solid.png); } diff --git a/QtMeshViewer/Source/FreeCamera.cpp b/QtMeshViewer/Source/FreeCamera.cpp new file mode 100644 index 0000000..feae058 --- /dev/null +++ b/QtMeshViewer/Source/FreeCamera.cpp @@ -0,0 +1,53 @@ +#include "..\Header\FreeCamera.h" +#include +#include +#include + + +///////////////////////////////////////////////////////////////////////// +// constructor/destructor + +FreeCamera::FreeCamera() +{ + resetView(); +} + +FreeCamera::~FreeCamera() +{ + +} + + +///////////////////////////////////////////////////////////////////////// +// functions + +void FreeCamera::rotateAction(QVector2D diff) +{ + m_rotation = QQuaternion::fromAxisAndAngle(QVector3D(diff.y(), diff.x(), 0.0).normalized(), diff.length() * 0.5) * m_rotation; +} + +void FreeCamera::moveAction(QVector2D diff) +{ + m_translation += {(float)(diff.x() * 0.01), (float)(diff.y() * -0.01), 0.0}; +} + +void FreeCamera::wheelAction(double value) +{ + m_translation += {0.0, 0.0, (float) (m_zSpeed * value / 240)}; +} + +void FreeCamera::recalculateMatrix() +{ + m_matrix = QMatrix4x4(); + + m_matrix.translate(m_translation); + m_matrix.rotate(m_rotation); +} + +void FreeCamera::resetView() +{ + m_translation = { 0, 0, -4 }; + m_rotation = QQuaternion(); + + CameraInterface::resetView(); +} diff --git a/QtMeshViewer/Source/MainWindow.cpp b/QtMeshViewer/Source/MainWindow.cpp index d5d5404..069449d 100644 --- a/QtMeshViewer/Source/MainWindow.cpp +++ b/QtMeshViewer/Source/MainWindow.cpp @@ -90,41 +90,26 @@ void MainWindow::setupWidgets() ////////////////////////////////////////////////// ui->mainToolBar->addSeparator(); - QSignalMapper* signalMapper = new QSignalMapper(this); + // Free Camera + QToolButton *freeCamera = new QToolButton(this); + freeCamera->setObjectName("freeCamera"); + freeCamera->setToolTip("free camera"); + connect(freeCamera, &QToolButton::pressed, viewer, &OglViewerWidget::useFreeCamera); + ui->mainToolBar->addWidget(freeCamera); - // X - QToolButton *x = new QToolButton(this); - x->setObjectName("x"); - x->setToolTip("x-direction"); - x->setCheckable(true); - x->setChecked(true); - ui->mainToolBar->addWidget(x); + // Orbital Camera + QToolButton *orbitCamera = new QToolButton(this); + orbitCamera->setObjectName("orbitalCamera"); + orbitCamera->setToolTip("orbital camera"); + connect(orbitCamera, &QToolButton::pressed, viewer, &OglViewerWidget::useOrbitCamera); + ui->mainToolBar->addWidget(orbitCamera); - // Y - QToolButton *y = new QToolButton(this); - y->setObjectName("y"); - y->setToolTip("y-direction"); - y->setCheckable(true); - y->setChecked(true); - ui->mainToolBar->addWidget(y); - - // Z - QToolButton *z = new QToolButton(this); - z->setObjectName("z"); - z->setToolTip("z-direction"); - z->setCheckable(true); - z->setChecked(true); - ui->mainToolBar->addWidget(z); - - connect(x, SIGNAL(pressed()), signalMapper, SLOT(map())); - connect(y, SIGNAL(pressed()), signalMapper, SLOT(map())); - connect(z, SIGNAL(pressed()), signalMapper, SLOT(map())); - - signalMapper->setMapping(x, 1); - signalMapper->setMapping(y, 2); - signalMapper->setMapping(z, 3); - - connect(signalMapper, SIGNAL(mapped(int)), viewer, SLOT(toggleAxis(int))); + // Move Camera + QToolButton *moveCamera = new QToolButton(this); + moveCamera->setObjectName("moveCamera"); + moveCamera->setToolTip("move camera"); + connect(moveCamera, &QToolButton::pressed, viewer, &OglViewerWidget::useMoveCamera); + ui->mainToolBar->addWidget(moveCamera); ////////////////////////////////////////////////// ui->mainToolBar->addSeparator(); diff --git a/QtMeshViewer/Source/MoveCamera.cpp b/QtMeshViewer/Source/MoveCamera.cpp new file mode 100644 index 0000000..fee8054 --- /dev/null +++ b/QtMeshViewer/Source/MoveCamera.cpp @@ -0,0 +1,46 @@ +#include "..\Header\MoveCamera.h" +#include + + +///////////////////////////////////////////////////////////////////////// +// constructor/destructor + +MoveCamera::MoveCamera() +{ + resetView(); +} + +MoveCamera::~MoveCamera() +{ + +} + + +///////////////////////////////////////////////////////////////////////// +// functions + +void MoveCamera::rotateAction(QVector2D diff) +{ + +} + +void MoveCamera::moveAction(QVector2D diff) +{ + +} + +void MoveCamera::wheelAction(double value) +{ + +} + +void MoveCamera::recalculateMatrix() +{ + +} + +void MoveCamera::resetView() +{ + + CameraInterface::resetView(); +} diff --git a/QtMeshViewer/Source/OglViewerWidget.cpp b/QtMeshViewer/Source/OglViewerWidget.cpp index e94f34e..11893fe 100644 --- a/QtMeshViewer/Source/OglViewerWidget.cpp +++ b/QtMeshViewer/Source/OglViewerWidget.cpp @@ -1,5 +1,8 @@ #include "..\Header\OglViewerWidget.h" #include "..\Header\MainWindow.h" +#include "..\Header\FreeCamera.h" +#include "..\Header\OrbitCamera.h" +#include "..\Header\MoveCamera.h" #include #include #include @@ -14,7 +17,8 @@ OglViewerWidget::OglViewerWidget(QWidget *parent) : QOpenGLWidget(parent) - , m_dataEngine(0) + , m_dataEngine(Q_NULLPTR) + , m_camera(new FreeCamera) { setFocus(); setAcceptDrops(true); @@ -29,7 +33,7 @@ OglViewerWidget::OglViewerWidget(QWidget *parent) connect(m_settings, &SettingsWindow::updateAmbCoef, this, &OglViewerWidget::setAmbCoef); connect(m_settings, &SettingsWindow::sendHeadlight, this, &OglViewerWidget::setHeadlight); connect(m_settings, &SettingsWindow::sendBackfaceCulling, this, &OglViewerWidget::setBackfaceCulling); - connect(m_settings, &SettingsWindow::sendZommSpeed, this, &OglViewerWidget::setZoomSpeed); + connect(m_settings, &SettingsWindow::sendZommSpeed, [this](int value) {m_camera->setZoomSpeed(value); }); } OglViewerWidget::~OglViewerWidget() @@ -40,6 +44,7 @@ OglViewerWidget::~OglViewerWidget() delete m_dataEngine; doneCurrent(); + delete m_camera; delete m_settings; } @@ -68,9 +73,7 @@ void OglViewerWidget::initShaders() void OglViewerWidget::resetView() { - m_rotation = QQuaternion(); - m_translation = { 0.0, 0.0, DEFAULT_Z_DISTANCE }; - m_zSpeed = 1; + m_camera->resetView(); if (m_light.headlight) updateLightPosition(); @@ -79,13 +82,13 @@ void OglViewerWidget::resetView() void OglViewerWidget::updateLightPosition() { - QMatrix4x4 rotateBack; - rotateBack.rotate(m_rotation.inverted()); - QVector3D cameraPosition = rotateBack * (-m_translation); + QVector4D lightPosition = { 0,0,0,1 }; - m_light.position.setX(cameraPosition.x()); - m_light.position.setY(cameraPosition.y()); - m_light.position.setZ(cameraPosition.z()); + lightPosition = m_camera->getMatrix().inverted() * lightPosition; + + m_light.position.setX(lightPosition.x()); + m_light.position.setY(lightPosition.y()); + m_light.position.setZ(lightPosition.z()); } // OpenGL /////////////////////////////////////////////////////////////// @@ -139,13 +142,8 @@ void OglViewerWidget::paintGL() // Clear color and depth buffer glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - // Calculate view transformation - QMatrix4x4 view; - view.translate(m_translation); - view.rotate(m_rotation); - // Set view-projection matrix - m_program.setUniformValue("vp_matrix", m_projection * view); + m_program.setUniformValue("vp_matrix", m_projection * m_camera->getMatrix()); // Set Light values m_program.setUniformValue("b_light", m_lightOn); @@ -155,9 +153,7 @@ void OglViewerWidget::paintGL() m_program.setUniformValue("light.ambientCoefficient", m_light.ambientCoefficient); // Set camera position - QMatrix4x4 rotateBack; - rotateBack.rotate(m_rotation.inverted()); - m_program.setUniformValue("cameraPosition", rotateBack * (-m_translation)); + m_program.setUniformValue("cameraPosition", (m_camera->getMatrix().inverted() * QVector4D(0,0,0,1)).toVector3D()); // Draw cube geometry if (m_backfaceCulling) @@ -199,76 +195,11 @@ void OglViewerWidget::mouseMoveEvent(QMouseEvent *e) if (m_mouse.left) { // get the difference between last press and now - QVector2D diff = QVector2D(e->localPos()) - m_mouse.position; + m_camera->rotateAction(QVector2D(e->localPos()) - m_mouse.position); // update the new position m_mouse.position = QVector2D(e->localPos()); - // calculate the rotations depending on the active axis - // XYZ - if (m_rotDirections.x && m_rotDirections.y && m_rotDirections.z) - { - m_rotation = QQuaternion::fromAxisAndAngle(QVector3D(diff.y(), diff.x(), 0.0).normalized(), diff.length() * 0.5) * m_rotation; - } - // XY - else if (m_rotDirections.x && m_rotDirections.y && !m_rotDirections.z) - { - - float pitch, yaw, roll; - m_rotation.getEulerAngles(&pitch, &yaw, &roll); - - pitch += diff.y() * 0.5; - yaw += diff.x() * 0.5; - - if (pitch > 89) - pitch = 89; - else if (pitch < -89) - pitch = -89; - - m_rotation = QQuaternion::fromEulerAngles(pitch, yaw, roll); - - } - // X - else if (m_rotDirections.x && !m_rotDirections.y && !m_rotDirections.z) - { - m_rotation = QQuaternion::fromAxisAndAngle(QVector3D(0.0, 1.0, 0.0).normalized(), diff.x() * 0.5) * m_rotation; - } - // Y - else if (!m_rotDirections.x && m_rotDirections.y && !m_rotDirections.z) - { - m_rotation = QQuaternion::fromAxisAndAngle(QVector3D(1.0, 0.0, 0.0).normalized(), diff.y() * 0.5) * m_rotation; - } - // Z - else if (!m_rotDirections.x && !m_rotDirections.y && m_rotDirections.z) - { - m_rotation = QQuaternion::fromAxisAndAngle(QVector3D(0.0, 0.0, 1.0).normalized(), diff.x() * 0.5) * m_rotation; - } - // XZ - else if (m_rotDirections.x && !m_rotDirections.y && m_rotDirections.z) - { - float pitch, yaw, roll; - m_rotation.getEulerAngles(&pitch, &yaw, &roll); - roll -= diff.y() * 0.5; - yaw += diff.x() * 0.5; - - m_rotation = QQuaternion::fromEulerAngles(pitch, yaw, roll); - } - // YZ - else if (!m_rotDirections.x && m_rotDirections.y && m_rotDirections.z) - { - float pitch, yaw, roll; - m_rotation.getEulerAngles(&pitch, &yaw, &roll); - pitch += diff.y() * 0.5; - roll += diff.x() * 0.5; - - if (pitch > 89) - pitch = 89; - else if (pitch < -89) - pitch = -89; - - m_rotation = QQuaternion::fromEulerAngles(pitch, yaw, roll); - } - // request an update if (m_light.headlight) updateLightPosition(); @@ -277,14 +208,11 @@ void OglViewerWidget::mouseMoveEvent(QMouseEvent *e) else if (m_mouse.right) { // get the difference between last press and now - QVector2D diff = QVector2D(e->localPos()) - m_mouse.position; + m_camera->moveAction(QVector2D(e->localPos()) - m_mouse.position); // update the new position m_mouse.position = QVector2D(e->localPos()); - // calculate the translation - m_translation += {(float)(diff.x() * 0.01), (float)(diff.y() * -0.01), 0.0}; - // request an update if (m_light.headlight) updateLightPosition(); @@ -294,7 +222,7 @@ void OglViewerWidget::mouseMoveEvent(QMouseEvent *e) void OglViewerWidget::wheelEvent(QWheelEvent *e) { - m_translation += {0.0, 0.0, (float)m_zSpeed * e->angleDelta().y() / 240}; + m_camera->wheelAction(e->angleDelta().y()); if (m_light.headlight) updateLightPosition(); @@ -341,20 +269,34 @@ void OglViewerWidget::loadFile(QString name) m_dataEngine->loadFile(name); } -void OglViewerWidget::toggleAxis(int axis) +void OglViewerWidget::useFreeCamera() { - switch (axis) - { - case 1: - m_rotDirections.x = !m_rotDirections.x; - break; - case 2: - m_rotDirections.y = !m_rotDirections.y; - break; - case 3: - m_rotDirections.z = !m_rotDirections.z; - break; - } + delete m_camera; + m_camera = new FreeCamera; + + if (m_lightOn) + updateLightPosition(); + update(); +} + +void OglViewerWidget::useOrbitCamera() +{ + delete m_camera; + m_camera = new OrbitCamera; + + if (m_lightOn) + updateLightPosition(); + update(); +} + +void OglViewerWidget::useMoveCamera() +{ + delete m_camera; + m_camera = new MoveCamera; + + if (m_lightOn) + updateLightPosition(); + update(); } void OglViewerWidget::toggleWireframe() @@ -441,8 +383,3 @@ void OglViewerWidget::setBackfaceCulling(bool value) m_backfaceCulling = value; update(); } - -void OglViewerWidget::setZoomSpeed(int percent) -{ - m_zSpeed = (double) percent / 100; -} diff --git a/QtMeshViewer/Source/OrbitCamera.cpp b/QtMeshViewer/Source/OrbitCamera.cpp new file mode 100644 index 0000000..058f382 --- /dev/null +++ b/QtMeshViewer/Source/OrbitCamera.cpp @@ -0,0 +1,64 @@ +#include "..\Header\OrbitCamera.h" +#include +#include +#include + + +///////////////////////////////////////////////////////////////////////// +// constructor/destructor + +OrbitCamera::OrbitCamera() +{ + resetView(); +} + +OrbitCamera::~OrbitCamera() +{ + +} + + +///////////////////////////////////////////////////////////////////////// +// functions + +void OrbitCamera::rotateAction(QVector2D diff) +{ + //m_phi += diff.x() * 0.01; + m_theta -= diff.y() * 0.01; + + m_theta = qMax(qMin(M_PI_2, m_theta), -M_PI_2); + +} + +void OrbitCamera::moveAction(QVector2D diff) +{ + +} + +void OrbitCamera::wheelAction(double value) +{ + m_roh -= m_zSpeed * value / 240; + m_roh = qMax(m_roh, 0.0); +} + +void OrbitCamera::recalculateMatrix() +{ + m_matrix = QMatrix4x4(); + + QVector3D tmpPosition; + tmpPosition.setX(qSin(m_theta) * qCos(m_phi)); + tmpPosition.setY(qSin(m_theta) * qSin(m_phi)); + tmpPosition.setZ(qCos(m_theta)); + + std::cout << m_theta << ":" << tmpPosition.x() << "-" << tmpPosition.y() << "-" << tmpPosition.z() << std::endl; + + m_matrix.lookAt(m_roh * tmpPosition, QVector3D(0, 0, 0), QVector3D(0, 1, 0)); +} + +void OrbitCamera::resetView() +{ + m_roh = 4; + m_phi = - M_PI_2; + m_theta = 0; + CameraInterface::resetView(); +}