This repository has been archived on 2020-03-09. You can view files and clone it, but cannot push or open issues or pull requests.
pg-tp4/glarea.cpp
2020-03-09 08:45:43 +01:00

183 lines
4.8 KiB
C++

// CC-BY Edouard.Thiel@univ-amu.fr - 22/01/2019
#include "glarea.h"
#include <QDebug>
#include <QSurfaceFormat>
#include <QMatrix4x4>
#include <stdio.h>
static const QString vertexShaderFile = ":/basic.vsh";
static const QString fragmentShaderFile = ":/basic.fsh";
GLArea::GLArea(QWidget *parent) :
QOpenGLWidget(parent)
{
qDebug() << "init GLArea" ;
QSurfaceFormat sf;
sf.setDepthBufferSize(24);
sf.setSamples(16);
setFormat(sf);
qDebug() << "Depth is"<< format().depthBufferSize();
setEnabled(true); // Événements clavier et souris.
setFocusPolicy(Qt::StrongFocus); // Accepte focus.
setFocus(); // Donne le focus.
timer = new QTimer(this);
timer->setInterval(16); // ms
connect(timer, SIGNAL(timeout()), this, SLOT(onTimeout()));
}
GLArea::~GLArea()
{
qDebug() << "destroy GLArea";
delete timer;
// Contrairement aux méthodes virtuelles initializeGL, resizeGL et repaintGL,
// dans le destructeur le contexte GL n'est pas automatiquement rendu courant.
makeCurrent();
// ici destructions de ressources GL
doneCurrent();
}
void GLArea::initializeGL()
{
qDebug() << __FUNCTION__ ;
initializeOpenGLFunctions();
glEnable(GL_DEPTH_TEST);
// Shaders.
program = new QOpenGLShaderProgram(this);
program->addShaderFromSourceFile
(QOpenGLShader::Vertex, vertexShaderFile);
program->addShaderFromSourceFile
(QOpenGLShader::Fragment, fragmentShaderFile);
if (!program->link()) {
qWarning("Failed to compile and link shader program:");
qWarning() << program->log();
}
// Récupère identifiants de "variables" dans les shaders.
posAttr = program->attributeLocation("posAttr");
colAttr = program->attributeLocation("colAttr");
matrix_uniform = program->uniformLocation("matrix");
}
void GLArea::resizeGL(int w, int h)
{
qDebug() << __FUNCTION__ << w << h;
// C'est fait par défaut
glViewport(0, 0, w, h);
ratio = (double) w / h;
// doProjection();
}
void GLArea::paintGL()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
program->bind();
QMatrix4x4 matrix;
GLfloat hr = focal_length;
GLfloat wr = hr * ratio;
matrix.frustum(-wr, wr, -hr, hr, near_clip, far_clip);
matrix.translate(0, 0, -distance);
matrix.rotate(angle, 0, 1, 0);
matrix.rotate(horiz_angle, 0,
cos(vert_angle * 2*M_PI /360),
sin(vert_angle * 2*M_PI /360));
matrix.rotate(vert_angle, 1, 0, 0);
program->setUniformValue(matrix_uniform, matrix);
scene.draw((QOpenGLFunctions&) (*this), program, matrix_uniform,
anim * 360, matrix, posAttr, colAttr);
program->release();
}
void GLArea::keyPressEvent(QKeyEvent *ev)
{
QString text = ev->text();
switch(ev->key()) {
case Qt::Key_A:
timer->isActive() ? timer->stop() : timer->start();
break;
case Qt::Key_Z:
setDistance(distance + (text == "z" ? -distance_step : distance_step));
break;
case Qt::Key_R:
setFocalLength(focal_length + (text == "r" ? -focal_length_step : focal_length_step));
break;
case Qt::Key_N:
setNearClip(near_clip + (text == "n" ? -near_clip_step : near_clip_step));
break;
case Qt::Key_F:
setFarClip(far_clip + (text == "f" ? -far_clip_step : far_clip_step));
break;
case Qt::Key_Space:
setAngle(angle + angle_step);
update();
break;
}
}
void GLArea::mousePressEvent(QMouseEvent *ev)
{
mouse_last[0] = ev->x() / (float) width();
mouse_last[1] = ev->y() / (float) height();
}
void GLArea::mouseMoveEvent(QMouseEvent *ev)
{
float x = ev->x() / (float) width();
float y = ev->y() / (float) height();
float dx = x - mouse_last[0];
float dy = y - mouse_last[1];
horiz_angle += dx * 200;
vert_angle += dy * 200;
if (vert_angle > 90) vert_angle = 90;
if (vert_angle < -90) vert_angle = -90;
mouse_last[0] = x;
mouse_last[1] = y;
update();
}
void GLArea::wheelEvent(QWheelEvent *ev)
{
setDistance(distance - ev->angleDelta().y() / 1000.);
update();
}
void GLArea::onTimeout()
{
anim += 0.0001;
if (anim > 1) anim--;
update();
}
#define SET_VALUE(orig, signal) \
qDebug() << "GLArea, setting " #orig " from" << orig << "to" << value; \
if (value > orig##_max) value = orig##_max;\
if (value < orig##_min) value = orig##_min;\
if (value != orig) {\
orig = value;\
emit signal(orig);\
update();\
}
void GLArea::setDistance(double value) { SET_VALUE(distance, distanceChanged); }
void GLArea::setFocalLength(double value) { SET_VALUE(focal_length, focalLengthChanged); }
void GLArea::setNearClip(double value) { SET_VALUE(near_clip, nearClipChanged); }
void GLArea::setFarClip(double value) { SET_VALUE(far_clip, farClipChanged); }
void GLArea::setAngle(double value)
{
while (value > angle_max) value -= angle_max;
while (value < angle_min) value += angle_min;
SET_VALUE(angle, angleChanged);
}
#undef SET_VALUE