183 lines
4.8 KiB
C++
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(); // active le shader program
|
|
|
|
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
|