Шаг 247.
Библиотека Qt.
Трехмерная графика

    На этом шаге рассмотрим пример трехметной графики в Qt.

    На рис. 1 показан результат работы программы, отображающей пирамиду в трехмерном пространстве, поворот которой относительно осей X и Y осуществляется при помощи мыши.


Рис.1. Пирамида

    Рассмотрим класс OGLPyramid:

class OGLPyramid : public QGLWidget {
private:
    GLuint  m_nPyramid;//переменная хранит номер дисплейного списка объекта пирамиды
    /*Дисплейные списки позволяют выделить конкретный набор команд,
      запомнить его и вызывать всякий раз, когда в нем возникает необходимость.
      Этот механизм очень похож на вызов обычных функций или на механизм записи
      графических команд, предоставляемый классом QPicture. Для запуска команд
      дисплейного списка необходимо знать присвоенный ему уникальный номер*/
    GLfloat m_xRotate;//нужны для хранения углов поворота по осям X
    GLfloat m_yRotate;//и Y
    QPoint  m_ptPosition;//хранит координату указателя мыши в момент нажатия

protected:
    virtual void   initializeGL   (                       );
    virtual void   resizeGL       (int nWidth, int nHeight);
    virtual void   paintGL        (                       );
    /*переопределяются методы обработки события мыши для
      осуществления поворота пирамиды*/
    virtual void   mousePressEvent(QMouseEvent* pe        );
    virtual void   mouseMoveEvent (QMouseEvent* pe        );
    //создает дисплейный список для отображения объекта пирамиды 
            GLuint createPyramid  (GLfloat fSize = 1.0f   );
public:
    OGLPyramid(QWidget* pwgt = 0);
};

    Рассмотрим реализацию указанных методов:

/*конструктор класса инициализирует переменные-члены для поворота и
передает указатель на виджет предка конструктору наследуемого класса QGLWidget*/
OGLPyramid::OGLPyramid(QWidget* pwgt/*= 0*/) : QGLWidget(pwgt)
                                             , m_xRotate(0)
                                             , m_yRotate(0)
{
}

/*virtual*/void OGLPyramid::initializeGL()
{
    qglClearColor(Qt::white);//устанавливается белый цвет очистки буфера изображения
    glEnable(GL_DEPTH_TEST);/*устанавливает режим разрешения проверки
                              глубины фрагментов*/
    glShadeModel(GL_FLAT);/*режим сглаживания цветов по умолчанию разрешен,
                            поэтому его необходимо отключить, передав в функцию
                            флаг GL_FLAT, иначе боковые грани пирамиды будут
                            иметь радужную окраску*/
    m_nPyramid = createPyramid(1.2f);/*создает дисплейный список для пирамиды и
                                       возвращает его номер, который присваивается
                                       переменной m_nPyramid. Параметр, передаваемый
                                       в этот метод, задает размеры самой пирамиды*/
}

/*virtual*/void OGLPyramid::resizeGL(int nWidth, int nHeight)
{
    glViewport(0, 0, (GLint)nWidth, (GLint)nHeight);/*устанавливает размеры видового
                                                окна равными размерам окна виджета*/
    glMatrixMode(GL_PROJECTION);//делает текущей матрицу проектирования
    glLoadIdentity();//присваивает матрице проектирования единичную матрицу
    glFrustum(-1.0, 1.0, -1.0, 1.0, 1.0, 10.0);/*задает так называемую пирамиду
                                    видимости. Параметры задают положения левой,
                                    правой, верхней, нижней, передней и задней
                                    отсекающих плоскостей. Последние два значения
                                    должны быть положительными и отсчитываться от
                                    центра проецирования вдоль оси Z; по ним
                                    устанавливается значение перспективы*/
}

/*virtual*/void OGLPyramid::paintGL()
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);//очистка буфера изображения
    glMatrixMode(GL_MODELVIEW);/*текущей устанавливается матрица моделирования,
                            служащая для задания положения объекта и его ориентации*/
    glLoadIdentity();//присваивает матрице моделирования единичную матрицу
    glTranslatef(0.0, 0.0, -3.0);/*сдвигает начало системы координат по оси Z
                                   на 3 единицы*/

    glRotatef(m_xRotate, 1.0, 0.0, 0.0);//поворачивает систему координат вокруг 
    glRotatef(m_yRotate, 0.0, 1.0, 0.0);//осей X и Y на угол, задаваемый
                                        //переменными m_xRotate и m_yRotate

    glCallList(m_nPyramid);/*передача в функцию номера дисплейного списка пирамиды
                             отобразит ее*/
}

/*virtual*/void OGLPyramid::mousePressEvent(QMouseEvent* pe)
{
    m_ptPosition = pe->pos();/*при нажатии пользователем кнопки мыши переменной
                               присваиваются координаты указателя мыши*/
}

/*virtual*/void OGLPyramid::mouseMoveEvent(QMouseEvent* pe)
{
    /*в методе обработки события перемещения мыши вычисляются
      углы поворота для осей X и Y*/
    m_xRotate += 180 * (GLfloat)(pe->y() - m_ptPosition.y()) / height();
    m_yRotate += 180 * (GLfloat)(pe->x() - m_ptPosition.x()) / width();
    updateGL();//обновляет изображение на экране, используя новые углы поворота
    m_ptPosition = pe->pos();//присваивается актуальная координата указателя мыши
}
/*Метод createPyramid() создает дисплейный список для отображения пирамиды
  и возвращает его номер*/
GLuint OGLPyramid::createPyramid(GLfloat fSize/*=1.0f*/)
{
    GLuint n = glGenLists(1);/*возвращает первый свободный номер для
                               идентификации дисплейного списка*/

    glNewList(n, GL_COMPILE);/*номер передается в функцию glNewList().
                               Второй параметр, GL_COMPILE, говорит о том,
                               что команды нужно лишь запомнить*/

        glBegin(GL_TRIANGLE_FAN);              //команды, находящиеся между
            qglColor(Qt::green);               //функциями glNewList() и glEndList(),
            glVertex3f(0.0, fSize, 0.0);       //помещаются в соответствующий 
            glVertex3f(-fSize, -fSize, fSize); //дисплейный список. Тип 
            glVertex3f(fSize, -fSize, fSize);  //GL_TRIANGLE_FAN задает треугольники
            qglColor(Qt::yellow);              //с общей вершиной, которая идет 
            glVertex3f(fSize, -fSize, -fSize); //первой в списке. Следующие две
            qglColor(Qt::red);                 //вершины задают треугольник. 
            glVertex3f(-fSize, -fSize, -fSize);//Затем каждая последующая вершина, 
            qglColor(Qt::magenta);             //совместно с предыдущей, задает 
            glVertex3f(-fSize, -fSize, fSize); //следующий треугольник
        glEnd();

        glBegin(GL_QUADS);/*для типа фигуры GL_QUADS каждые четыре вершины
                            задают четырехугольник*/
            qglColor(Qt::blue);
            glVertex3f(-fSize, -fSize, fSize);
            glVertex3f(fSize, -fSize, fSize);
            glVertex3f(fSize, -fSize, -fSize);
            glVertex3f(-fSize, -fSize, -fSize);
        glEnd();
    glEndList();
    return n;
} 

    Файлы приложения можно взять здесь.

    На следующем шаге рассмотрим класс QPrinter.




Предыдущий шаг Содержание Следующий шаг