Программирование игр, создание игрового движка, OpenGL, DirectX, физика, форум
GameDev.ru / Программирование / Статьи / OpenGL на Qt 4. Это просто! (часть 1)

OpenGL на Qt 4. Это просто! (часть 1)

Автор:

Это ознакомительная статья, посвящённая программированию 3D-графики OpenGL (Open Graphics Library — открытая графическая библиотека) с помощью кроссплатформенной библиотеки Qt 4 (Q + toolkit: «Q» — префикс классов (с красивым начертанием, по мнению разработчиков); toolkit — инструментарий). Я надеюсь, она окажется полезной для тех, кто впервые решил познакомиться с OpenGL и выбирает практичную и удобную библиотеку GUI (Graphical User Interface — графический интерфейс пользователя).

Список частей:

  • OpenGL на Qt 4. Это просто! (часть 1)
  • OpenGL на Qt 4. Это просто! (часть 2)
  • Введение
    An opensource of this lecture
      scene3D.h
      scene3D.cpp
      main.cpp
      lecture1.pro
    Модуль QtOpenGL
    Класс QGLWidget
      Инициализация контекста рендеринга
      Настройки окна виджета
      Вывод изображения
    Рисуем икосаэдр
      Обработка пользовательского ввода
      Используя массивы вершин
      Настройки
      Ещё раз про обработку сигналов
    Собираем всё вместе и не только!
    Литература

    Введение

    Возможности библиотеки Qt далеко выходят за рамки разработки GUI и она считается одной из самых успешных библиотек для разработки кроссплатформенных приложений для различных целей. Конечно же, статья направлена на популяризацию Qt как API (Application Programming Interface — интерфейс прикладного программирования) для создания трёхмерной графики. Поэтому эта статья также окажется полезной для профессиональных программистов OpenGL, незнакомых с возможностями Qt 4, и программистов Qt, не работавших с OpenGL. От читателя потребуется знание языка C++. Изложение будет построено таким образом: вначале читателю предлагается только исходный код программы статьи. Затем последует объяснение базовых понятий и подробный разбор программы.

    An opensource of this lecture

    lecture1 | OpenGL на Qt 4. Это просто! (часть 1)

    scene3D.h

    #ifndef SCENE3D_H 
    #define SCENE3D_H
    
    #include <QGLWidget>
    
    class Scene3D : public QGLWidget
    { 
       private: 
          GLfloat xRot;
          GLfloat yRot; 
          GLfloat zRot;
          GLfloat zTra;
          GLfloat nSca;
          
          QPoint ptrMousePosition;
          
          void scale_plus();
          void scale_minus();
          void rotate_up();
          void rotate_down();
          void rotate_left();
          void rotate_right();
          void translate_down();
          void translate_up();     
          void defaultScene();  
          
          void drawAxis();
          
          void getVertexArray();
          void getColorArray();
          void getIndexArray();     
          void drawFigure();
            
       protected:
          void initializeGL();         
          void resizeGL(int nWidth, int nHeight);  
          void paintGL();                          
          void mousePressEvent(QMouseEvent* pe); 
          void mouseMoveEvent(QMouseEvent* pe);  
          void mouseReleaseEvent(QMouseEvent* pe); 
          void wheelEvent(QWheelEvent* pe);  
          void keyPressEvent(QKeyEvent* pe);       
          
       public: 
          Scene3D(QWidget* parent = 0);
    }; 
    #endif 

    scene3D.cpp

    #include <QtGui>
    #include <math.h>
    #include "scene3D.h"
    
    const static float pi=3.141593, k=pi/180;
    
    GLfloat VertexArray[12][3];
    GLfloat ColorArray[12][3];
    GLubyte IndexArray[20][3];
    
    Scene3D::Scene3D(QWidget* parent) : QGLWidget(parent) 
    { 
       xRot=-90; yRot=0; zRot=0; zTra=0; nSca=1;
    } 
    
    void Scene3D::initializeGL()
    {
       qglClearColor(Qt::white); 
       glEnable(GL_DEPTH_TEST);
       glShadeModel(GL_FLAT);
       glEnable(GL_CULL_FACE);  
       
       getVertexArray();
       getColorArray();
       getIndexArray();
       
       glEnableClientState(GL_VERTEX_ARRAY);
       glEnableClientState(GL_COLOR_ARRAY);
    }
    
    void Scene3D::resizeGL(int nWidth, int nHeight)
    { 
       glMatrixMode(GL_PROJECTION);
       glLoadIdentity();
     
       GLfloat ratio=(GLfloat)nHeight/(GLfloat)nWidth;
       
       if (nWidth>=nHeight)
          glOrtho(-1.0/ratio, 1.0/ratio, -1.0, 1.0, -10.0, 1.0); 
       else
          glOrtho(-1.0, 1.0, -1.0*ratio, 1.0*ratio, -10.0, 1.0);      
    
       glViewport(0, 0, (GLint)nWidth, (GLint)nHeight);
    }
    
    void Scene3D::paintGL()
    { 
       glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 
    
       glMatrixMode(GL_MODELVIEW); 
       glLoadIdentity();           
    
       glScalef(nSca, nSca, nSca);
       glTranslatef(0.0f, zTra, 0.0f);    
       glRotatef(xRot, 1.0f, 0.0f, 0.0f);     
       glRotatef(yRot, 0.0f, 1.0f, 0.0f);
       glRotatef(zRot, 0.0f, 0.0f, 1.0f);
     
       drawAxis();
       drawFigure();
    }  
    
    void Scene3D::mousePressEvent(QMouseEvent* pe)
    {
       ptrMousePosition = pe->pos();                     
    } 
    
    void Scene3D::mouseReleaseEvent(QMouseEvent* pe)
    { 
            
    } 
    
    void Scene3D::mouseMoveEvent(QMouseEvent* pe) 
    {   
       xRot += 180/nSca*(GLfloat)(pe->y()-ptrMousePosition.y())/height(); 
       zRot += 180/nSca*(GLfloat)(pe->x()-ptrMousePosition.x())/width(); 
       
       ptrMousePosition = pe->pos();
       
       updateGL();
    }
    
    void Scene3D::wheelEvent(QWheelEvent* pe) 
    { 
       if ((pe->delta())>0) scale_plus(); else if ((pe->delta())<0) scale_minus();   
        
       updateGL();       
    }
    
    void Scene3D::keyPressEvent(QKeyEvent* pe) 
    {  
       switch (pe->key())
       {         
          case Qt::Key_Plus:  
             scale_plus();
          break;
             
          case Qt::Key_Equal:  
             scale_plus(); 
          break;
             
          case Qt::Key_Minus: 
             scale_minus();
          break;
    
          case Qt::Key_Up:  
             rotate_up();
          break;
             
          case Qt::Key_Down:  
             rotate_down();
          break;         
             
          case Qt::Key_Left:  
            rotate_left();
          break;
             
          case Qt::Key_Right:  
             rotate_right();
          break;                           
             
          case Qt::Key_Z:
             translate_down();
          break;  
             
          case Qt::Key_X:
             translate_up();
          break; 
             
          case Qt::Key_Space:
             defaultScene();
          break;
          
          case Qt::Key_Escape:
             this->close();
          break;                                                           
       }
       
       updateGL();
    }
    
    void Scene3D::scale_plus()
    {
       nSca = nSca*1.1;
    }
    
    void Scene3D::scale_minus()
    {
       nSca = nSca/1.1;
    }
    
    void Scene3D::rotate_up()
    {
       xRot += 1.0;
    }
    
    void Scene3D::rotate_down()
    {
       xRot -= 1.0;
    }
    
    void Scene3D::rotate_left()
    {
       zRot += 1.0;
    }
    
    void Scene3D::rotate_right()
    {
       zRot -= 1.0;
    }
    
    void Scene3D::translate_down()
    {
       zTra -= 0.05;
    }
    
    void Scene3D::translate_up()
    {
       zTra += 0.05;
    }
    
    void Scene3D::defaultScene()
    {
       xRot=-90; yRot=0; zRot=0; zTra=0; nSca=1;
    }
    
    void Scene3D::drawAxis()
    {
       glLineWidth(3.0f); 
       
       glColor4f(1.00f, 0.00f, 0.00f, 1.0f); 
       glBegin(GL_LINES);
          glVertex3f( 1.0f,  0.0f,  0.0f);
          glVertex3f(-1.0f,  0.0f,  0.0f);
       glEnd();  
       
       QColor halfGreen(0, 128, 0, 255);
       qglColor(halfGreen);
       glBegin(GL_LINES);
          glVertex3f( 0.0f,  1.0f,  0.0f);
          glVertex3f( 0.0f, -1.0f,  0.0f);
      
          glColor4f(0.00f, 0.00f, 1.00f, 1.0f);
          glVertex3f( 0.0f,  0.0f,  1.0f);
          glVertex3f( 0.0f,  0.0f, -1.0f);
       glEnd();
    }
    
    void Scene3D::getVertexArray()
    {
       GLfloat R=0.75;
       
       GLfloat a=4*R/sqrt(10+2*sqrt(5));
       GLfloat alpha=acos((1-a*a/2/R/R));
    
       VertexArray[0][0]=0;
       VertexArray[0][1]=0;
       VertexArray[0][2]=R; 
       
       VertexArray[1][0]=R*sin(alpha)*sin(0);
       VertexArray[1][1]=R*sin(alpha)*cos(0); 
       VertexArray[1][2]=R*cos(alpha);
       
       VertexArray[2][0]=R*sin(alpha)*sin(72*k);
       VertexArray[2][1]=R*sin(alpha)*cos(72*k);
       VertexArray[2][2]=R*cos(alpha);
       
       VertexArray[3][0]=R*sin(alpha)*sin(2*72*k);
       VertexArray[3][1]=R*sin(alpha)*cos(2*72*k);
       VertexArray[3][2]=R*cos(alpha); 
       
       VertexArray[4][0]=R*sin(alpha)*sin(3*72*k);
       VertexArray[4][1]=R*sin(alpha)*cos(3*72*k);
       VertexArray[4][2]=R*cos(alpha);  
       
       VertexArray[5][0]=R*sin(alpha)*sin(4*72*k);
       VertexArray[5][1]=R*sin(alpha)*cos(4*72*k);
       VertexArray[5][2]=R*cos(alpha);
       
       VertexArray[6][0]=R*sin(pi-alpha)*sin(-36*k);
       VertexArray[6][1]=R*sin(pi-alpha)*cos(-36*k);
       VertexArray[6][2]=R*cos(pi-alpha);
       
       VertexArray[7][0]=R*sin(pi-alpha)*sin(36*k);
       VertexArray[7][1]=R*sin(pi-alpha)*cos(36*k);
       VertexArray[7][2]=R*cos(pi-alpha);
       
       VertexArray[8][0]=R*sin(pi-alpha)*sin((36+72)*k);
       VertexArray[8][1]=R*sin(pi-alpha)*cos((36+72)*k);
       VertexArray[8][2]=R*cos(pi-alpha);  
       
       VertexArray[9][0]=R*sin(pi-alpha)*sin((36+2*72)*k);
       VertexArray[9][1]=R*sin(pi-alpha)*cos((36+2*72)*k);
       VertexArray[9][2]=R*cos(pi-alpha);
       
       VertexArray[10][0]=R*sin(pi-alpha)*sin((36+3*72)*k);
       VertexArray[10][1]=R*sin(pi-alpha)*cos((36+3*72)*k);
       VertexArray[10][2]=R*cos(pi-alpha); 
       
       VertexArray[11][0]=0;
       VertexArray[11][1]=0;
       VertexArray[11][2]=-R;    
    }
    
    void Scene3D::getColorArray()
    {
       for (int i=0; i<12; i++)
       {      
          ColorArray[i][0]=0.1f*(qrand()%11);
          ColorArray[i][1]=0.1f*(qrand()%11);
          ColorArray[i][2]=0.1f*(qrand()%11);
       }
    }
    
    void Scene3D::getIndexArray()
    {
       IndexArray[0][0]=0;
       IndexArray[0][1]=2;
       IndexArray[0][2]=1;
       
       IndexArray[1][0]=0;
       IndexArray[1][1]=3;
       IndexArray[1][2]=2;
       
       IndexArray[2][0]=0;
       IndexArray[2][1]=4;
       IndexArray[2][2]=3;
       
       IndexArray[3][0]=0;
       IndexArray[3][1]=5;
       IndexArray[3][2]=4;
        
       IndexArray[4][0]=0;
       IndexArray[4][1]=1;
       IndexArray[4][2]=5;
       
       IndexArray[5][0]=6;
       IndexArray[5][1]=1;
       IndexArray[5][2]=7;
       
       IndexArray[6][0]=7;
       IndexArray[6][1]=1;
       IndexArray[6][2]=2;
       
       IndexArray[7][0]=7;
       IndexArray[7][1]=2;
       IndexArray[7][2]=8;
       
       IndexArray[8][0]=8;
       IndexArray[8][1]=2;
       IndexArray[8][2]=3;
       
       IndexArray[9][0]=8;
       IndexArray[9][1]=3;
       IndexArray[9][2]=9;
       
       IndexArray[10][0]=9;
       IndexArray[10][1]=3;
       IndexArray[10][2]=4;
       
       IndexArray[11][0]=9;
       IndexArray[11][1]=4;
       IndexArray[11][2]=10;
       
       IndexArray[12][0]=10;
       IndexArray[12][1]=4;
       IndexArray[12][2]=5;
       
       IndexArray[13][0]=10;
       IndexArray[13][1]=5;
       IndexArray[13][2]=6;
       
       IndexArray[14][0]=6;
       IndexArray[14][1]=5;
       IndexArray[14][2]=1;
       
       IndexArray[15][0]=7;
       IndexArray[15][1]=11;
       IndexArray[15][2]=6;
       
       IndexArray[16][0]=8;
       IndexArray[16][1]=11;
       IndexArray[16][2]=7;
       
       IndexArray[17][0]=9;
       IndexArray[17][1]=11;
       IndexArray[17][2]=8;
       
       IndexArray[18][0]=10;
       IndexArray[18][1]=11;
       IndexArray[18][2]=9;
       
       IndexArray[19][0]=6;
       IndexArray[19][1]=11;
       IndexArray[19][2]=10; 
    }
    
    void Scene3D::drawFigure()
    {
       glVertexPointer(3, GL_FLOAT, 0, VertexArray); 
       glColorPointer(3, GL_FLOAT, 0, ColorArray);  
       glDrawElements(GL_TRIANGLES, 60, GL_UNSIGNED_BYTE, IndexArray);
    }

    main.cpp

    #include <QApplication> 
    #include "scene3D.h" 
    
    int main(int argc, char** argv) 
    { 
       QApplication app(argc, argv);
    
       Scene3D scene1;
       scene1.setWindowTitle("lecture1"); 
       scene1.resize(500, 500);
       scene1.show();
     
       return app.exec();
    } 

    lecture1.pro

    TEMPLATE = app
    
    # Input
    HEADERS += scene3D.h
    SOURCES += main.cpp scene3D.cpp
    QT += opengl
    Страницы: 1 2 3 4 Следующая »

    19 января 2011

    #3D, #графика, #OpenGL, #Qt, #Qt4


    Обновление: 2 января 2013

    2001—2018 © GameDev.ru — Разработка игр