Commit 4e889a03 by Alisa Jung

Kamera verschieben, um neues zentrum rotieren, unabh zoomen.

parent e2c4da19
#include "controller.h"
#include "myglwidget.h"
Controller::Controller()
{
modeCamera = true;
}
Controller::~Controller(){
}
void Controller::switchToModeCamera(){
qDebug("Bla");
modeCamera = true;
}
void Controller::switchToModeManipulate(){
modeCamera = false;
}
void Controller::processMousePressEvent(QMouseEvent *event, MyGLWidget *widget){
rightButtonPressed = false;
leftButtonPressed = false;
if (event->button() == Qt::RightButton){
rightButtonPressed = true;
lastClickPosition = event->pos();
qDebug() << "mouse press at " << lastClickPosition;
} else if (event->button() == Qt::LeftButton){
leftButtonPressed = true;
lastClickPosition = event->pos();
}
//TODO if widget was not selected before, set active.
}
void Controller::processMouseMoveEvent(QMouseEvent *event, MyGLWidget *widget){
//This didn't work properly, used bool to store state instead. if (event->button() == Qt::RightButton){
if (rightButtonPressed){
QPoint currentPosition = event->pos();
QPoint diff = currentPosition - lastClickPosition;
lastClickPosition = currentPosition;
if (modeCamera){
widget->translateCamera(-0.01*diff.x(),0.01*diff.y());
} else{
widget->translateQube(0.01*diff.x(),-0.01*diff.y());
}
}else if (leftButtonPressed){
QQuaternion q = computeRotation(event->pos());
if (modeCamera){
//TODO nur bei perspective widget
//TODO widget->rotateCamera
widget->rotateCamera(q);
}else{
widget->rotateQube(q);
}
}
}
void Controller::setScreenScenter(QPoint center){
screenCenter = center;
}
QQuaternion Controller::computeRotation(QPoint newPosition){
//according to https://www.opengl.org/wiki/Object_Mouse_Trackball
double radius = std::min(screenCenter.x(),screenCenter.y());
//translate touches around screen center
double xOld = ((double)(lastClickPosition.x() - screenCenter.x()));
double yNew = ((double)(lastClickPosition.y() - screenCenter.y()));
double xNew = ((double)(newPosition.x() - screenCenter.x()));
double yOld = ((double)(newPosition.y() - screenCenter.y()));
lastClickPosition = newPosition;
//https://www.opengl.org/wiki/Object_Mouse_Trackball#Sit_and_spin
//compute z coordinates ether on sphere or on hyperbolic sheet
double zOld, zNew;
double rsquareover2 = radius*radius/2.0;
double xyOld = xOld*xOld + yOld*yOld;
double xyNew = xNew*xNew + yNew*yNew;
if (xyOld < rsquareover2){
zOld = sqrt(radius*radius - xyOld);
qDebug() << "z old 1 " << zOld;
}else{
zOld = rsquareover2/(sqrt(xyOld));
qDebug() << "z old 2 " << zOld;
}
if(xyNew < rsquareover2){
zNew = sqrt(radius*radius - xyNew);
}else{
zNew = rsquareover2/sqrt(xyNew);
}
// set V_1 and V_2 (Vectors on Sphere around screen center, corresponding to input
QVector3D v1 = QVector3D(xOld,yOld,zOld);
v1.normalize();
QVector3D v2 = QVector3D(xNew,yNew,zNew);
v2.normalize();
//Compute normal of plane through v1 and v2 -> rotation axis
QVector3D n = QVector3D::crossProduct(v1,v2);
n.normalize();
//and theta (angle between v1 and v2)
double theta = acos(QVector3D::dotProduct(v1,v2));
//Accumulate Rotation
QQuaternion q = QQuaternion(cos(theta/2.0),sin(theta/2)*n);
q.normalize();
qDebug() << "quaternion diff " << q << "xo " << xOld << "yo " << yOld << " x new " << xNew << " ynew " << yNew;
qDebug() << "v1 " << v1 << ", v2 " << v2;
return q;
}
#ifndef CONTROLLER_H
#define CONTROLLER_H
#include <QGLWidget>
#include <gl/GLU.h>
#include <QDebug>
#include <QWheelEvent>
#include <QQuaternion>
#include <QMatrix4x4>
#include <math.h>
#include <QVector3D>
#include <QGLShaderProgram>
#include <QGLShader>
#include <QDebug>
#include <QObject>
class MyGLWidget;
class Controller : public QObject
{
Q_OBJECT
public:
Controller();
~Controller();
//processes input and might call follow up functions in widget
void processMousePressEvent(QMouseEvent* event, MyGLWidget* widget);
//processes mouse movement, calls some translate / rotate function in widget
void processMouseMoveEvent(QMouseEvent* event, MyGLWidget* widget);
void setScreenScenter(QPoint center);
private:
bool modeCamera;
bool rightButtonPressed;
bool leftButtonPressed;
QPoint screenCenter;//Center of screen in pixel coordinates
QPoint lastClickPosition;
QQuaternion computeRotation(QPoint newPosition);
public slots:
void switchToModeCamera();
void switchToModeManipulate();
};
#endif // CONTROLLER_H
...@@ -18,14 +18,14 @@ SOURCES += main.cpp\ ...@@ -18,14 +18,14 @@ SOURCES += main.cpp\
scenegraph.cpp \ scenegraph.cpp \
primitive.cpp \ primitive.cpp \
rigidbodytransformation.cpp \ rigidbodytransformation.cpp \
widgetfront.cpp controller.cpp
HEADERS += mainwindow.h \ HEADERS += mainwindow.h \
myglwidget.h \ myglwidget.h \
scenegraph.h \ scenegraph.h \
primitive.h \ primitive.h \
rigidbodytransformation.h \ rigidbodytransformation.h \
widgetfront.h controller.h
RESOURCES += \ RESOURCES += \
helloqube.qrc helloqube.qrc
......
...@@ -76,7 +76,8 @@ MainWindow::MainWindow(QWidget *parent) ...@@ -76,7 +76,8 @@ MainWindow::MainWindow(QWidget *parent)
setStatusBar(statusBar); setStatusBar(statusBar);
//4.0 Widget //4.0 Widget
myGLWidget = new MyGLWidget(this); controller = new Controller();
myGLWidget = new MyGLWidget(controller,this);
setCentralWidget(myGLWidget); setCentralWidget(myGLWidget);
//4.1.1 connect shading actions to slot //4.1.1 connect shading actions to slot
...@@ -114,18 +115,22 @@ MainWindow::MainWindow(QWidget *parent) ...@@ -114,18 +115,22 @@ MainWindow::MainWindow(QWidget *parent)
//TODO connect slot //TODO connect slot
toolBar->addAction(modeCameraAction); toolBar->addAction(modeCameraAction);
toolBar->insertSeparator(modeCameraAction); toolBar->insertSeparator(modeCameraAction);
connect(modeCameraAction,SIGNAL(triggered(bool)),controller,SLOT(switchToModeCamera()));
modeManipulateAction = new QAction("Manipulation Mode", toolBar); modeManipulateAction = new QAction("Manipulation Mode", toolBar);
modeManipulateAction->setIcon(QIcon(":/grapa-a2-iconset/select.png")); modeManipulateAction->setIcon(QIcon(":/grapa-a2-iconset/select.png"));
modeManipulateAction->setCheckable(true); modeManipulateAction->setCheckable(true);
//TODO connect slot //TODO connect slot
toolBar->addAction(modeManipulateAction); toolBar->addAction(modeManipulateAction);
connect(modeManipulateAction,SIGNAL(triggered(bool)),controller,SLOT(switchToModeManipulate()));
modeSwitchGroup = new QActionGroup(toolBar); modeSwitchGroup = new QActionGroup(toolBar);
modeSwitchGroup->addAction(modeCameraAction); modeSwitchGroup->addAction(modeCameraAction);
modeSwitchGroup->addAction(modeManipulateAction); modeSwitchGroup->addAction(modeManipulateAction);
//2 Switch view modes //2 Switch view modes
viewButton = new QToolButton(toolBar); viewButton = new QToolButton(toolBar);
viewButton->setIcon(QIcon(":/grapa-a2-iconset/viewports.png")); viewButton->setIcon(QIcon(":/grapa-a2-iconset/viewports.png"));
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#include <myglwidget.h> #include <myglwidget.h>
#include <QSlider> #include <QSlider>
#include <QToolButton> #include <QToolButton>
#include <controller.h>
class MainWindow : public QMainWindow class MainWindow : public QMainWindow
{ {
...@@ -67,6 +68,8 @@ private: ...@@ -67,6 +68,8 @@ private:
//4.1.1 Slider //4.1.1 Slider
QSlider* tesselationSlider; QSlider* tesselationSlider;
Controller* controller;
public slots : public slots :
void showAboutBox ( ) ; void showAboutBox ( ) ;
}; };
......
#include "myglwidget.h" #include "myglwidget.h"
#include "controller.h"
MyGLWidget::MyGLWidget(QWidget *parent) MyGLWidget::MyGLWidget(Controller* c, QWidget *parent)
: QGLWidget(QGLFormat(QGL::SampleBuffers), parent) : QGLWidget(QGLFormat(QGL::SampleBuffers), parent)
{ {
MyGLWidget::modeCamera = true;
tesselation = 1; tesselation = 1;
qubeRotationQuaternion = QQuaternion(); qubeRotation = QQuaternion();
cameraRotation = QQuaternion();
translatex = 0; translatex = 0;
translatey = 0; translatey = 0;
cameraX = 0;
cameraY = 0;
cameraZ = 0;
camRotCenter = QVector3D(0,0,0);
cameraZoom = cameraZoomDefault; cameraZoom = cameraZoomDefault;
clickStartPosition = QPoint(0,0); clickStartPosition = QPoint(0,0);
rightButtonPressed = false; rightButtonPressed = false;
controller = c;
} }
MyGLWidget::~MyGLWidget() MyGLWidget::~MyGLWidget()
...@@ -109,24 +117,47 @@ void MyGLWidget::paintGL(){ ...@@ -109,24 +117,47 @@ void MyGLWidget::paintGL(){
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity(); glLoadIdentity();
//zoom camera //cam rotation
glTranslatef(0,0,cameraZoom);//Kamera sitzt sonst in (0,0,0) und man sieht nichts (duh) QMatrix4x4 camRot = QMatrix4x4();
camRot.rotate(cameraRotation);
//for translation
double qubeWidth = 1.0;
double dist = qubeWidth/(double)tesselation;
//for cube rotation
QMatrix4x4 m = QMatrix4x4();
m.rotate(qubeRotation);
//for cube translation //for cube translation
QMatrix4x4 translateRot1 = QMatrix4x4(1,0,0,translatex,0,1,0,translatey,0,0,1,0,0,0,0,1); QMatrix4x4 translateRot1 = QMatrix4x4(1,0,0,translatex,0,1,0,translatey,0,0,1,0,0,0,0,1);
//for cube rotation QMatrix4x4 translateCamera = QMatrix4x4(1,0,0,cameraX,0,1,0,cameraY,0,0,1,cameraZ,0,0,0,1);
QMatrix4x4 m = QMatrix4x4();
m.rotate(qubeRotationQuaternion); QMatrix4x4 zoomCameraMatrix = QMatrix4x4(1,0,0,0,0,1,0,0,0,0,1,cameraZoom,0,0,0,1);
// //zoom camera
// glTranslatef(0,0,cameraZoom);//Kamera sitzt sonst in (0,0,0) und man sieht nichts (duh)
// glTranslatef(cameraX,cameraY,0);//TODO anständig machen, kamerarotation fehlt noch.
//stack matrices //stack matrices
glMultMatrixf(translateRot1.data());//Punkte zurück schieben damit rotation um qube zentrum ist // glMultMatrixf(translateRot1.data());//Punkte zurück schieben damit rotation um qube zentrum ist
glMultMatrixf(m.data()); // glMultMatrixf(m.data());
//So scheint das zumindest für die Kamera zu funktionieren:
//1. ins Rotationszentrum verschieben - Wenn Rotationszentrum geändert wird, schon rotation berücksichtigen
//2. Rotieren
//3. Zoomen
glMultMatrixf(zoomCameraMatrix.data());
glMultMatrixf(camRot.data());
glTranslatef(camRotCenter.x(),camRotCenter.y(),camRotCenter.z());
//tesselation
double qubeWidth = 1.0;
double dist = qubeWidth/(double)tesselation;
//4.1.1 Unit Qube + Tesselation + Diffuse Material //4.1.1 Unit Qube + Tesselation + Diffuse Material
{ {
...@@ -241,97 +272,51 @@ void MyGLWidget::resizeGL(int width, int height){ ...@@ -241,97 +272,51 @@ void MyGLWidget::resizeGL(int width, int height){
glMatrixMode(GL_MODELVIEW); glMatrixMode(GL_MODELVIEW);
screenCenter = QPoint((double)width/2.0,(double)height/2.0);//lieber zu oft casten bevors nicht tut... controller->setScreenScenter(QPoint((double)width/2.0,(double)height/2.0));//lieber zu oft casten bevors nicht tut...
} }
void MyGLWidget::mousePressEvent(QMouseEvent *event){ void MyGLWidget::mousePressEvent(QMouseEvent *event){
rightButtonPressed = false; controller->processMousePressEvent(event,this);
leftButtonPressed = false;
if (event->button() == Qt::RightButton){
rightButtonPressed = true;
clickStartPosition = event->pos();
qDebug() << "mouse press at " << clickStartPosition;
} else if (event->button() == Qt::LeftButton){
leftButtonPressed = true;
clickStartPosition = event->pos();
}
} }
void MyGLWidget:: mouseMoveEvent(QMouseEvent *event){ void MyGLWidget:: mouseMoveEvent(QMouseEvent *event){
//This didn't work properly, used bool to store state instead. if (event->button() == Qt::RightButton){ controller->processMouseMoveEvent(event,this);
if (rightButtonPressed){ }
QPoint currentPosition = event->pos();
QPoint diff = currentPosition - clickStartPosition; void MyGLWidget::translateCamera(double xDiff, double yDiff, double zDiff)
clickStartPosition = currentPosition; {
translatex += 0.01*diff.x(); //in order to "move parallel to image plane", we have to rotate the image coordinates xDiff and yDiff by our current camera rotation.
translatey -= 0.01*diff.y(); camRotCenter += cameraRotation.conjugate().rotatedVector(QVector3D(xDiff,yDiff,zDiff));
updateGL();
}
void MyGLWidget::translateQube(double xDiff, double yDiff){
translatex += xDiff;
translatey += yDiff;
updateGL();
}
void MyGLWidget::rotateQube(QQuaternion diff){
/*
* Wikipedia: Two rotation quaternions can be combined into
* one equivalent quaternionby the relation:
* q' = q_2*q_1'
* in which q′ corresponds to the rotation q1 followed by the rotation q2.
* (Note that quaternion multiplication is not commutative.)
*/
qubeRotation = diff*qubeRotation;
qubeRotation.normalize();
updateGL(); updateGL();
}else if (leftButtonPressed){
//according to https://www.opengl.org/wiki/Object_Mouse_Trackball
double radius = std::min(screenCenter.x(),screenCenter.y());
//translate touches around screen center
double xOld = ((double)(clickStartPosition.x() - screenCenter.x()));
double yNew = ((double)(clickStartPosition.y() - screenCenter.y()));
QPoint newPosition = event->pos();
double xNew = ((double)(newPosition.x() - screenCenter.x()));
double yOld = ((double)(newPosition.y() - screenCenter.y()));
clickStartPosition = newPosition;
//https://www.opengl.org/wiki/Object_Mouse_Trackball#Sit_and_spin
//compute z coordinates ether on sphere or on hyperbolic sheet
double zOld, zNew;
double rsquareover2 = radius*radius/2.0;
double xyOld = xOld*xOld + yOld*yOld;
double xyNew = xNew*xNew + yNew*yNew;
if (xyOld < rsquareover2){
zOld = sqrt(radius*radius - xyOld);
}else{
zOld = rsquareover2/(sqrt(xyOld));
}
if(xyNew < rsquareover2){
zNew = sqrt(radius*radius - xyNew);
}else{
zNew = rsquareover2/sqrt(xyNew);
}
// set V_1 and V_2 (Vectors on Sphere around screen center, corresponding to input
QVector3D v1 = QVector3D(xOld,yOld,zOld);
v1.normalize();
QVector3D v2 = QVector3D(xNew,yNew,zNew);
v2.normalize();
//Compute normal of plane through v1 and v2 -> rotation axis
QVector3D n = QVector3D::crossProduct(v1,v2);
n.normalize();
//and theta (angle between v1 and v2)
double theta = acos(QVector3D::dotProduct(v1,v2));
//Accumulate Rotation
QQuaternion q = QQuaternion(cos(theta/2.0),sin(theta/2)*n);
q.normalize();
/*
* Wikipedia: Two rotation quaternions can be combined into
* one equivalent quaternionby the relation:
* q' = q_2*q_1'
* in which q′ corresponds to the rotation q1 followed by the rotation q2.
* (Note that quaternion multiplication is not commutative.)
*/
qubeRotationQuaternion = q*qubeRotationQuaternion;
qubeRotationQuaternion.normalize();
updateGL();
} }
void MyGLWidget::rotateCamera(QQuaternion diff){
cameraRotation = diff*cameraRotation;
cameraRotation.normalize();
updateGL();
} }
//4.1.2 User Input: Zooming //4.1.2 User Input: Zooming
...@@ -384,9 +369,14 @@ void MyGLWidget::setTessellation(int t){ ...@@ -384,9 +369,14 @@ void MyGLWidget::setTessellation(int t){
} }
void MyGLWidget::resetCamera(){ void MyGLWidget::resetCamera(){
qubeRotationQuaternion = QQuaternion(); qubeRotation = QQuaternion();
translatex = 0; translatex = 0;
translatey = 0; translatey = 0;
cameraX = 0;
cameraY = 0;
cameraZ = 0;
camRotCenter = QVector3D(0,0,0);
cameraZoom = cameraZoomDefault; cameraZoom = cameraZoomDefault;
cameraRotation = QQuaternion();
updateGL(); updateGL();
} }
...@@ -12,18 +12,28 @@ ...@@ -12,18 +12,28 @@
#include <QGLShaderProgram> #include <QGLShaderProgram>
#include <QGLShader> #include <QGLShader>
class Controller;
class MyGLWidget : public QGLWidget class MyGLWidget : public QGLWidget
{ {
Q_OBJECT //from HelloGL Example Q_OBJECT //from HelloGL Example
public: public:
MyGLWidget(QWidget *parent = 0); MyGLWidget(Controller* c, QWidget *parent = 0);
~MyGLWidget(); ~MyGLWidget();
//From HelloGL example. //From HelloGL example.
QSize minimumSizeHint() const; QSize minimumSizeHint() const;
QSize sizeHint() const; QSize sizeHint() const;
/* Assignment 2*/
bool modeCamera;
void translateCamera(double xDiff, double yDiff, double zDiff = 0);
void translateQube(double xDiff, double yDiff);
void rotateCamera(QQuaternion diff);
void rotateQube(QQuaternion diff);
protected: protected:
//4.1 Core Functionality //4.1 Core Functionality
void initializeGL(); void initializeGL();
...@@ -33,13 +43,18 @@ protected: ...@@ -33,13 +43,18 @@ protected:
void mouseMoveEvent(QMouseEvent *event); void mouseMoveEvent(QMouseEvent *event);
void wheelEvent(QWheelEvent *event); void wheelEvent(QWheelEvent *event);
Controller* controller;
private: private:
//tesselation slider //tesselation slider
int tesselation; int tesselation;
//zoom camera //zoom camera
const double cameraZoomDefault = -5; const double cameraZoomDefault = -5;
double cameraX,cameraY,cameraZ;
double cameraZoom; double cameraZoom;
QQuaternion cameraRotation;
QVector3D camRotCenter;
//translate camera //translate camera
QPoint clickStartPosition; QPoint clickStartPosition;
...@@ -48,13 +63,15 @@ private: ...@@ -48,13 +63,15 @@ private:
//rotate cube //rotate cube
bool leftButtonPressed; bool leftButtonPressed;
QQuaternion qubeRotationQuaternion; QQuaternion qubeRotation;
QPoint screenCenter;//Center of screen in pixel coordinates QPoint screenCenter;//Center of screen in pixel coordinates
//Phong Shader //Phong Shader
QGLShaderProgram *phongShader; QGLShaderProgram *phongShader;
public slots: public slots:
//4.1.1 slots for shading modes //4.1.1 slots for shading modes
void shadeWireframeSlot(); void shadeWireframeSlot();
......
...@@ -5,20 +5,20 @@ RigidBodyTransformation::RigidBodyTransformation(Primitive child) ...@@ -5,20 +5,20 @@ RigidBodyTransformation::RigidBodyTransformation(Primitive child)
tx = 0; tx = 0;
ty = 0; ty = 0;
tz = 0; tz = 0;
rotation = new QQuaternion(); rotation = QQuaternion();
this->child = child; this->child = child;
} }
RigidBodyTransformation::setTranslation(double x, double y, double z=0){ void RigidBodyTransformation::setTranslation(double x, double y, double z){
tx = x; tx = x;
ty = y; ty = y;
tz = z; tz = z;
} }
RigidBodyTransformation::getRotation(){ QQuaternion RigidBodyTransformation::getRotation(){
return rotation; return rotation;
} }
RigidBodyTransformation::setRotation(QQuaternion newRotation){ void RigidBodyTransformation::setRotation(QQuaternion newRotation){
rotation = newRotation; rotation = newRotation;
} }
#ifndef RIGIDBODYTRANSFORMATION_H #ifndef RIGIDBODYTRANSFORMATION_H
#define RIGIDBODYTRANSFORMATION_H #define RIGIDBODYTRANSFORMATION_H
#include <QQuaternion>
#include <primitive.h>
class RigidBodyTransformation class RigidBodyTransformation
{ {
public: public:
RigidBodyTransformation(); RigidBodyTransformation(Primitive child);
void setTranslation(double x, double y, double z = 0); void setTranslation(double x, double y, double z);
void setRotation(QQuaternion newRotation); void setRotation(QQuaternion newRotation);
QQuaternion getRotation(); QQuaternion getRotation();
......
#ifndef GLWIDGET_H
#define GLWIDGET_H
#include <QGLWidget>
#include <gl/GLU.h>
#include <QDebug>
#include <QWheelEvent>
#include <QQuaternion>
#include <QMatrix4x4>
#include <math.h>
#include <QVector3D>
#include <QGLShaderProgram>
#include <QGLShader>
class WidgetFront : public QGLWidget
{
Q_OBJECT //from HelloGL Example
public:
WidgetFront(QWidget *parent = 0);
~WidgetFront();
//From HelloGL example.
QSize minimumSizeHint() const;
QSize sizeHint() const;
protected:
//4.1 Core Functionality
void initializeGL();
void paintGL();
void resizeGL(int width, int height);
void mousePressEvent(QMouseEvent *event);
void mouseMoveEvent(QMouseEvent *event);
void wheelEvent(QWheelEvent *event);
private:
//tesselation slider
int tesselation;
//zoom camera
const double cameraZoomDefault = -5;
double cameraZoom;
double cameraX, cameraY;
//translate camera
QPoint clickStartPosition;
bool rightButtonPressed;
double translatex, translatey;
//rotate cube
bool leftButtonPressed;
QQuaternion qubeRotationQuaternion;
QPoint screenCenter;//Center of screen in pixel coordinates
//Phong Shader
QGLShaderProgram *phongShader;
public slots:
//4.1.1 slots for shading modes
void shadeWireframeSlot();
void shadeFlatSlot();
void shadeGouraudSlot();
void shadePhongSlot();
void setTessellation(int t);
void resetCamera();
};
#endif // GLWIDGET_H
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment