Геометрические примитивы в OpenGL
Другие примитивы
Треугольники в OpenGl используются чаще всего, поскольку могут аппроксимировать фигуру любой сложности. Но в OpenGL имеются также прямоугольники и универсальные многоугольники (полигоны). Для рисования прямоугольных четырехугольников применяется команда
glBegin(GL_QUADS); ..................... glEnd();
Для аппроксимации сложных поверхностей прямоугольниками они строятся в ленты (как и треугольники) с помощью команды
glBegin(GL_QUAD_STRIP); ..................... glEnd();
Полигоны задаются с помощью команды
glBegin(GL_POLYGON); ..................... glEnd();
При задании вершин одного прямоугольника или полигона важно следить за тем, чтобы все вершины лежали в одной плоскости. Хотя это условие можно обойти, применяя опцию GL_TRIANGLE_FAN вместо GL_POLYGON.
Упражнение 7. Фактура многоугольников (PolygonStipple)
Существует два способа (помимо структурированной или градиентной заливки) наложить на поверхность многоугольника какой-либо рисунок:
- наложение текстуры - когда изображение отображается на поверхность многоугольника
- задание фактурного узора с помощью наложения маски - как это мы делали для линий
Здесь мы рассмотрим второй способ, а про текстуры будем говорить позднее.
Фактурный узор многоугольника - это не более чем монохромное растровое изображение-маска размером 32x32 пиксела, используемое как узор-заполнитель. Включение режима заполнения многоугольника фактурой выполняется следующей последовательностью команд
glEnable(GL_POLYGON_STIPPLE); glPolygonStipple(pBitmap);
pBitmap - это указатель на узор-заполнитель типа ( GLubyte * - unsigned byte). Этот узор является маской подобно используемой нами при наложении фактуры на линию. Маску для многоугольников можно сравнить с полем крассворда, которые печатают в газетах. Буфер для размещения маски должен имет размер 4*32=128 байт.
Рассмотрим маску костра, которую будем реализовывать в нашем упражнении рисования многоугольников с фактурой. Построчный порядок задания значения шаблона обратно противоположный его использованию
- Через панель Solution Explorer добавьте к проекту новый header -файл (заголовочный файл) с именем PolygonStipple.h
- Заполните этот файл следующим кодом
// Описание битовой маски костра 32x32 снизу вверх GLubyte fire[128] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x01, 0xf0, 0x00, 0x00, 0x07, 0xf0, 0x0f, 0x00, 0x1f, 0xe0, 0x1f, 0x80, 0x1f, 0xc0, 0x0f, 0xc0, 0x3f, 0x80, 0x07, 0xe0, 0x7e, 0x00, 0x03, 0xf0, 0xff, 0x80, 0x03, 0xf5, 0xff, 0xe0, 0x07, 0xfd, 0xff, 0xf8, 0x1f, 0xfc, 0xff, 0xe8, 0xff, 0xe3, 0xbf, 0x70, 0xde, 0x80, 0xb7, 0x00, 0x71, 0x10, 0x4a, 0x80, 0x03, 0x10, 0x4e, 0x40, 0x02, 0x88, 0x8c, 0x20, 0x05, 0x05, 0x04, 0x40, 0x02, 0x82, 0x14, 0x40, 0x02, 0x40, 0x10, 0x80, 0x02, 0x64, 0x1a, 0x80, 0x00, 0x92, 0x29, 0x00, 0x00, 0xb0, 0x48, 0x00, 0x00, 0xc8, 0x90, 0x00, 0x00, 0x85, 0x10, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00 }; // Рисуем полигон в форме дорожного знака // с заливкой по битовой маске void PolygonStipple() { // Очистить окно рисования glClear(GL_COLOR_BUFFER_BIT); // Запомнить первоначальное состояние матрицы вращения glPushMatrix(); // Настроить два последовательных поворота // для будущей визуализации сцены glRotatef(xRot, 1.0f, 0.0f, 0.0f);// Первое состояние матрицы вращения glRotatef(yRot, 0.0f, 1.0f, 0.0f);// Следующее состояние // Включить красный цвет рисования glColor3f(1.0f, 0.0f, 0.0f); // Включить фактуру при заполнении полигонов glEnable(GL_POLYGON_STIPPLE); // Адресовать битовую маску костра для фактуры glPolygonStipple(fire); // Нарисовать полигон в форме дорожного знака // "Движение без остановки запрещено", // закрашенного по маске костра красным цветом glBegin(GL_POLYGON); glVertex2f(-20.0f, 50.0f); glVertex2f(20.0f, 50.0f); glVertex2f(50.0f, 20.0f); glVertex2f(50.0f, -20.0f); glVertex2f(20.0f, -50.0f); glVertex2f(-20.0f, -50.0f); glVertex2f(-50.0f, -20.0f); glVertex2f(-50.0f, 20.0f); glEnd(); glColor3f(0.0f, 1.0f, 0.0f); // Восстановить цвет рисования зеленый // Выключить фактуру при заполнении полигонов glDisable(GL_POLYGON_STIPPLE); // Восстановить матрицу вращения в исходное состояние glPopMatrix(); }Листинг 21.63. Код файла PolygonStipple.h
#include "stdafx.h" // Искать в текущем каталоге проекта // Прототипы функций void RenderScene(void); void SetupRC(void); void ExecuteMenu(int); void ChangeSize(int, int); void Points(); // Пустой аргумент необязателен void SpecialKeys(int key, int x, int y);// Можно указать только типы void PointsZ(); void Lines(); void LinesW(); void LinesStipple(); void Prompt(); void TriangleExecuteMenu(int); void Triangle(); void PolygonStipple(); ..................................Листинг 21.64. Объявление (прототип) функции PolygonStipple()
- Добавьте в функцию main() файла Primitives.cpp новый пункт меню для вызова нового упражнения
// Точка входа приложения void main(void) { glutInitDisplayMode(GLUT_SINGLE | GLUT_RGBA); glutCreateWindow("Primitives"); // Заголовок окна glutDisplayFunc(RenderScene); // Обновление сцены при разрушении окна glutReshapeFunc(ChangeSize); // При изменении размера окна SetupRC(); // Создаем подменю для рисования конуса int triangle_menu = glutCreateMenu(TriangleExecuteMenu); glutAddMenuEntry("Показать с начальными установками", 0); glutAddMenuEntry("Отбор Вкл/Выкл", 1); glutAddMenuEntry("Глубина Вкл/Выкл", 2); glutAddMenuEntry("Каркас задней стенки Вкл/Выкл", 3); // Создание меню и добавление опций выбора glutCreateMenu(ExecuteMenu); glutAddSubMenu("Рисование конуса", triangle_menu);// Именно на первом месте glutAddMenuEntry("Рисование функцией Points", 1); glutAddMenuEntry("Точки с увеличением размера", 2); glutAddMenuEntry("Веер линий", 3); glutAddMenuEntry("Управление шириной линий", 4); glutAddMenuEntry("Управление фактурой линий", 5); // Число 6 у нас задействовано для субменю glutAddMenuEntry("Управление фактурой полигонов", 7); glutAttachMenu(GLUT_RIGHT_BUTTON);// Присоединяем // Конец создания меню glutSpecialFunc(SpecialKeys); // Для управления с клавиатуры glutMainLoop(); // Цикл сообщений графического окна }Листинг 21.65. Добавление нового пункта меню в функции main()
- Добавьте в функцию рендеринга RenderScene() файла Primitives.cpp код вызова нового упражнения
//**************************************************** // Функция обратного вызова для рисования сцены void RenderScene(void) { // Окно очищается текущим цветом, // установленным функцией glClearColor() glClear(GL_COLOR_BUFFER_BIT); // Отработка выбора пользователя switch(::choice){ case 1: Points(); break; case 2: PointsZ(); break; case 3: Lines(); break; case 4: LinesW(); break; case 5: LinesStipple(); break; case 6: Triangle(); break; case 7: PolygonStipple(); break; default: Prompt(); } // Исполнить (очистить) очередь команд glFlush(); }Листинг 21.66. Вызов функции PolygonStipple()
#include "Points.h" // Включение перенесенного кода #include "PointsZ.h" // Включение кода рисования точек с увеличением размера #include "Lines.h" // Веер линий #include "LinesW.h" // Проверяется изменение ширины линий #include "LinesStipple.h" // Линии с разной фактурой #include "triangle.h" // Рисовать конус #include "PolygonStipple.h" // Рисовать полигон с закраской по маске #include "Prompt.h" // Вспомогательный код для начального окнаЛистинг 21.67. Подключение файла PolygonStipple.h с кодом нового упражнения
- Запустите приложение - должен получиться следующий результат