use class for camera handling,

orbit does not work. Need to figure out why
This commit is contained in:
Anakin 2017-02-02 18:01:08 +01:00
parent b17ab3f8e9
commit 333eca25eb
12 changed files with 329 additions and 185 deletions

View File

@ -0,0 +1,26 @@
#pragma once
#include <QMatrix4x4>
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; };
};

View File

@ -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;
};

View File

@ -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;
};

View File

@ -5,6 +5,7 @@
#include <QMatrix4x4> #include <QMatrix4x4>
#include "GeometryEngine.h" #include "GeometryEngine.h"
#include "SettingsWindow.h" #include "SettingsWindow.h"
#include "CameraInterface.h"
class GeometryEngine; class GeometryEngine;
@ -37,25 +38,16 @@ private:
bool headlight = false; bool headlight = false;
} m_light; } m_light;
SettingsWindow* m_settings;
struct { struct {
bool left = false; bool left = false;
bool right = false; bool right = false;
QVector2D position; QVector2D position;
} m_mouse; } m_mouse;
struct {
bool x = true;
bool y = true;
bool z = true;
} m_rotDirections;
QMatrix4x4 m_projection; QMatrix4x4 m_projection;
QVector3D m_translation; CameraInterface* m_camera;
QQuaternion m_rotation;
double m_zSpeed = 1.0; SettingsWindow* m_settings;
// functions // functions
private: private:
@ -81,10 +73,13 @@ protected:
// slots // slots
public slots: public slots:
void loadFile(QString name); void loadFile(QString name);
void toggleAxis(int axis); void useFreeCamera();
void useOrbitCamera();
void useMoveCamera();
void toggleWireframe(); void toggleWireframe();
void toggleLight(); void toggleLight();
void showSettings(); void showSettings();
void setBGColorOff(QVector3D value); void setBGColorOff(QVector3D value);
void setBGColorOn(QVector3D value); void setBGColorOn(QVector3D value);
void setLightColor(QVector3D value); void setLightColor(QVector3D value);
@ -92,7 +87,6 @@ public slots:
void setAmbCoef(double value); void setAmbCoef(double value);
void setHeadlight(bool value); void setHeadlight(bool value);
void setBackfaceCulling(bool value); void setBackfaceCulling(bool value);
void setZoomSpeed(int percent);
}; };

View File

@ -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;
};

View File

@ -15,17 +15,11 @@
<file>info.png</file> <file>info.png</file>
<file>about.png</file> <file>about.png</file>
<file>open.png</file> <file>open.png</file>
<file>X.png</file>
<file>Y.png</file>
<file>Z.png</file>
<file>screenshot.png</file> <file>screenshot.png</file>
<file>wireframe.png</file> <file>wireframe.png</file>
<file>light_off.png</file> <file>light_off.png</file>
<file>light_on.png</file> <file>light_on.png</file>
<file>solid.png</file> <file>solid.png</file>
<file>X_disabled.png</file>
<file>Y_disabled.png</file>
<file>Z_disabled.png</file>
<file>settings.png</file> <file>settings.png</file>
</qresource> </qresource>
</RCC> </RCC>

View File

@ -37,30 +37,6 @@ QToolButton#screenshot {
image: url(:/images/toolbar/screenshot.png); 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 { QToolButton#wireframe {
image: url(:/images/toolbar/solid.png); image: url(:/images/toolbar/solid.png);
} }

View File

@ -0,0 +1,53 @@
#include "..\Header\FreeCamera.h"
#include <QVector2D>
#include <QVector3D>
#include <QQuaternion>
/////////////////////////////////////////////////////////////////////////
// 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();
}

View File

@ -90,41 +90,26 @@ void MainWindow::setupWidgets()
////////////////////////////////////////////////// //////////////////////////////////////////////////
ui->mainToolBar->addSeparator(); 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 // Orbital Camera
QToolButton *x = new QToolButton(this); QToolButton *orbitCamera = new QToolButton(this);
x->setObjectName("x"); orbitCamera->setObjectName("orbitalCamera");
x->setToolTip("x-direction"); orbitCamera->setToolTip("orbital camera");
x->setCheckable(true); connect(orbitCamera, &QToolButton::pressed, viewer, &OglViewerWidget::useOrbitCamera);
x->setChecked(true); ui->mainToolBar->addWidget(orbitCamera);
ui->mainToolBar->addWidget(x);
// Y // Move Camera
QToolButton *y = new QToolButton(this); QToolButton *moveCamera = new QToolButton(this);
y->setObjectName("y"); moveCamera->setObjectName("moveCamera");
y->setToolTip("y-direction"); moveCamera->setToolTip("move camera");
y->setCheckable(true); connect(moveCamera, &QToolButton::pressed, viewer, &OglViewerWidget::useMoveCamera);
y->setChecked(true); ui->mainToolBar->addWidget(moveCamera);
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)));
////////////////////////////////////////////////// //////////////////////////////////////////////////
ui->mainToolBar->addSeparator(); ui->mainToolBar->addSeparator();

View File

@ -0,0 +1,46 @@
#include "..\Header\MoveCamera.h"
#include <QVector2D>
/////////////////////////////////////////////////////////////////////////
// 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();
}

View File

@ -1,5 +1,8 @@
#include "..\Header\OglViewerWidget.h" #include "..\Header\OglViewerWidget.h"
#include "..\Header\MainWindow.h" #include "..\Header\MainWindow.h"
#include "..\Header\FreeCamera.h"
#include "..\Header\OrbitCamera.h"
#include "..\Header\MoveCamera.h"
#include <QMouseEvent> #include <QMouseEvent>
#include <QDropEvent> #include <QDropEvent>
#include <QMimeData> #include <QMimeData>
@ -14,7 +17,8 @@
OglViewerWidget::OglViewerWidget(QWidget *parent) OglViewerWidget::OglViewerWidget(QWidget *parent)
: QOpenGLWidget(parent) : QOpenGLWidget(parent)
, m_dataEngine(0) , m_dataEngine(Q_NULLPTR)
, m_camera(new FreeCamera)
{ {
setFocus(); setFocus();
setAcceptDrops(true); setAcceptDrops(true);
@ -29,7 +33,7 @@ OglViewerWidget::OglViewerWidget(QWidget *parent)
connect(m_settings, &SettingsWindow::updateAmbCoef, this, &OglViewerWidget::setAmbCoef); connect(m_settings, &SettingsWindow::updateAmbCoef, this, &OglViewerWidget::setAmbCoef);
connect(m_settings, &SettingsWindow::sendHeadlight, this, &OglViewerWidget::setHeadlight); connect(m_settings, &SettingsWindow::sendHeadlight, this, &OglViewerWidget::setHeadlight);
connect(m_settings, &SettingsWindow::sendBackfaceCulling, this, &OglViewerWidget::setBackfaceCulling); 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() OglViewerWidget::~OglViewerWidget()
@ -40,6 +44,7 @@ OglViewerWidget::~OglViewerWidget()
delete m_dataEngine; delete m_dataEngine;
doneCurrent(); doneCurrent();
delete m_camera;
delete m_settings; delete m_settings;
} }
@ -68,9 +73,7 @@ void OglViewerWidget::initShaders()
void OglViewerWidget::resetView() void OglViewerWidget::resetView()
{ {
m_rotation = QQuaternion(); m_camera->resetView();
m_translation = { 0.0, 0.0, DEFAULT_Z_DISTANCE };
m_zSpeed = 1;
if (m_light.headlight) if (m_light.headlight)
updateLightPosition(); updateLightPosition();
@ -79,13 +82,13 @@ void OglViewerWidget::resetView()
void OglViewerWidget::updateLightPosition() void OglViewerWidget::updateLightPosition()
{ {
QMatrix4x4 rotateBack; QVector4D lightPosition = { 0,0,0,1 };
rotateBack.rotate(m_rotation.inverted());
QVector3D cameraPosition = rotateBack * (-m_translation);
m_light.position.setX(cameraPosition.x()); lightPosition = m_camera->getMatrix().inverted() * lightPosition;
m_light.position.setY(cameraPosition.y());
m_light.position.setZ(cameraPosition.z()); m_light.position.setX(lightPosition.x());
m_light.position.setY(lightPosition.y());
m_light.position.setZ(lightPosition.z());
} }
// OpenGL /////////////////////////////////////////////////////////////// // OpenGL ///////////////////////////////////////////////////////////////
@ -139,13 +142,8 @@ void OglViewerWidget::paintGL()
// Clear color and depth buffer // Clear color and depth buffer
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 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 // 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 // Set Light values
m_program.setUniformValue("b_light", m_lightOn); m_program.setUniformValue("b_light", m_lightOn);
@ -155,9 +153,7 @@ void OglViewerWidget::paintGL()
m_program.setUniformValue("light.ambientCoefficient", m_light.ambientCoefficient); m_program.setUniformValue("light.ambientCoefficient", m_light.ambientCoefficient);
// Set camera position // Set camera position
QMatrix4x4 rotateBack; m_program.setUniformValue("cameraPosition", (m_camera->getMatrix().inverted() * QVector4D(0,0,0,1)).toVector3D());
rotateBack.rotate(m_rotation.inverted());
m_program.setUniformValue("cameraPosition", rotateBack * (-m_translation));
// Draw cube geometry // Draw cube geometry
if (m_backfaceCulling) if (m_backfaceCulling)
@ -199,76 +195,11 @@ void OglViewerWidget::mouseMoveEvent(QMouseEvent *e)
if (m_mouse.left) if (m_mouse.left)
{ {
// get the difference between last press and now // 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 // update the new position
m_mouse.position = QVector2D(e->localPos()); 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 // request an update
if (m_light.headlight) if (m_light.headlight)
updateLightPosition(); updateLightPosition();
@ -277,14 +208,11 @@ void OglViewerWidget::mouseMoveEvent(QMouseEvent *e)
else if (m_mouse.right) else if (m_mouse.right)
{ {
// get the difference between last press and now // 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 // update the new position
m_mouse.position = QVector2D(e->localPos()); 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 // request an update
if (m_light.headlight) if (m_light.headlight)
updateLightPosition(); updateLightPosition();
@ -294,7 +222,7 @@ void OglViewerWidget::mouseMoveEvent(QMouseEvent *e)
void OglViewerWidget::wheelEvent(QWheelEvent *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) if (m_light.headlight)
updateLightPosition(); updateLightPosition();
@ -341,20 +269,34 @@ void OglViewerWidget::loadFile(QString name)
m_dataEngine->loadFile(name); m_dataEngine->loadFile(name);
} }
void OglViewerWidget::toggleAxis(int axis) void OglViewerWidget::useFreeCamera()
{ {
switch (axis) delete m_camera;
{ m_camera = new FreeCamera;
case 1:
m_rotDirections.x = !m_rotDirections.x; if (m_lightOn)
break; updateLightPosition();
case 2: update();
m_rotDirections.y = !m_rotDirections.y;
break;
case 3:
m_rotDirections.z = !m_rotDirections.z;
break;
} }
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() void OglViewerWidget::toggleWireframe()
@ -441,8 +383,3 @@ void OglViewerWidget::setBackfaceCulling(bool value)
m_backfaceCulling = value; m_backfaceCulling = value;
update(); update();
} }
void OglViewerWidget::setZoomSpeed(int percent)
{
m_zSpeed = (double) percent / 100;
}

View File

@ -0,0 +1,64 @@
#include "..\Header\OrbitCamera.h"
#include <QVector2D>
#include <qmath.h>
#include <iostream>
/////////////////////////////////////////////////////////////////////////
// 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();
}