| Китай |
Геометрические примитивы в 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 с кодом нового упражнения
-
Запустите
приложение - должен получиться следующий результат



