PDA

View Full Version : QOpenGL QTimer, how do I animate this?



JerichoJosh
18th December 2013, 15:40
Hi everyone,

I'm drawing a large amount of triangles on the screen using the intialize-resize-paint method.
The program works, but without animation.
I've been trying for a long time to figure out how to use a Timer to animate this, but I haven't been able to find a way.
(Background info: the animation I want is to make the triangles rotate and scale individually.)
Can somebody help me?

Since it is quite a large program, I have brought the code down to structure only.

Thank you ahead of time!

In the main:



int main(int argc, char **argv)
{
QApplication a(argc,argv);

GlWidget w;
w.show();

return a.exec();
}


In the glwidget header file:


class GlWidget : public QGLWidget
{
Q_OBJECT //this macro is included because we might want to use signals and slots

public:
GlWidget(QWidget *parent = 0);
~GlWidget();
QSize sizeHint() const; //to set reasonable default sizes

protected:

void initializeGL();
void resizeGL(int width, int height);
void paintGL();

private:

makeTriangles();
QVector<QVector3D> vertices, colors;

};

In the glwidget source file:




#include "glwidget.h"

//! [0]
GlWidget::GlWidget(QWidget *parent) : QGLWidget(QGLFormat(), parent)
{
}

GlWidget::~GlWidget()
{
}


QSize GlWidget::sizeHint() const
{
return QSize(520, 640);
}
//! [0]


//! [1]

void GlWidget::initializeGL()
{
glEnable(GL_DEPTH_TEST);

glEnable(GL_CULL_FACE);

QGLWidget::qglClearColor(QColor(20,20,20,255));

shaderProgram.addShaderFromSourceFile(QGLShader::V ertex, ":/vertexShader.vsh");
shaderProgram.addShaderFromSourceFile(QGLShader::F ragment, ":/fragmentShader.fsh");
shaderProgram.link();

makeTriangles();
}
//! [1]

//! [2]

void GlWidget::resizeGL(int width, int height)
{
if (height == 0) {
height = 1;
}

pMatrix.setToIdentity();
pMatrix.perspective(60.0, (float) width / (float) height, 0.001, 1000);

glViewport(0, 0, width, height);
}
//! [2]

//! [3]
void GlWidget::paintGL()
{

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

QMatrix4x4 mMatrix;
QMatrix4x4 vMatrix;

shaderProgram.bind();

shaderProgram.setUniformValue("mvpMatrix", pMatrix * vMatrix * mMatrix);

shaderProgram.setAttributeArray("color", colors.constData());
shaderProgram.enableAttributeArray("color");

shaderProgram.setAttributeArray("vertex", vertices.constData());
shaderProgram.enableAttributeArray("vertex");

glDrawArrays(GL_TRIANGLES, 0, vertices.size());

shaderProgram.disableAttributeArray("vertex");
shaderProgram.disableAttributeArray("color");
shaderProgram.release();
}


GlWidget::makeTriangles()
{
/*specify vertices and colors of triangles, here, the variables vertices and color are defined*/
}
//! [3]

wysota
18th December 2013, 16:45
How are you using the timer? I think the simplest approach would be to make each triangle a QObject and use QPropertyAnimation to animate its state. Then through the use of signals, notify the view that it needs to be redrawn.

anda_skoa
18th December 2013, 16:49
One way would be to add Qt properties for values you want to animate individually and then use QPropertyAnimation to drive the value changes.

You would then also connect the properties' change signals to the updateGL() slot, so that it is called whenever any of those properties changes.

Cheers,
_

JerichoJosh
19th December 2013, 08:19
I tried using a QTimer, (copying the idea from a graphicsscene application I have made)

adding a declaration in the header:


QTimer *timer1;
public slots:
void doSomething();

adding the following lines to the constructor:


timer1 = new QTimer(this);
connect(timer1,SIGNAL(timeout()),this, SLOT(doSomething()));
timer1->start(10);

and finally adding the slot definition in the source file to test:


void GlWidget::doSomething()
{
qDebug() << "I'm doing something!"; //here I would like to call the function makeTriangles() to change the properties 'colors' and 'vertices'
}

But this apparentlly doesn't work.


I think the simplest approach would be to make each triangle a QObject and use QPropertyAnimation to animate its state. Then through the use of signals, notify the view that it needs to be redrawn.
Could you give me an example on how to do this, I have no clue how to implement that?

wysota
19th December 2013, 09:05
Could you give me an example on how to do this, I have no clue how to implement that?

Have a look at the Animation Framework docs.

JerichoJosh
19th December 2013, 10:47
Could you help me to implement a QTimer?
the documentation you gave me remains too abstract for me, and mostly related to qPainter

anda_skoa
19th December 2013, 15:25
I think what you will have to do is change values in your time slot and then call updateGL()

That will result in another call to paintGL() in which you can update your GL data.

Cheers,
_

wysota
19th December 2013, 17:59
Could you help me to implement a QTimer?
the documentation you gave me remains too abstract for me, and mostly related to qPainter

There is not a single reference to QPainter in the documentation I gave you.

8Observer8
30th March 2024, 13:41
Use QOpenGLWindow with the frameSwapped signal. This is my example with Qt 6.7 that prints delta time to the console:

main.cpp



#include <QtCore/QElapsedTimer>
#include <QtGui/QOpenGLFunctions>
#include <QtGui/QSurfaceFormat>
#include <QtOpenGL/QOpenGLWindow>
#include <QtWidgets/QApplication>

class OpenGLWindow : public QOpenGLWindow, private QOpenGLFunctions
{
public:

OpenGLWindow()
{
setTitle("OpenGL ES 2.0, Qt6, C++");
resize(380, 380);

QSurfaceFormat surfaceFormat;
surfaceFormat.setSwapInterval(1);
connect(this, SIGNAL(frameSwapped()), this, SLOT(update()));
setFormat(surfaceFormat);
}

private:

void initializeGL() override
{
initializeOpenGLFunctions();
glClearColor(0.2f, 0.2f, 0.2f, 1.f);
m_elapsedTimer.start();
}

void resizeGL(int w, int h) override
{
glViewport(0, 0, w, h);
}

void paintGL() override
{
float dt = m_elapsedTimer.elapsed() / 1000.f;
m_elapsedTimer.restart();
qDebug() << dt;
glClear(GL_COLOR_BUFFER_BIT);
}

private:
QElapsedTimer m_elapsedTimer;
};

int main(int argc, char *argv[])
{
QApplication::setAttribute(Qt::ApplicationAttribut e::AA_UseDesktopOpenGL);
QApplication app(argc, argv);
OpenGLWindow w;
w.show();
return app.exec();
}