вторник, 29 мая 2012 г.

Qt + OpenGL встроенными методами

Рано или поздно каждый просто жаждет дорваться до рисования 3Д графики. Я не смогу вам описать тут все функции работы с OpenGL (да и не особо хочу), за этим вам гораздо лучше обратиться к другим источникам (например: NeHe Tutorials ). Но как нарисовать простую 3Д фигуру я вам здесь наглядно покажу. На выходе будет окошко, с вращающимся кубиком:


Итак, первым делом необходимо проверить, есть ли у нас модуль работы с OpenGL. Для этого откройте любой пример OpenGL, который есть в составе QtSDK. Если соберётся и работает то вам повезло, иначе - неповезло :)
Если не повезло собирайте его, либо пересоберите либу целиком.

Итак, будем считать OpenGL у нас есть. Теперь необходимо написать widget для работы с OpenGL.
Наследуется наш виджет от QGLWidget. Кроме того, необходимо в обязательном порядке определить несколько методов (все они указаны в классе).

#ifndef MYGLWIDGET_H
#define MYGLWIDGET_H
#include <QGLWidget>
#include <QTimer>
#include <GL/glu.h>
class myGLWidget : public QGLWidget
{
    Q_OBJECT
public:
    explicit myGLWidget(QWidget *parent = 0);
    
private:
    void initializeGL(); // функция инициализации OpenGL
    void resizeGL(int w, int h); //функция обработки изменения размера вывода
    void paintGL(); // функция прорисовки
private:
    GLfloat rtri;   // парачка переменных для рисования
    GLfloat rquad;    
    
};
#endif // MYGLWIDGET_H

Функция инициализации прорисовки и прочее для тех, кто знает OpenGL стандартные. Для тех же кто хочет что-нибудь вывести, я приведу эти функции в качестве примера.

void myGLWidget::initializeGL()
{
    // Set up the rendering context, define display lists etc.:
    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
    glClearDepth(1.0);
    glDepthFunc(GL_LESS);
    glEnable(GL_DEPTH_TEST);
    glShadeModel(GL_SMOOTH);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(45.0f,(GLfloat)this->width()/(GLfloat)this->height(),0.1f,100.0f);
    glMatrixMode(GL_MODELVIEW);
}
void myGLWidget::paintGL()
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glLoadIdentity();
    glTranslatef(-1.5f,0.0f,-6.0f);
    glRotatef(rtri,0.0f,1.0f,0.0f);
// здесь рисуется кристалл из треугольников
glBegin(GL_TRIANGLES); glColor3f(1.0f,0.0f,0.0f); glVertex3f( 0.0f, 1.0f, 0.0f); glColor3f(0.0f,1.0f,0.0f); glVertex3f(-1.0f,-1.0f, 1.0f); glColor3f(0.0f,0.0f,1.0f); glVertex3f( 1.0f,-1.0f, 1.0f); glColor3f(1.0f,0.0f,0.0f); glVertex3f( 0.0f, 1.0f, 0.0f); glColor3f(0.0f,0.0f,1.0f); glVertex3f( 1.0f,-1.0f, 1.0f); glColor3f(0.0f,1.0f,0.0f); glVertex3f( 1.0f,-1.0f, -1.0f); glColor3f(1.0f,0.0f,0.0f); glVertex3f( 0.0f, 1.0f, 0.0f); glColor3f(0.0f,1.0f,0.0f); glVertex3f( 1.0f,-1.0f, -1.0f); glColor3f(0.0f,0.0f,1.0f); glVertex3f(-1.0f,-1.0f, -1.0f); glColor3f(1.0f,0.0f,0.0f); glVertex3f( 0.0f, 1.0f, 0.0f); glColor3f(0.0f,0.0f,1.0f); glVertex3f(-1.0f,-1.0f,-1.0f); glColor3f(0.0f,1.0f,0.0f); glVertex3f(-1.0f,-1.0f, 1.0f); glEnd(); glLoadIdentity(); glTranslatef(1.5f,0.0f,-7.0f); glRotatef(rquad,1.0f,1.0f,1.0f);
// здесь рисуется куб
glBegin(GL_QUADS); glColor3f(0.0f,1.0f,0.0f); glVertex3f( 1.0f, 1.0f,-1.0f); glVertex3f(-1.0f, 1.0f,-1.0f); glVertex3f(-1.0f, 1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, 1.0f); glColor3f(1.0f,0.5f,0.0f); glVertex3f( 1.0f,-1.0f, 1.0f); glVertex3f(-1.0f,-1.0f, 1.0f); glVertex3f(-1.0f,-1.0f,-1.0f); glVertex3f( 1.0f,-1.0f,-1.0f); glColor3f(1.0f,0.0f,0.0f); glVertex3f( 1.0f, 1.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 1.0f); glVertex3f(-1.0f,-1.0f, 1.0f); glVertex3f( 1.0f,-1.0f, 1.0f); glColor3f(1.0f,1.0f,0.0f); glVertex3f( 1.0f,-1.0f,-1.0f); glVertex3f(-1.0f,-1.0f,-1.0f); glVertex3f(-1.0f, 1.0f,-1.0f); glVertex3f( 1.0f, 1.0f,-1.0f); glColor3f(0.0f,0.0f,1.0f); glVertex3f(-1.0f, 1.0f, 1.0f); glVertex3f(-1.0f, 1.0f,-1.0f); glVertex3f(-1.0f,-1.0f,-1.0f); glVertex3f(-1.0f,-1.0f, 1.0f); glColor3f(1.0f,0.0f,1.0f); glVertex3f( 1.0f, 1.0f,-1.0f); glVertex3f( 1.0f, 1.0f, 1.0f); glVertex3f( 1.0f,-1.0f, 1.0f); glVertex3f( 1.0f,-1.0f,-1.0f); glEnd(); rtri+=0.7f; rquad-=0.75f; } void myGLWidget::resizeGL(int w, int h) { if (h==0) h=1; glViewport(0, 0, w, h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(45.0f,(GLfloat)w/(GLfloat)h,0.1f,100.0f); glMatrixMode(GL_MODELVIEW); }
Теперь главная мелочь. В данном случае, если мы оставим всё, как есть, у нас выведется статичная картинка. Если же вы хотите, чтобы картинка менялась, надо окно перерисовывать:
myGLWidget::myGLWidget(QWidget *parent) :
    QGLWidget(parent)
{
    QTimer *timer = new QTimer(this);
    timer->setInterval(30);
    connect(timer, SIGNAL(timeout()), this, SLOT(updateGL()));
    timer->start();
}
Если у вас не соберётся проект (а он и не соберётся), вы забыли подключить необходимые библиотеки:
QT += opengl
LIBS += -lGLU

Собирал я эту красоту под убунтой, так что под окнами, извиняйте, но с библиотеками мучайтесь сами :).


1 комментарий: