- •Часть II. Основы программирования
- •Введение
- •Лекция 1. Библиотека OpenGl
- •1. Назначение библиотеки OpenGl
- •2. Основные возможности OpenGl
- •3. Макет консольного приложения, использующего библиотеку glaux
- •Программа 1.1
- •4. Имена функций OpenGl
- •5. Системы координат
- •5.1 Матрицы преобразований
- •5.2 Видовые и модельные преобразования
- •5.3 Проекционное преобразование
- •5.4 Оконное преобразование
- •6. Пример выполнения модельных преобразований
- •6.1 Параллельный перенос
- •Фрагмент программы 1.2
- •6.2 Поворот
- •Фрагмент программы 1.3
- •7. Сводка результатов
- •8. Упражнения Упражнение 1
- •Упражнение 2
- •Упражнение 3
- •Упражнение 4
- •Упражнение 5
- •Упражнение 6
- •Лекция 2. Генерация движущихся изображений
- •1. Анимация с двойной буферизацией
- •2. Обработка событий клавиатуры и мыши
- •2.1 Пример обработки события от мыши: изменение цвета вращающегося объекта по нажатию левой кнопки мыши
- •3. Композиция нескольких преобразований
- •3.1 Модель солнечной системы
- •3.2 Модель манипулятора робота
- •4. Сводка результатов
- •5. Упражнения Упражнение 1
- •Упражнение 2
- •Упражнение 3
- •Упражнение 4
- •Упражнение 5
- •Лекция 3. Геометрические примитивы
- •1. Служебные графические операции
- •1.1 Очистка окна
- •1.2 Задание цвета
- •1.3 Удаление невидимых поверхностей
- •2. Описание точек, отрезков и многоугольников
- •2.1 Точки
- •2.2 Отрезки
- •2.3 Многоугольники
- •2.4 Прямоугольники
- •2.5 Кривые
- •2.6 Задание вершин
- •2.7 Геометрические примитивы OpenGl
- •3. Свойства точек, отрезков и многоугольников
- •3.1 Точки
- •3.2 Отрезки
- •3.3 Многоугольники
- •4. Сводка результатов
- •Лекция 4. Полигональная аппроксимация поверхностей
- •1. Векторы нормали
- •2. Некоторые рекомендации по построению полигональных аппроксимаций поверхностей
- •3. Пример: построение икосаэдра
- •3.1 Вычисление нормалей к граням икосаэдра
- •3.2 Повышение точности аппроксимации сферической поверхности
- •3.3 Алгоритм разбиения треугольной грани произвольной поверхности
- •4. Плоскости отсечения
- •6. Сводка результатов
- •7. Упражнения Упражнение 1
- •Упражнение 2
- •Упражнение 3
- •Упражнение 4
- •Лекция 5. Цвет и освещение
- •1. Цветовая модель rgb
- •2. Задание способа закраски
- •3. Освещение
- •4. Освещение в реальном мире и в OpenGl
- •4.1 Излучаемый, рассеянный, диффузно отраженный и зеркально отраженный свет
- •4.2 Цвет материала
- •4.3 Значения rgb для источников света и материалов
- •5. Пример: рисование освещенной сферы
- •5.1 Вектора нормали в вершинах объектов
- •5.2 Создание, расположение и включение источников света
- •5.3 Выбор модели освещения
- •5.4 Задание свойств материалов для объектов сцены
- •6. Создание источников света
- •6.1 Цвет
- •6.2 Местоположение и затухание
- •6.3 Прожекторы
- •6.4 Использование нескольких источников света
- •6.5 Изменение местоположения источников света
- •4. Сводка результатов
- •Лекция 6. Свойства материала и спецэффекты освещения
- •1. Задание свойств материала
- •1.1 Диффузное и рассеянное отражение
- •1.2 Зеркальное отражение
- •1.3 Излучаемый свет
- •1.4 Изменение свойств материала
- •1.5 Имитация реальных материалов
- •2. Смешение цветов и прозрачность
- •2.1 Множители source (исходный пиксел) и destination (результирующего пиксела)
- •2.2 Области применения смешения цветов
- •2.3 Пример использования смешения цветов
- •3. Туман
- •3.1 Использование тумана
- •4. Сводка результатов
- •5. Упражнения Упражнение 1
- •2. Назначение текстур
- •3. Создание текстуры в оперативной памяти
- •4. Автоматическое повторение текстуры на плоском многоугольнике
- •5. Наложение текстуры на произвольную поверхность
- •6. Сводка результатов
- •7. Упражнения Упражнение 1
- •Упражнение 2
- •Задание 1.1
- •2. Объемный "тетрис"
- •Задание 2.1
2.1 Пример обработки события от мыши: изменение цвета вращающегося объекта по нажатию левой кнопки мыши
Перечислим изменения, которые необходимо внести в программу 2.1, чтобы по нажатию левой кнопки мыши цвет вращающегося чайника циклически изменялся в следующей последовательности: желтый, красный, зеленый, синий.
Надо добавить в программу описание глобальной переменной, в который будет храниться порядковый номер текущего цвета (0/1/2/3 – желтый/красный/зеленый/синий):
int clr_number = 0;
Значение переменной clr_number надо учесть в функции рисования трехмерной сцены, чтобы перед рисованием чайника устанавливался соответствующий цвет:
switch ( clr_number )
{
case 0 : glColor3f( 0.5, 0.5, 0 ); break;
case 1 : glColor3f( 1, 0, 0 ); break;
case 2 : glColor3f( 0, 1, 0 ); break;
case 3 : glColor3f( 0, 0, 1 ); break;
default : glColor3f( 1, 1, 1 ); break;
}
В раздел прототипов надо внести прототип обработчика события от мыши:
void CALLBACK mouse_leftbtn( AUX_EVENTREC* event );
В функции-обработчике выполняется изменение номера текущего цвета:
void CALLBACK mouse_leftbtn( AUX_EVENTREC* event )
{
if ( ++clr_number == 3 )
clr_number = 0;
}
Перед входом в главный цикл GLAUX надо зарегистрировать обработчик события "нажатие левой кнопки мыши":
auxMouseFunc( AUX_LEFTBUTTON, AUX_MOUSEDOWN, mouse_leftbtn );
3. Композиция нескольких преобразований
Для генерации анимационных изображений объектов, движущихся относительно друг друга, часто бывает удобно применять последовательность нескольких преобразований, параметры которых определяются текущим положением объектов. В данном параграфе показывается применение композиции нескольких преобразований для двух моделей: для простейшей модели солнечной системы (несколько объектов вращаются вокруг собственных осей и по орбитам вокруг солнца) и для модели манипулятора робота (при отображении манипулятора требуется выполнять преобразование координатных систем отдельных сегментов).
3.1 Модель солнечной системы
Рассмотрим простейшую модель солнечной системы, которая состоит из солнца и одной планеты, движущейся по круговой орбите. Планета совершает полный оборот по орбите за 365 дней, а оборот вокруг своей оси за 24 часа.
Оба тела рисуются в виде каркасных сфер, для отображения сцены применяется перспективная проекция (функция gluPerspective()).
Угловое движение планеты по орбите и вокруг собственной оси учитывается с помощью функции glRotated(). Для размещения планеты на орбите применяется функция glTranslated().
Центр сферы, изображающей солнце, находится в начале координат. Вращение солнца вокруг собственной оси не показывается (хотя это легко сделать с помощью функции glRotated()). Для рисования планеты, обращающейся вокруг солнца (рис. 2.1), требуется выполнить несколько модельных преобразований.
Рис. 2.1. Движение планеты по орбите и вокруг своей оси.
Для определения порядка модельных преобразований надо представить, что должно происходить с модельной системой координат. Сначала модельная система координат совпадает с мировой. В этом состоянии надо функцией glRotated() повернуть модельную систему координат относительно мировой системы на угол, соответствующий текущему положению планеты на орбите. Затем glTranslated() выполняет перенос модельной системы координат по радиусу орбиты. После этого выполняется еще один вызов glRotated(), поворачивающий модельную систему координат вокруг оси вращения планеты в соответствии с временем суток на планете. После выполнения всех трех преобразований, можно нарисовать планету.
Описанные преобразования выполняются в программе 2.2. Фоновой функции в этой программе нет, поэтому изменение времени производится клавишами курсора: увеличение/уменьшение времени суток с помощью стрелок вверх/вниз (на 1 час), дней – с помощью стрелок вправо/влево (на 1 день).
#include <windows.h>
#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glaux.h>
void CALLBACK resize( int width, int height );
void CALLBACK display();
void CALLBACK dayAdd();
void CALLBACK daySubtract();
void CALLBACK hourAdd();
void CALLBACK hourSubtract();
// Счетчики дней и часов
int day_cnt = 0, hour_cnt = 0;
void main()
{
// Создание экранного окна
auxInitDisplayMode( AUX_RGBA | AUX_DEPTH | AUX_DOUBLE );
auxInitPosition( 50, 10, 400, 400);
auxInitWindow( "Лекция 2, Программа 2.2" );
// Включение ряда параметров OpenGL
glEnable( GL_ALPHA_TEST ); // Учет прозрачности
glEnable( GL_DEPTH_TEST ); // Удаление невидимых поверхностей
glEnable( GL_COLOR_MATERIAL );
glEnable( GL_BLEND ); // Разрешение смешения цветов
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
glEnable( GL_LIGHTING ); // Учет освещения
glEnable( GL_LIGHT0 ); // Включение нулевого источника света
// Задание положения и направления нулевого источника света
float pos[4] = { 5, 5, 5, 1 };
float dir[3] = { -1, -1, -1 };
glLightfv( GL_LIGHT0, GL_POSITION, pos );
glLightfv( GL_LIGHT0, GL_SPOT_DIRECTION, dir );
// Регистрация обработчиков событий
auxReshapeFunc( resize );
auxKeyFunc( AUX_LEFT, daySubtract );
auxKeyFunc( AUX_RIGHT, dayAdd );
auxKeyFunc( AUX_UP, hourAdd );
auxKeyFunc( AUX_DOWN, hourSubtract );
// Вход в главный цикл GLAUX
auxMainLoop( display );
}
void CALLBACK resize( int width, int height )
{
glViewport( 0, 0, width, height );
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
gluPerspective( 60.0, (float)width/(float)height, 1.0, 20.0 );
gluLookAt( 0,0,5, 0,0,0, 0,1,0 );
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
}
void CALLBACK display(void)
{
// Очистка буфера кадра
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glColor3f( 1.0, 1.0, 1.0 );
glPushMatrix();
auxWireSphere( 1.0 ); // Солнце
glRotated( (double)day_cnt*360.0/365.0, 0.0, 1.0, 0.0 );
glTranslated( 2.0, 0.0, 0.0 );
glRotated( (double)hour_cnt*360.0/24.0, 0.0, 1.0, 0.0 );
auxWireSphere( 0.2 ); // Планета
glPopMatrix();
// Копирование содержимого буфера кадра на экран
glFlush();
auxSwapBuffers();
}
void CALLBACK dayAdd()
{
day_cnt = (day_cnt + 1) % 360;
}
void CALLBACK daySubtract()
{
day_cnt = (day_cnt - 1) % 360;
}
void CALLBACK hourAdd()
{
hour_cnt = (hour_cnt + 1) % 24;
}
void CALLBACK hourSubtract()
{
hour_cnt = (hour_cnt - 1) % 24;
}
Программа 2.2. Модель солнечной системы.
