Commit 4332f836 by Alisa Jung

fertig bis trackball

parent 3ebc80d3
......@@ -95,6 +95,12 @@ MainWindow::MainWindow(QWidget *parent)
tesselationSlider->setValue(1);
connect(tesselationSlider,SIGNAL(valueChanged(int)),myGLWidget,SLOT(setTessellation(int)));
toolBar->addWidget(tesselationSlider);
//reset Camera button
resetCameraAction = new QAction("Reset Camera",toolBar);
connect(resetCameraAction,SIGNAL(triggered(bool)),myGLWidget,SLOT(resetCamera()));
toolBar->addAction(resetCameraAction);
}
MainWindow::~MainWindow()
......
......@@ -47,6 +47,8 @@ private:
QAction *shadePhongAction;
QActionGroup *shaderGroup;
QAction *resetCameraAction;
//Widgets
MyGLWidget *myGLWidget;
......
......@@ -4,9 +4,10 @@ MyGLWidget::MyGLWidget(QWidget *parent)
: QGLWidget(QGLFormat(QGL::SampleBuffers), parent)
{
tesselation = 1;
cameraZoom = -5;
translationX = 0;
translationY = 0;
qubeRotationQuaternion = QQuaternion();
tx = 0;
ty = 0;
cameraZoom = cameraZoomDefault;
clickStartPosition = QPoint(0,0);
rightButtonPressed = false;
}
......@@ -97,11 +98,18 @@ void MyGLWidget::paintGL(){
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glTranslatef(translationX,translationY,cameraZoom);//Kamera sitzt sonst in (0,0,0) und man sieht nichts (duh)
//zoom camera
glTranslatef(0,0,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 rotation
QMatrix4x4 m = QMatrix4x4();
m.rotate(qubeRotationQuaternion);
glMultMatrixf(m.data());
//4.1.1 Unit Qube + Tesselation + Diffuse Material
{
glBegin(GL_QUADS);
......@@ -116,14 +124,16 @@ void MyGLWidget::paintGL(){
// glColor3f(0,0,1);//blau
GLfloat blue[] = {0,0,1};
glMaterialfv(GL_FRONT,GL_DIFFUSE,blue);
glNormal3f(0,0,1);
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);
glVertex3f(tx+0.5-dist*i,ty+0.5-dist*j,0.5);
glVertex3f(tx+0.5-dist*(i+1),ty+0.5-dist*j,0.5);
glVertex3f(tx+0.5-dist*(i+1),ty+0.5-dist*(j+1),0.5);
glVertex3f(tx+0.5-dist*i,ty+0.5-dist*(j+1),0.5);
}
}
//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
......@@ -132,12 +142,13 @@ void MyGLWidget::paintGL(){
//oben // y-Achse
GLfloat green[] = {0,1,0};
glMaterialfv(GL_FRONT,GL_DIFFUSE,green);
glNormal3f(0,1,0);
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));
glVertex3f(tx+0.5-dist*(i+1), ty+0.5, 0.5-dist*(j+1));
glVertex3f(tx+0.5-dist*(i+1), ty+0.5, 0.5-dist*j);
glVertex3f(tx+0.5-dist*i, ty+0.5, 0.5-dist*j);
glVertex3f(tx+0.5-dist*i, ty+0.5, 0.5-dist*(j+1));
}
}
......@@ -145,12 +156,13 @@ void MyGLWidget::paintGL(){
//rechts //x-Achse
GLfloat red[] = {1,0,0};
glMaterialfv(GL_FRONT,GL_DIFFUSE,red);
glNormal3f(1,0,0);
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));
glVertex3f(tx+0.5, ty+0.5-dist*i, 0.5-dist*j);
glVertex3f(tx+0.5, ty+0.5-dist*(i+1), 0.5-dist*j);
glVertex3f(tx+0.5, ty+0.5-dist*(i+1), 0.5-dist*(j+1));
glVertex3f(tx+0.5, ty+0.5-dist*i, 0.5-dist*(j+1));
}
}
......@@ -158,36 +170,39 @@ void MyGLWidget::paintGL(){
//hinten // z-Achse
GLfloat yellow[] = {1,0.9,0};
glMaterialfv(GL_FRONT,GL_DIFFUSE,yellow);
glNormal3f(0,0,-1);
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
glVertex3f(tx+0.5-dist*i, ty+0.5-dist*(j+1), -0.5);//4
glVertex3f(tx+0.5-dist*(i+1), ty+0.5-dist*(j+1), -0.5);//3
glVertex3f(tx+0.5-dist*(i+1), ty+0.5-dist*j, -0.5);//2
glVertex3f(tx+0.5-dist*i,ty+ 0.5-dist*j, -0.5);//1
}
}
//links
GLfloat cyan[] = {0,1,1};
glMaterialfv(GL_FRONT,GL_DIFFUSE,cyan);
glNormal3f(-1,0,0);
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);
glVertex3f(tx-0.5, ty+0.5-dist*i, 0.5-dist*(j+1));
glVertex3f(tx-0.5, ty+0.5-dist*(i+1), 0.5-dist*(j+1));
glVertex3f(tx-0.5, ty+0.5-dist*(i+1), 0.5-dist*j);
glVertex3f(tx-0.5, ty+0.5-dist*i, 0.5-dist*j);
}
}
//unten //-y
GLfloat magenta[] = {1,0,1};
glMaterialfv(GL_FRONT,GL_DIFFUSE,magenta);
glNormal3f(0,-1,0);
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));
glVertex3f(tx+0.5-dist*i, ty-0.5, 0.5-dist*(j+1));
glVertex3f(tx+0.5-dist*i, ty-0.5, 0.5-dist*j);
glVertex3f(tx+0.5-dist*(i+1), ty-0.5, 0.5-dist*j);
glVertex3f(tx+0.5-dist*(i+1), ty-0.5, 0.5-dist*(j+1));
}
}
......@@ -199,28 +214,31 @@ void MyGLWidget::paintGL(){
void MyGLWidget::resizeGL(int width, int height){
double p = (double)width / (double)height;
qDebug() << "Resize to " << width << "," << height << ", Perspective: " << p;
//old:
// GLInt x = 0;//The lower-left corner of the viewport rectangle, in pixels. The default is (0,0).
// GLInt y = 0;//The lower-left corner of the viewport rectangle, in pixels. The default is (0,0).
// glViewport(x,y,width,height);//The width of the viewport. When an OpenGL context is first attached to a window, width and height are set to the dimensions of that window.
glViewport(0,0,width,height);
glMatrixMode(GL_PROJECTION);
glMatrixMode(GL_PROJECTION);//from HelloGL example
glLoadIdentity();
gluPerspective(45.0,p,0.1,1000);//TODO komisch: wenn schmaler als hoch auf einmal grau.
gluPerspective(45.0,p,0.1,1000);
glMatrixMode(GL_MODELVIEW);
screenCenter = QPoint((double)width/2.0,(double)height/2.0);//lieber zu oft casten bevors nicht tut...
}
void MyGLWidget::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 MyGLWidget:: mouseMoveEvent(QMouseEvent *event){
......@@ -229,11 +247,73 @@ void MyGLWidget:: mouseMoveEvent(QMouseEvent *event){
QPoint currentPosition = event->pos();
QPoint diff = currentPosition - clickStartPosition;
clickStartPosition = currentPosition;
translationX -= 0.01*diff.x();
translationY += 0.01*diff.y();
tx += 0.01*diff.x();
ty -= 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 yOld = ((double)(clickStartPosition.y() - screenCenter.y()));
QPoint newPosition = event->pos();
double xNew = ((double)(newPosition.x() - screenCenter.x()));
double yNew = ((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();
}
qDebug() << "mouse move button " << event->button();
}
//4.1.2 User Input: Zooming
......@@ -278,3 +358,11 @@ void MyGLWidget::setTessellation(int t){
tesselation = t;
updateGL();
}
void MyGLWidget::resetCamera(){
qubeRotationQuaternion = QQuaternion();
tx = 0;
ty = 0;
cameraZoom = cameraZoomDefault;
updateGL();
}
......@@ -5,6 +5,10 @@
#include <gl/GLU.h>
#include <QDebug>
#include <QWheelEvent>
#include <QQuaternion>
#include <QMatrix4x4>
#include <math.h>
#include <QVector3D>
class MyGLWidget : public QGLWidget
{
......@@ -28,11 +32,22 @@ protected:
void wheelEvent(QWheelEvent *event);
private:
//tesselation slider
int tesselation;
//zoom camera
const double cameraZoomDefault = -5;
double cameraZoom;
//translate camera
QPoint clickStartPosition;
bool rightButtonPressed;
double translationX, translationY;
double tx, ty;
//rotate cube
bool leftButtonPressed;
QQuaternion qubeRotationQuaternion;
QPoint screenCenter;//Center of screen in pixel coordinates
public slots:
......@@ -42,6 +57,7 @@ public slots:
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