QtでOpenGL:タイマーを使ったアニメーション
概要
QGLWidgetのpaintGL()はupdateGL()がシグナルとなって呼ばれます。
ここではタイマーを使って一定間隔ごとにupdateGL()を呼ぶことでアニメーションさせます。
タイマーは、QBasicTimerクラスを用います。
ここではタイマーを使って一定間隔ごとにupdateGL()を呼ぶことでアニメーションさせます。
タイマーは、QBasicTimerクラスを用います。
使い方は下記の通りです。
#include <QBasicTimer>
QBasicTimer timer;
void GLWidget::initializeGL()
{
//タイマーの開始、間隔を16ms(≒60fps)に設定
timer.start(16, this);
}
void GLWidget::timerEvent(QTimerEvent *e)
{
Q_UNUSED(e);
updateGL();
}
このとき、timer.startの第一引数がタイマーの間隔で、第二引数がtimerEventメソッドを持つオブジェクトを渡します。
ここではGLWidgetのメソッドとしてtiemrEventを用意しているので、第二引数はthisとします。
ここではGLWidgetのメソッドとしてtiemrEventを用意しているので、第二引数はthisとします。
ソースコード
- glwidget.h
#ifndef GLWIDGET_H
#define GLWIDGET_H
#include <QGLWidget>
#include <QVector3D>
#include <QBasicTimer>
class GLWidget : public QGLWidget
{
Q_OBJECT
public:
GLWidget(QWidget *parent = 0);
~GLWidget();
protected:
void timerEvent(QTimerEvent *e);
protected:
virtual void initializeGL();
virtual void resizeGL( int w, int h );
virtual void paintGL();
GLuint createCube();
private:
QBasicTimer *timer;
private:
GLfloat angle;
GLuint cubeList;
};
#endif // GLWIDGET_H
- glwidget.cpp
#include "glwidget.h"
#include <math.h>
GLWidget::GLWidget(QWidget *parent):
QGLWidget(parent),
timer(new QBasicTimer)
{
}
GLWidget::~GLWidget()
{
delete timer; timer = 0;
}
void GLWidget::timerEvent(QTimerEvent *e)
{
Q_UNUSED(e);
updateGL();
}
void GLWidget::initializeGL()
{
glClearColor(0.5, 0.5, 0.5, 1.0);
glEnable(GL_DEPTH_TEST);
//カリング:表面のみ表示
glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);
//光源有効
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
//光源の設定
GLfloat light_position[] = { -50.0, 50.0, 50.0, 1.0 };
GLfloat light_ambient[] = { 0.2, 0.2, 0.2, 1.0 };
GLfloat light_diffuse[] = { 1.0, 1.0, 1.0, 1.0 };
GLfloat light_specular[] = { 1.0, 1.0, 1.0, 1.0 };
glLightfv( GL_LIGHT0, GL_POSITION, light_position );
glLightfv( GL_LIGHT0, GL_AMBIENT, light_ambient );
glLightfv( GL_LIGHT0, GL_DIFFUSE, light_diffuse );
glLightfv( GL_LIGHT0, GL_SPECULAR, light_specular );
cubeList = createCube();
timer->start(16, this); // タイマー開始
}
void GLWidget::resizeGL( int w, int h )
{
glViewport(0, 0, w, h);
//プロジェクション・マトリックス設定
glMatrixMode (GL_PROJECTION);
glLoadIdentity();
gluPerspective(30.0, (double)w / (double)h, 1.0, 100.0);
}
void GLWidget::paintGL()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
//モデル・ビュー・マトリックス設定
glMatrixMode (GL_MODELVIEW);
glLoadIdentity();
//カメラ設定
gluLookAt(3.0, 4.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
glPushMatrix();
{ // 直方体の表示
//材質設定
GLfloat red[] = { 0.8, 0.2, 0.2, 1.0 };
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, red);
glRotatef(angle, 0.0, 1.0, 0.0); // 回転
//glCallList(cubeList);
glCallList(sphereList);
}
glPopMatrix();
angle = (angle>360.0) ? angle-360.0 : angle+1;
}
GLuint GLWidget::createCube()
{
GLuint index = glGenLists(1);
float lx = 0.5f;
float ly = 0.5f;
float lz = 0.5f;
glNewList(index, GL_COMPILE);
// sides
glBegin (GL_TRIANGLE_STRIP);
glNormal3f (-1,0,0);
glVertex3f (-lx,-ly,-lz);
glVertex3f (-lx,-ly,lz);
glVertex3f (-lx,ly,-lz);
glVertex3f (-lx,ly,lz);
glNormal3f (0,1,0);
glVertex3f (lx,ly,-lz);
glVertex3f (lx,ly,lz);
glNormal3f (1,0,0);
glVertex3f (lx,-ly,-lz);
glVertex3f (lx,-ly,lz);
glNormal3f (0,-1,0);
glVertex3f (-lx,-ly,-lz);
glVertex3f (-lx,-ly,lz);
glEnd();
// top face
glBegin (GL_TRIANGLE_FAN);
glNormal3f (0,0,1);
glVertex3f (-lx,-ly,lz);
glVertex3f (lx,-ly,lz);
glVertex3f (lx,ly,lz);
glVertex3f (-lx,ly,lz);
glEnd();
// bottom face
glBegin (GL_TRIANGLE_FAN);
glNormal3f (0,0,-1);
glVertex3f (-lx,-ly,-lz);
glVertex3f (-lx,ly,-lz);
glVertex3f (lx,ly,-lz);
glVertex3f (lx,-ly,-lz);
glEnd();
glEndList();
return index;
}