М. Ву, Т. Девис, Дж. Нейдер, Д. Шрайнер - OpenGL. Руководство по программированию (Библиотека программиста) (2006) (1124363), страница 54
Текст из файла (страница 54)
Например, следующий список отображения выводит велосипед, причем отдельные детали конструкции велосипеда (руль, рама и колеса) отображаются собственными списками: а!Мень!яс(!!зС)паек,6( СОМР!СЕ); к1са»С!зС(лапа1епагз); а1Са11(!зс(ггаае); к1тгапз1аге((1.0, В.О, 0.8); 61Са»С!яС(илее1); к1тгапя!агес(3.0, 0.0, 0.0); 6)са» Ссяс(ипее!); Е(Елани.!яС(); Это не позволит вам реализовать полноценную глубокую рекурсию, так как вложенность списков отображения ограничена значением 64, но это число может быть и больше, в зависимости от реализации. Для получения информации о максимальной вложенности списков для конкретной реализации Ореп01 воспользуйтесь вызовом ((16ес1псекегч(6( мАх (15т ме5т1м6, 61!пс *аз!а); Орепб).
позволяет создавать списки отображения, которые вызывают еще не существующие списки. При этом ничего не происходит. Наконец, иерархическая структура — просто удобное средство компоновки нескольких списков более низкого уровня в смысле послелующего редактирования, как в дистинге 7.3. Здесь внешний список отображения объединяет описания отдельных вершин многоугольника.
Листинг 7.3. Иерархический список отображения 61нень!яС(1,61 СОМР1(Е); 61Чег(ехзгч(ч1): Е1ЕпаС!яС(); Е1Меис!ЯС(2,6( СОМРХ(Е); 61Чеггех3(ч(ч2); 6!Ела(!яС(); М!Меис!зс(3,6С СОИР!СЕ); Е1Чеггех3(ч(чз); а!Епа(!яС(>; а1иеиь!4С(4,61 СОМР1(Е): а!Вез!п(6( РОСЧООМ); асса»(ся(( 1>; 61са111!яС(2): 61са11(! яС(3); 6!Ела(); 6!Ела!!я!(); Чтобы воспроизвести многоугольник, вызывается список с номером 4. Чтобы от. редактировать отдельную вершину, нужно всего лишь пересоздать соответствующий этой вершине вложенный список. Удобно то, что, когда вы создадите новый список под старым индексом, сусцествующий список автоматически будет ула.
Выполнение составных списков отображения 251 нен. Это не значит, что распределение памяти будет оптимальным для достиженнн максимальной производительности, но в иных случаях зто лучше чем ничего. С1Ьоо)еап я11нг1нг(СЕн1пС 1мг); Возвращает 6Е ТМОЕ, если аргумент Ы представляет уже используемый ин- декс, и 61 ЕА15Е в противном случае. Вм можете явно удалить указанный список отображения или набор списков с по- следовательными индексами при помощи вызова х10е1егее1нгнО. Соответст- нующис индексы становятся снова доступными. то1П 610е1еге11нгн(СЕшп1 Ы, С(л(ге) галде) Удаляет заданное количество (галде) списков отображения, начиная от задан- ного индексом Внг.
При попытке удаления несуществующего списка ничего не происходит. выполнение составных списков отображения ОрепСЬ предоставляет эффективный механизм последовательного выполнения нккольких списков отображения. Этот механизм требует, чтобы вы поместили нндексы списков в массив и воспользовались вызовом я16а11е1нгн (), Очевидню, что применение данного механизма имеет смысл в случае, когда индексы сонтнетствуют каким-либо выразительным значениям. Так, если вы создаете шрифт, пждый индекс будет ассоциирован с АБСП-кодом символа шрифта.
Чтобы иметь несколько таких шрифтов, вам нужно задать для них различные начальные индексы, а сделать это легко с помощью вызова х111 нгВане() перед выполнением 11СнП11нгн(). ной н111 нгване(СЕп1п( бане); Задает смещение, добавляемое к индексам списка отображения.
По умолча- нию принято значение О. Это смещение пе имеет эффекта пи на команду н1Са1111 н ГО, примененную к одиночному списку отображения, ни на коман- ду н1йем11нг(). нок( н16а1111нгн(С1н1ге1 и, СЕеппш Гуре, сопл( СЕчоЫ *ЪЬ); Выполняет л списков отбраження.
целевые индексы вычисляются путем сло- вения базового смещения (заданного х11! згване()) с целыми числами мас- сива, указанного аргументом Ъй. эт- юый да- 1ргумент гуре обозначает тип данных элемента массива; 6е Втте, 6е ОМ516йе0 1(ТЕ, 61 5НОНТ, 61 ОМ516МЕО 5НОКТ, 61 1МТ, 61 ОМ516МЕО 1МТ или 6Е РЕОАТ. Управление индексацией списков отображений Пока что мы советовали не пренебрегать командой к16еп1! нгн(), чтобы всегда быть уверенными в уникальности индексов списков отображения. Если это по аким-либо причинам вас не устраивает, воспользуйтесь командой я\1нЕ!нг(), позволяющей узнать, свободен ли указанный индекс.
252 Глава? ° Списки отображения Соответственно, понимается, что с аргументом 1м/з нужно обращаться как с массивом байтов, беззнаковых байтов, коротких целых чисел, коротких целых без знака, целых чисел, беззнаковых целых чисел или чисел с плавающей запятой. Аргумент гуре может также принимать значение 6Е 2 ВУТЕ5, 6С 3 ВТТЕ5 или 6С 4 ВУТЕ5. В этом случае цепочки длиной в 2, 3 или 4 байта читаются из массива 1ст(з, а результирующее смещение вычисляется по следующему алгоритму (здесь Оу/е[01 — стартовый байт последовательности): /* Ь = 2, Э ипи 4; байты массива нумеруются в поспедоватепьностн О, 1, 2, 3 "/ от(вес = 0; тот (! = 8; ! < Ь; (++) ( от!вес = от!вес « 8; о!тает += ЬуСе(!): ) !пбех = оттает + 1!яСЬаве; Для многобайтовых полей первыми обрабатываются старшие разряды, а в остальном порядок идентичен обработке массива.
Листинг 7А приведен нами в качестве примера использования комбинированных списков отображения, это фрагмент программы, полностью представленной в листинге 7.5. Эта программа рисует символы векторного шрифта (набора символов, образованных отрезками линий). Процедура ! и! 15сгохебропС() устанавливает индексы списка отображения для каждого символа так, чтобы они соответствовали своим А8СП-кодам.
Листинг 7.4. Определение составных списков отображений чо!б !п(С5СгонебропС(чо!б) 6(м(пС паве; Ьаве = 816епС!втв( 128): 81С!втваве(Ьаве); 81яеиС!вС(Ьаве+'А', 6С СОМР1СЕ); бгаигеттег(Абата); 81ЕпбС(вС(); 81яеиС!вС(Ьаве+'Е', 6С СОМР1СЕ); бгаигеССег(Ебата); 81ЕпбС(ят(); 81яеиС!вС(ьаве+'Р', 6С СОМР1СЕ); бгаисеССег(Рбата); 81Епб(!вС(); 81кеиС!вС(Ьаве+'а', 61 СОМРХСЕ); бгаиьеССег(хвата); 81ЕпбС(вт(); 8(кеиС!вС(Ьаве+'5', 61 СОМР1СЕ); бган(.еССег(5бата); 81Епбь!вС(); 81яеиС!ят(Ьаве+' ', 6С СОМР1СЕ); /' пробел */ 8\Тгапв1атег(8.9, 8.0, 0.0); 81ЕпбС(вт(): Команда 816епс! 818 () заказывает 128 последовательных индексов.
Первый из них становится базовым значением. В списке отображения каждый символ представляется суммой базового значения и АВСП-кода символа. В этом примере мы описываем только пять букв и пробел. Выполнение составных списков отображения 253 после создания списков отображения можно вызвать команду к1са111! 515[) ЗЛЯ ИХ Обработки. Так, можно передать процедуре рг( п151гохе051г ( па [) строку символов: мш рг)п151гонеи51г(пх(6( Ьусе *з) ( 61)пс 1ел = ксг1ел(З); 5]саПС)зсз(]ел, ОС Вуте, з); ) Здесь значение АЯСП-кода служит как смешение в наборе индексов, а целевой индекс образуется его сложением с текущим базовым смещением.
Результат ра[юты программы, представленной в листинге 7.5, показан на рис. 7.]. Рис. 7.1. Фраза, составленная нз символов векторного шрифта: А, Е, Р, Р„5 йнстинг 7.5. Составные списки отображения, определяющие векторный шрифт: Вохе.с Рисгле Рт 1 Мс)спе 5ТМОКЕ 2 Усе()пе ЕМО 3 1уреиег зсгисс слагро)л1 ( ЕСУ]оас к, !Ь1 1уре; . ] СР; СР Аиаса(] = ( ( О, О, РТ), [О, 9, РТ], (1, 10. РТ), (4, 10, РТ), (5 9 РТ] (5 0 5ТВОКЕ) (О 5 РТ) [5 5 ЕМО) СР Ееаса(] = ( (5, е, Рт>, (о. о, Рт>, [в, 1о, рт>, (5, 1в, 5ткоке], (О, 5, РТ], (4, 5, ЕМО] Н Риаса[] = ( О Р (Е 10 РТ) (4, 10, РТ), (5, 9 РТ] (5 (4 5 РТ) (О 5 ЕМО) ]: СР Виа1а(] = ( (В, 6, РТ], (О, 10, РТ), (4. 10, РТ], (5, 9, РТ), (5, 6, РТ], (4, 5, РТ], (О, 5, 5ТМОКЕ), (3, 5. РТ), (5, О, ЕМО) ): СР 54а1а [] = [ (З, 1, рт>, [1, В, Рт), (4, Е, рт], [5, 1, РТ>, (5, 4, Рт], лроаиллгение *Р 254 Глава 7 ° Списки отображения Листииг 7.5 (орос/олжение) (4, 5, РТ), (1, 5, РТ».
(8, 6, РТ), (8, 9, РТ), (1, 18, РТ), (4, !8, РТ), (5, 9, ЕМО) /' бганСеСсег() интерпретирует команды из массива ' для символа и воспроизводит символ отрезками прямых >/ ьтаС1с чо1б бганСеССег(СР *1) ( 61Веа!п(6с с1МЕ 5ТМ1Р); нл(!е (1) ( ьи(сел (1->суре) ( саье РТ; 61Чегтех2(ч(81->х); Ьгеа)с; саье 5ТРОКЕ: 81Чегтех2тч(й1->х); 61Епб(); 61ВеВ(п(6с (1МЕ 5ТМ1Р); Ьгеас; саье ЕМО: В!Чегтех2(ч(81->х); В)Епб(); В!!галь!атет(В.В, О.О, 8.8>; гесигп; 1++; /' Создание списка отображения для каждого из 6 символов "/ ьтаС>с чо1б (п!С(чо(б) Осм!пс Ьаье; 615лабеМабе1(6( РСАТ); ьаье = 616епс!ьсь(128); 61с!ьсваье(ьаье); В!ЙенС(ьт(Ьаье+'А', 6С СОМР1СЕ>; бгаиСеССег(Абата); 81ЕпбС(ьС(); В!ИенС(ьС(Ьаье+'Е', 6С СОМР(СЕ>; бганСеССег(Ебата>; 81ЕпбС>ьС(); 81йенС(ьС(Ьаье+'Р', 6С СОМРХСЕ); бганСеттег(Рбата); 61Епб(.(ьС(): 6!иенс»ьс(ьаье+'й', 6с сомР1се); бгаисессег(оба!а); В(Епс(С(ьС(); 61меис(ьс(ьаье+'5', 6с сОмР1(е); бгаисессег(5баса); 61ЕпбС>ьС(); 61иенС1ьС(Ьаье+' ', 6С СОМР1СЕ); 61тгапь1асет(В.О, 0.8, 8.8); 61ЕпбСзьС(); спаг *Сеьт! = "А 5РАЙЕ 5ЕМАРЕ АРРЕАЙ5 А5"; слаг *СеьС2 = "АРЕ5 РМЕРАМЕ КАМЕ РЕРРЕМ5"; 256 Глава 7 ° Списки отображения Листинг 7.5 (продолжение) 81итиа1п(оор(); гегигп 9; Управление параметрами состояния с помощью списков отображения Список отображения может содержать вызовы команд, которые изменяют переменные состояния ОрепО)..
Эти изменения производятся во время выполнения списка отображения, как если бы команды выполнялись в непосредственном режиме, и их результаты остаются зафиксированными по окончании выполнения списка отображения. Вы уже видели зто в листинге 7. 2, и мы снова демонстрируем в листинге 7.6, что изменения текущих цвета и матрицы остаются в силе и после выполнения списка отображения. Листинг 7.6.