10.5. Стандартные объемные формы
В OpenGL предусмотрены некоторые стандартные, наиболее часто используемые трехмерные объекты. Набор таких форм представлен в библиотеке GLU (Utility Library), которая реализована в виде модуля giu32.dll и является неотъемлемой частью OpenGL. Она включает в себя несколько функций управления проекциями (одну из которых — gluPerspective мы уже использовали), функции работы с полигонами, кривыми и поверхностями типа В-сплайнов и другие функции.
Рассмотрим функции gluCylinder, gluSphere, gluDisk И gluPartialDisk (рис. 10.4—10.7).
Перечисленные объекты названы "quadric objects". Параметры slices и stacks определяют количество плоских граней, используемых для аппроксимации поверхности. Для того чтобы нарисовать подобный объект, необхо-

Рис. 10.4. Цилиндр

Рис. 10.5. Шар

Рис. 10.6. Диск

Рис. 10.7. Часть диска
димо вызвать функцию giuNewQuadric, а после рисования освободить память ВЫЗОВОМ функции gluDeleteQuadric.

По умолчанию каждый объект рисуется со сплошным заполнением. Изменить СТИЛЬ показа МОЖНО ВЫЗОВОМ функции gluQuadricDrawStyle. МОЖНО за-
дать такие стили показа — в виде точек, расположенных в вершинах многоугольника, каркасное изображение, сплошное заполнение и силуэт (разновидность каркасного). Например, вызов
![]()
дает каркасное изображение.
Объекты данного типа располагаются в пространстве в центре координат (0, 0, 0) с учетом матрицы glmodelview. Поэтому, чтобы нарисовать изображение объекта в требуемом месте, нужно соответствующим образом изменить эту матрицу, например, С ПОМОЩЬЮ функций glTranslate И glRotate.
Нижеприведенный пример иллюстрирует показ объектов типа "quadric
objects".
Файл studex53. срр:
Т); , 40);
tion);


Изображение в окне программы studex53 приведено на рис. 10.8.

Рис. 10.8. Цилиндры, шар и диск
При подготовке этого рисунка к печати был изменен цвет фона на белый. Однако на экране монитора синий цвет выглядит значительно лучше (в тексте программы: giciearColor(0, 0, 0.5, l.0f)).
10.6. Текстура
В OpenGL имеется достаточно полный набор средств для построения тексту-рированных изображений.
В качестве текстуры можно использовать растровое изображение. Оно может быть одномерным или двумерным. Для наложения текстуры необходимо выполнить несколько операций.
1. Сначала открыть в памяти массив, в котором будет храниться растр текстуры. Число байт массива рассчитывается исходя из количества бит на пиксел текстуры. Размеры растра текстуры обязательно должны быть равны степени двойки (плюс несколько пикселов на бордюр). Это требование создает некоторые неудобства для программиста, особенно в случае, когда текстура может быть прочитана из произвольного растрового файла. Впрочем, это не является неразрешимой проблемой — любой растр текстуры можно либо обрезать, либо растянуть (сжать) до требуемых размеров.
2. Заполнить массив текстуры. Здесь следует учитывать то, в каком формате представлен растр текстуры. Если пикселы текстуры представляются в формате RGB (24 бита на пиксел), то байты в массиве должны располагаться в виде троек (R, G, В). Заметим, что в массивах DIB Windows API цветовые компоненты располагаются в обратном порядке, то есть (В, G, R).
3. После того как массив открыт, нужно передать OpenGL адрес массива и другие его параметры. Делается это вызовом функции giTeximage2D для двумерной текстуры и giTeximageiD для одномерной
4. Затем можно задать параметры фильтрации текстуры (вызовом функции glTexParameter) для качественного отображения объектов различных размеров.
5. Перед непосредственным рисованием объектов необходимо установить режим использования текстуры. Делается это вызовом функции giEnable(GL_TEXTURE_2D). Для объектов типа "quadric objects" (шар, цилиндр, диск) нужно также вызвать еще и функцию
gluQuadricTexture(quadricObj, GL_TRUE).
6. При выводе полигональных граней (gljtriangles, gl_quads и им подобных) необходимо указывать соответствие текстурных координат и координат в пространстве объектов. Сделать это можно вызовом функций из семейства giTexCoord. Так, например, функция giTexCoord2f (s,t) указывает на точку с текстурными координатами s и t. Последующий вызов функции givertex3f (x,y, z) одновременно с заданием координат грани также ставит в соответствие координаты (s,t) координатам (x,y,z). На рис. 10.9 показан пример отображения координат четырехугольной грани.

Рис. 10.9. Координаты текстуры (s, t) и координаты вершин (Р1—РА)
Запрограммировать такое отображение текстуры можно таким образом:

Рассмотрим пример использования текстуры в следующей программе.
Файл studex54. срр:



Результат работы программы studex54 показан на рис. 10.10.

Рис. 10.10. Пример синтетической текстуры
Можно предположить, что хозяин этого замка решил покрыть плиткой стены, дабы уберечь свою недвижимость от разрушительного воздействия агрессивной окружающей среды. Так это было или нет, но здесь мы еще раз использовали шахматный узор — уже для текстуры. Растр текстуры генерируется здесь "на лету" и сохраняется в массиве pixels. Это пример синтетической-текстуры, узор создается простейшим алгоритмом. Для создания реалистичных изображений в качестве текстур обычно используются цифровые фотографии.
В общем случае, текстуры удобнее хранить в файлах на диске. Это могут быть достаточно сложные изображения, изготовленные заблаговременно. В программах для Windows растры можно создавать в виде ресурсов, которые после компиляции записываются в выполняемые файлы, например, в файлы ЕХЕ. А можно использовать и отдельные файлы стандартных форматов. В последнем случае текстуры удобно многократно редактировать.
Рассмотрим, как можно использовать текстуры, записанные в файлах BMP. Такие файлы хранят растр в формате DIB (Device Independent Bitmap). Формат DIB похож на формат текстуры OpenGL, однако есть некоторые отличия, Так, в DIB используется выравнивание строк на границу двойного слова. Иными словами, количество байт в строке растра всегда должно быть кратно четырем — если это не так, то добавляют лишние байты. В нашем случае благоприятным фактором является то, что размеры текстур OpenGL должны быть равны степени двойки. Начиная с размеров по горизонтали, равных четырем, 24-битные растры DIB автоматически располагаются в памяти так же, как и текстуры OpenGL — выравнивание отсутствует.
Если использовать 24-битную глубину цвета, то более существенным отличием DIB от формата текстур OpenGL является порядок расположения байтов R, G и В. Для массивов текстур OpenGL должно быть R-G-B, в то время как в DIB наоборот: B-G-R. Поэтому после чтения файла необходимо переставлять байты R и В.
Наша следующая программа (studex55) иллюстрирует чтение текстуры из файла BMP. Эта программа является модификацией предыдущей программы (studex54). Изменения коснулись только функции initMyTexture. В ее тело встроена функция чтения файлов BMP, которая названа ReadTextureBMP.



Текстура здесь читается из файла "filename.bmp".
В этой программе текстура загружается в массив всякий раз при создании, кадра. В данном примере это вполне допустимо, однако в других случаях такой подход может быть плохим по быстродействию. Поскольку дисковые операции являются медленными (особенно при чтении нескольких различных файлов больших размеров), то чтение файлов текстур нужно стараться делать как можно реже. Например, при построении кадров "облета замка" — to есть при "показе одних и тех же объектов с разных ракурсов, текстуры лучше всего загружать перед началом цикла показа. Если используются несколько текстур, то для каждой можно создать в памяти отдельный массив.
На рис. 10. 11 показан результат работы studex55.
Возможно, в этом замке мало дверей и окон. Но их несложно добавить в текстуру с помощью любого растрового графического редактора, не так ли? Хотя, вероятно, понадобится использовать уже несколько текстур для разных стен.
Следует отметить, что приведенная выше функция ReadTextureBMP не является универсальной— она не рассчитана на другие разновидности формата файлов BMP. Эту функцию необходимо существенно видоизменить, если предусматривается чтение, например, и 256-цветных растров. Такие растры читать несколько сложнее, поскольку требуется загружать и устанавливать палитру. В качестве универсального решения для чтения файлов формата BMP можно порекомендовать использовать функцию auxDiBimageLoad из библиотеки glaux.

Рис. 10.11. Использование текстуры из файла
