Commit e2c4da19 by Alisa Jung

toolbar stuff: switch mode and viewport mode

parent d5b0a410
...@@ -17,13 +17,15 @@ SOURCES += main.cpp\ ...@@ -17,13 +17,15 @@ SOURCES += main.cpp\
myglwidget.cpp \ myglwidget.cpp \
scenegraph.cpp \ scenegraph.cpp \
primitive.cpp \ primitive.cpp \
rigidbodytransformation.cpp rigidbodytransformation.cpp \
widgetfront.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
RESOURCES += \ RESOURCES += \
helloqube.qrc helloqube.qrc
......
...@@ -7,5 +7,15 @@ ...@@ -7,5 +7,15 @@
<file>img/wireframe.png</file> <file>img/wireframe.png</file>
<file>phong.frag</file> <file>phong.frag</file>
<file>phong.vert</file> <file>phong.vert</file>
<file>grapa-a2-iconset/box.png</file>
<file>grapa-a2-iconset/camera.png</file>
<file>grapa-a2-iconset/cone.png</file>
<file>grapa-a2-iconset/cylinder.png</file>
<file>grapa-a2-iconset/select.png</file>
<file>grapa-a2-iconset/sphere.png</file>
<file>grapa-a2-iconset/torus.png</file>
<file>grapa-a2-iconset/view-dual.png</file>
<file>grapa-a2-iconset/viewports.png</file>
<file>grapa-a2-iconset/view-single.png</file>
</qresource> </qresource>
</RCC> </RCC>
...@@ -101,6 +101,68 @@ MainWindow::MainWindow(QWidget *parent) ...@@ -101,6 +101,68 @@ MainWindow::MainWindow(QWidget *parent)
resetCameraAction->setIcon(QIcon(":/img/cam_home.png")); resetCameraAction->setIcon(QIcon(":/img/cam_home.png"));
connect(resetCameraAction,SIGNAL(triggered(bool)),myGLWidget,SLOT(resetCamera())); connect(resetCameraAction,SIGNAL(triggered(bool)),myGLWidget,SLOT(resetCamera()));
toolBar->addAction(resetCameraAction); toolBar->addAction(resetCameraAction);
toolBar->insertSeparator(resetCameraAction);
/* Assignment 2*/
//2 Camera Mode, Object Manipulation Mode
modeCameraAction = new QAction("Camera Mode",toolBar);
modeCameraAction->setIcon(QIcon(":/grapa-a2-iconset/camera.png"));
modeCameraAction->setCheckable(true);
modeCameraAction->setChecked(true);
//TODO connect slot
toolBar->addAction(modeCameraAction);
toolBar->insertSeparator(modeCameraAction);
modeManipulateAction = new QAction("Manipulation Mode", toolBar);
modeManipulateAction->setIcon(QIcon(":/grapa-a2-iconset/select.png"));
modeManipulateAction->setCheckable(true);
//TODO connect slot
toolBar->addAction(modeManipulateAction);
modeSwitchGroup = new QActionGroup(toolBar);
modeSwitchGroup->addAction(modeCameraAction);
modeSwitchGroup->addAction(modeManipulateAction);
//2 Switch view modes
viewButton = new QToolButton(toolBar);
viewButton->setIcon(QIcon(":/grapa-a2-iconset/viewports.png"));
viewMenu = new QMenu(viewButton);
viewButton->setMenu(viewMenu);
viewButton->setPopupMode(QToolButton::MenuButtonPopup);
toolBar->addWidget(viewButton);
viewGroup = new QActionGroup(viewMenu);
singleViewAction = new QAction("Single View",viewMenu);
singleViewAction->setIcon(QIcon(":/grapa-a2-iconset/view-single.png"));
singleViewAction->setCheckable(true);
singleViewAction->setChecked(true);
singleViewAction->setShortcut(QKeySequence(Qt::Key_1));
//TODO connect slot
viewMenu->addAction(singleViewAction);
viewMenu->setDefaultAction(singleViewAction);
viewGroup->addAction(singleViewAction);
dualViewAction = new QAction("Dual View",viewMenu);
dualViewAction->setIcon(QIcon(":/grapa-a2-iconset/view-dual.png"));
dualViewAction->setCheckable(true);
dualViewAction->setShortcut(QKeySequence(Qt::Key_2));
//TODO connect slot
viewMenu->addAction(dualViewAction);
viewGroup->addAction(dualViewAction);
quadViewAction = new QAction("Quad View",viewMenu);
quadViewAction->setIcon(QIcon(":/grapa-a2-iconset/viewports.png"));
quadViewAction->setCheckable(true);
quadViewAction->setShortcut(QKeySequence(Qt::Key_4));
//TODO connect slot
viewMenu->addAction(quadViewAction);
viewGroup->addAction(quadViewAction);
} }
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include <QStatusBar> #include <QStatusBar>
#include <myglwidget.h> #include <myglwidget.h>
#include <QSlider> #include <QSlider>
#include <QToolButton>
class MainWindow : public QMainWindow class MainWindow : public QMainWindow
{ {
...@@ -49,6 +50,17 @@ private: ...@@ -49,6 +50,17 @@ private:
QAction *resetCameraAction; QAction *resetCameraAction;
QAction *modeCameraAction;
QAction *modeManipulateAction;
QActionGroup *modeSwitchGroup;
QAction *singleViewAction;
QAction *dualViewAction;
QAction *quadViewAction;
QActionGroup *viewGroup;
QToolButton* viewButton;
QMenu* viewMenu;
//Widgets //Widgets
MyGLWidget *myGLWidget; MyGLWidget *myGLWidget;
......
...@@ -117,15 +117,14 @@ void MyGLWidget::paintGL(){ ...@@ -117,15 +117,14 @@ void MyGLWidget::paintGL(){
double dist = qubeWidth/(double)tesselation; double dist = qubeWidth/(double)tesselation;
//for cube rotation //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);
QMatrix4x4 translateRot2 = QMatrix4x4(1,0,0,-translatex,0,1,0,-translatey,0,0,1,0,0,0,0,1);
QMatrix4x4 translateText = QMatrix4x4(1,0,0,2,0,1,0,0,0,0,1,0,0,0,0,1);
//for cube rotation
QMatrix4x4 m = QMatrix4x4(); QMatrix4x4 m = QMatrix4x4();
m.rotate(qubeRotationQuaternion); m.rotate(qubeRotationQuaternion);
//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());
...@@ -152,11 +151,6 @@ void MyGLWidget::paintGL(){ ...@@ -152,11 +151,6 @@ void MyGLWidget::paintGL(){
} }
} }
glEnd(); glEnd();
//reference for previous front
// glVertex3f(0.5, 0.5, 0.5);//4
// glVertex3f(-0.5, 0.5, 0.5);//3
// glVertex3f(-0.5, -0.5, 0.5);//2
// glVertex3f(0.5, -0.5, 0.5);//1
//oben // y-Achse //oben // y-Achse
GLfloat green[] = {0,1,0}; GLfloat green[] = {0,1,0};
......
#include "widgetfront.h"
widgetFront::widgetFront()
{
}
#include "WidgetFront.h"
WidgetFront::WidgetFront(QWidget *parent)
: QGLWidget(QGLFormat(QGL::SampleBuffers), parent)
{
tesselation = 1;
qubeRotationQuaternion = QQuaternion();
translatex = 0;
translatey = 0;
cameraZoom = cameraZoomDefault;
clickStartPosition = QPoint(0,0);
rightButtonPressed = false;
}
WidgetFront::~WidgetFront()
{
/*http://doc.qt.io/qt-4.8/qt-opengl-hellogl-example.html :
* We use a destructor to ensure that any OpenGL-specific
* data structures are deleted when the widget is no longer
* needed (although in this case nothing needs cleaning up).
*/
//In helloGL example: nothing needs cleaning up.
}
/*
* From Example
* We provide size hint functions to ensure that
* the widgetis shown at a reasonable size:
*/
QSize WidgetFront::minimumSizeHint() const
{
return QSize(50, 50);
}
/*
* From Example
* We provide size hint functions to ensure that
* the widgetis shown at a reasonable size:
*/
QSize WidgetFront::sizeHint() const
{
return QSize(600, 400);
}
void WidgetFront::initializeGL()
{
glClearColor(0.0, 0.0, 0.0, 0.0);
glEnable(GL_DEPTH_TEST);
//Phong Shader:
QGLShader* vert = new QGLShader(QGLShader::Vertex);
qDebug() << "new vert shader";
QGLShader* frag = new QGLShader(QGLShader::Fragment);
qDebug() << "new frag shader";
bool e = QFile::exists(":/phong.vert");
qDebug() << "vert exists" << e;
bool successVertex = vert->compileSourceFile(":/phong.vert");
if (!successVertex)qDebug() << "Vertex compilation failed.";
else qDebug() << "Vertex compiled.";
bool successFragment = frag->compileSourceFile(":/phong.frag");
if (!successFragment) qDebug() << "Frag failed";
else qDebug() << "frag success";
phongShader = new QGLShaderProgram(this);
phongShader->addShader(vert);
phongShader->addShader(frag);
phongShader->link();
shadeFlatSlot();//set up flat shading
qDebug() << "flat done";
// glEnable(GL_CULL_FACE);//backface culling.
// glCullFace(GL_BACK);//backface culling
// glEnable(GL_COLOR_MATERIAL); //Habe ich für glColor3f gebraucht. Wieder raus für Material. //In order to use both color and lighting you must activate openGL color materials
//4.1.1
/*
* The initial state of the OpenGL state machine is defined in
initializeGL(). Furthermore, you can set all OpenGL parameters
that will not change during program execution here as well, for
example, the background color.
*/
glEnable(GL_LIGHTING);//enable lighting.
glEnable(GL_LIGHT0);//enable an OpenGL light
/*
* https://msdn.microsoft.com/en-us/library/windows/desktop/dd373578%28v=vs.85%29.aspx
* The glLightfv function returns light source parameter values.
* GL_POSITION:
* The params parameter contains four floating-point values
* that specify the position of the light in homogeneous object
* coordinates. Both integer and floating-point values are
* mapped directly. Neither integer nor floating-point values
* are clamped.
*/
static GLfloat lightPosition[4] = {0.5, 0.0, 2.0, 1.0};
glLightfv(GL_LIGHT0,GL_POSITION,lightPosition);//set Position of light source.
}
void WidgetFront::paintGL(){
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
//zoom camera
glTranslatef(cameraX,cameraY,cameraZoom);//Kamera sitzt sonst in (0,0,0) und man sieht nichts (duh)
//for translation
double qubeWidth = 1.0;
double dist = qubeWidth/(double)tesselation;
//for cube translation
QMatrix4x4 translateRot1 = QMatrix4x4(1,0,0,translatex,0,1,0,translatey,0,0,1,0,0,0,0,1);
//for cube rotation
QMatrix4x4 m = QMatrix4x4();
m.rotate(qubeRotationQuaternion);
//stack matrices
glMultMatrixf(translateRot1.data());//Punkte zurück schieben damit rotation um qube zentrum ist
glMultMatrixf(m.data());
//4.1.1 Unit Qube + Tesselation + Diffuse Material
{
GLfloat specularColor[] = {1,1,1};
GLfloat shininess[] = {128};//specular exponent
glMaterialfv(GL_FRONT,GL_SPECULAR,specularColor);
glMaterialfv(GL_FRONT,GL_SHININESS,shininess);
//vorne // z-Achse
// glColor3f(0,0,1);//blau //alt und doof
GLfloat blue[] = {0,0,1};
glMaterialfv(GL_FRONT,GL_DIFFUSE,blue);
glNormal3f(0,0,1);
glBegin(GL_QUADS);
for (int i = 0; i < tesselation; i++){
for (int j = 0; j < tesselation; j++){
glVertex3f(0.5-dist*i,0.5-dist*j,0.5);
glVertex3f(0.5-dist*(i+1),0.5-dist*j,0.5);
glVertex3f(0.5-dist*(i+1),0.5-dist*(j+1),0.5);
glVertex3f(0.5-dist*i,0.5-dist*(j+1),0.5);
}
}
glEnd();
//oben // y-Achse
GLfloat green[] = {0,1,0};
glMaterialfv(GL_FRONT,GL_DIFFUSE,green);
glNormal3f(0,1,0);
glBegin(GL_QUADS);
for (int i = 0; i < tesselation; i++){
for (int j = 0; j < tesselation; j++){
glVertex3f(0.5-dist*(i+1), 0.5, 0.5-dist*(j+1));
glVertex3f(0.5-dist*(i+1), 0.5, 0.5-dist*j);
glVertex3f(0.5-dist*i, 0.5, 0.5-dist*j);
glVertex3f(0.5-dist*i, 0.5, 0.5-dist*(j+1));
}
}
glEnd();
//rechts //x-Achse
GLfloat red[] = {1,0,0};
glMaterialfv(GL_FRONT,GL_DIFFUSE,red);
glNormal3f(1,0,0);
glBegin(GL_QUADS);
for (int i = 0; i < tesselation; i++){
for (int j = 0; j < tesselation; j++){
glVertex3f(0.5, 0.5-dist*i, 0.5-dist*j);
glVertex3f(0.5, 0.5-dist*(i+1), 0.5-dist*j);
glVertex3f(0.5, 0.5-dist*(i+1), 0.5-dist*(j+1));
glVertex3f(0.5, 0.5-dist*i, 0.5-dist*(j+1));
}
}
glEnd();
//hinten // z-Achse
GLfloat yellow[] = {1,0.9f,0};
glMaterialfv(GL_FRONT,GL_DIFFUSE,yellow);
glNormal3f(0,0,-1);
glBegin(GL_QUADS);
for (int i = 0; i < tesselation; i++){
for (int j = 0; j < tesselation; j++){
glVertex3f(0.5-dist*i, 0.5-dist*(j+1), -0.5);//4
glVertex3f(0.5-dist*(i+1), 0.5-dist*(j+1), -0.5);//3
glVertex3f(0.5-dist*(i+1), 0.5-dist*j, -0.5);//2
glVertex3f(0.5-dist*i, 0.5-dist*j, -0.5);//1
}
}
glEnd();
//links
GLfloat cyan[] = {0,1,1};
glMaterialfv(GL_FRONT,GL_DIFFUSE,cyan);
glNormal3f(-1,0,0);
glBegin(GL_QUADS);
for (int i = 0; i < tesselation; i++){
for (int j = 0; j < tesselation; j++){
glVertex3f(-0.5, 0.5-dist*i, 0.5-dist*(j+1));
glVertex3f(-0.5, 0.5-dist*(i+1), 0.5-dist*(j+1));
glVertex3f(-0.5, 0.5-dist*(i+1), 0.5-dist*j);
glVertex3f(-0.5, 0.5-dist*i, 0.5-dist*j);
}
}
glEnd();
//unten //-y
GLfloat magenta[] = {1,0,1};
glMaterialfv(GL_FRONT,GL_DIFFUSE,magenta);
glNormal3f(0,-1,0);
glBegin(GL_QUADS);
for (int i = 0; i < tesselation; i++){
for (int j = 0; j < tesselation; j++){
glVertex3f(0.5-dist*i, -0.5, 0.5-dist*(j+1));
glVertex3f(0.5-dist*i, -0.5, 0.5-dist*j);
glVertex3f(0.5-dist*(i+1), -0.5, 0.5-dist*j);
glVertex3f(0.5-dist*(i+1), -0.5, 0.5-dist*(j+1));
}
}
glEnd();
}
}
void WidgetFront::resizeGL(int width, int height){
double p = (double)width / (double)height;
qDebug() << "Resize to " << width << "," << height << ", Perspective: " << p;
glViewport(0,0,width,height);
glMatrixMode(GL_PROJECTION);//from HelloGL example
glLoadIdentity();
gluPerspective(45.0,p,0.1,1000);//set vof to 45°
glMatrixMode(GL_MODELVIEW);
screenCenter = QPoint((double)width/2.0,(double)height/2.0);//lieber zu oft casten bevors nicht tut...
}
void WidgetFront::mousePressEvent(QMouseEvent *event){
rightButtonPressed = false;
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 WidgetFront:: mouseMoveEvent(QMouseEvent *event){
//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 - clickStartPosition;
clickStartPosition = currentPosition;
translatex += 0.01*diff.x();
translatey -= 0.01*diff.y();
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();
}
}
//4.1.2 User Input: Zooming
void WidgetFront::wheelEvent(QWheelEvent *event){
cameraZoom += 0.01*event->delta();//0.01 seemed to be a good factor
qDebug() << "Cam zoom delta " << event->delta() << " stored " << cameraZoom;
updateGL();
}
//4.1.1 slots for shading modes
void WidgetFront::shadeWireframeSlot(){
qDebug() << "Wireframe selected";
phongShader->release();
glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);//Wireframe looks way cooler with both faces on
updateGL();
}
void WidgetFront::shadeFlatSlot(){
qDebug() << "Flat selected";
phongShader->release();
glShadeModel(GL_FLAT);
glPolygonMode(GL_FRONT,GL_FILL);
updateGL();
}
void WidgetFront::shadeGouraudSlot(){
qDebug() << "Gouraud selected";
phongShader->release();
glShadeModel(GL_SMOOTH);
glPolygonMode(GL_FRONT,GL_FILL);
updateGL();
}
void WidgetFront::shadePhongSlot(){
qDebug() << "Phong selected";
glPolygonMode(GL_FRONT,GL_FILL);
phongShader->bind();
updateGL();
}
//4.1.1 tesselation slot
void WidgetFront::setTessellation(int t){
qDebug() << "Tesselation: " << t;
tesselation = t;
updateGL();
}
void WidgetFront::resetCamera(){
qubeRotationQuaternion = QQuaternion();
translatex = 0;
translatey = 0;
cameraZoom = cameraZoomDefault;
updateGL();
}
#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