Опубликован: 13.07.2010 | Доступ: свободный | Студентов: 889 / 20 | Оценка: 4.40 / 4.20 | Длительность: 77:34:00
Самостоятельная работа 19:

Простая программа на OpenGL

Пояснения кода GLRect

При программировании с использованием библиотеки OpenGL часто более удобно пользоваться псевдонимами встроенных типов языка C. Эти типы определены в заголовочном файле GL.h

typedef unsigned int GLenum;
typedef unsigned char GLboolean;
typedef unsigned int GLbitfield;
typedef signed char GLbyte;
typedef short GLshort;
typedef int GLint;
typedef int GLsizei;
typedef unsigned char GLubyte;
typedef unsigned short GLushort;
typedef unsigned int GLuint;
typedef float GLfloat;
typedef float GLclampf;
typedef double GLdouble;
typedef double GLclampd;
typedef void GLvoid;
Листинг 19.17. Псевдонимы типов

Вызов

glutInitWindowSize(800, 600);

устанавливает начальные размеры графического окна.

Функции RenderScene() и ChangeSize() являются функциями обратного вызова. Остановимся на функции ChangeSize(), которая срабатывает каждый раз при изменении размеров окна.

Масштабирование рисунка под размеры окна

Практически во всех средах с управлением окнами пользователь может изменить размеры окна. Даже если приложение запускается сразу в полноэкранном режиме, все равно считается, что окно меняет размер один раз при создании и настройке под конкретное разрешение экрана. Иногда нужно просто разместить иллюстрацию по клиентской области окна с соблюдением пропорций рисунка или без них.

Функция обратного вызова

void ChangeSize(int width, int height)

вызывается всякий раз при изменении размеров окна и принимает новые параметры ширины и высоты клиентской области окна.

Код

// Предотвращаем деление на нуль
  if(height == 0)
    height = 1;

предотвращает возникновение системного прерывания на случай, если пользователь уменьшит высоту окна до нуля. Попробуйте запустить приложение и попытайтесь уменьшить ширину окна до нуля. Это не удасться, поскольку система оставляет видимыми компоненты заголовка окна. Но уменьшить высоту клиентской области окна до нуля выполнить нетрудно. Вот от этого и защищаемся.

Внутри клиентской области функция

void glViewport(GLint x, GLint y, GLsizei width, GLsizei height)

устанавливает поле просмотра для OpenGL. Поле просмотра - это та часть клиентской области, куда отображается графическая информация, генерируемая функциями OpenGL. Параметры x, y задают левый нижний угол поля просмотра внутри окна, а параметры ширины и высоты определяют эти размеры в пикселах. Обычно x, y равны нулю, но поля просмотра можно использовать для размещения нескольких рисунков в разных частях окна.Поле просмотра определяет область внутри окна в реальных экранных координатах. Если задать поле просмотра меньше окна, визуализация будет соответствующим образом масштабирована.


В нашем обращении

// Устанавливаем поле просмотра с размерами окна
    glViewport(0, 0, width, height);

поле просмотра размещается в пределах всей клиентской области, поскольку в функцию обратного вызова

void ChangeSize(int width, int height)

передаются текущие значения ширины и высоты именно клиентской области.

Описание трехмерного объекта представляется в трехмерной системе координат объекта. Наиболее простая - ортогональная система координат. В OpenGL базовой принята правая система координат (большой палец правой руки направлен по X, указательный по Y, средний по Z ).

Кодом

// Рисуем прямоугольник, заполненный текущим цветом
  glRectf(-50.0f, 50.0f, 50.0f, -50.0f);

мы нарисовали прямоугольник (заданным ранее красным цветом), который расположен симметрично относительно начала системы координат объекта с координатой глубины z = 0.

Синтаксис функции glRect() - нарисовать плоский прямоугольник
Цель: Нарисовать плоский прямоугольник
Варианты:
  • void glRectd(GLdouble x1, GLdouble y1, GLdouble x2, GLdouble y2) ;
  • void glRectf(GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2) ;
  • .............................................
Описание: Приведенная функция предлагает простой метод задания прямоугольника через координаты противоположных вершин. Прямоугольник задается в плоскости x0y при z = 0 системы координат объекта.
Параметры:
  • x1, y1 - задает левый верхний угол прямоугольника
  • x2, y2 - задает правый нижний угол прямоугольника


Если не устанавливать отсекающий объем ( перспективу ) при ортогональном проецировании, то в поле просмотра будут помещены (предварительно преобразованные в растр) все точки прямоугольника. При этом размеры прямоугольника, установленные функцией glRectf() не будут иметь никакого значения - прямоугольник растянется по всему полю просмотра.

Чтобы проецировать прямоугольник в требуемом аспекте, необходимо вокруг него создать отсекающий объем в виде параллелепипеда, который и будет целиком отображаться в поле просмотра вместе с размещенным в нем прямоугольником.


Отображение в поле просмотра экранного окна будет таким, каким спроецируется прямоугольник на переднюю стенку параллелепипеда расположенным сзади параллельным (бесконечно удаленным) источником света, или каким он будет в рамках отсекающего объема на плоскости, совпадающей с осями x0y.

Поле просмотра мы задали на всю площадь клиентской области графического окна приложения. Поэтому, если не принимать мер по коррекции отсекающего объема (перспективы), то каково бы ни было соотношение сторон его передней плоскости, все равно она примет размеры клиентской области. Это значит, что заданный нами квадрат будет отображаться квадратом только при квадратных размерах клиентской области окна. С этой целью введен код

aspectRatio = (GLfloat)width / (GLfloat)height;
    if (width <= height)
    glOrtho (-100.0, 100.0, -100 / aspectRatio,
        100.0 / aspectRatio, 
        1.0, -1.0);
    else 
    glOrtho (-100.0 * aspectRatio, 
        100.0 * aspectRatio, 
        -100.0, 100.0, 
        1.0, -1.0);

который при каждом изменении размеров окна корректирует координаты отсекающего параллелепипеда так, чтобы сохранялось соотношение сторон ширины и высоты, обратное соотношению размеров клиентской области графического окна приложения. Характеристическое число aspectRatio определяет соотношение сторон и используется как раз для этих целей.

Приведенный код определения отсекающего объема (перспективы) окаймляется следующими вызовами

// Устанавливает матрицу преобразования в режим проецирования
  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
  
  .......................................................
      
  // Восстановливает матрицу преобразования в исходный режим вида
  glMatrixMode(GL_MODELVIEW);
  glLoadIdentity();

В системах компьютерной графики, использующих конвейерный принцип обработки, желательно, чтобы все операции формирования изображения выполнялись единообразно - в форме перемножения матриц. Ряд матриц преобразования являются переменными состояния OpenGL и сохраняют свои последние значения до тех пор, пока их принудительно не изменят. Существует много матриц преобразования, в том числе матрица проецирования и матрица вида. Доступ к каждой из этих матриц осуществляется функций glMatrixMode() с соответствующим параметром. Функция glLoadIdentity() применяет соответствующую матрицу к системе координат.

Хорошим тоном считается восстанавливать систему OpenGL в исходное состояние для использования в других областях программы, поэтому применяются два последних вызова приведенного фрагмента кода.