Программирование графики с использованием Direct3D

         

COM


Microsoft COM (Component Object Model) — это программная модель разработанная с целью позволить создание полностью переносимых компонентов, допускающих безопасное обновление. С точки зрения COM программные компоненты должны устанавливаться также легко, как и аппаратные. COM — основа некоторых API, таких как OLE и DirectX.

COM использует объектно-ориентированную модель, отличающуюся от модели, применяемой в таких языках как C++. Модель COM более строгая. Например, версия наследования в COM ограничена по сравнению с C++. Также COM-объекты не могут содержать открытых членов данных. Все взаимодействие с объектом должно осуществляться через функции-члены.

COM-компонент состоит из объекта и одного или нескольких интерфейсов посредством которых осуществляется доступ к объекту. Объект обеспечивает функциональность, предоставляемую COM-компонентом, но к нему нельзя обратиться напрямую. К COM-объектам всегда обращаются через интерфейсы. Один объект может поддерживать несколько интерфейсов. Рис. 3.1 иллюстрирует отношения объект/интерфейс.



Рис. 3.1. COM-объекты и интерфейсы


Рисунок иллюстрирует взаимодействие приложения с COM-объектом. Приложение использует COM-объект только через поддерживаемые объектом интерфейсы.

COM-объект может поддерживать сразу несколько интерфейсов, чтобы его функциональность можно было совершенствовать или расширять без риска нарушить работу существующих программ.

COM также поддерживает свойство, названное инкапсуляция времени существования (lifetime encapsulation). Инкапсуляция времени существования означает, что COM-объекты управляют своим собственным уничтожением. Когда объект обнаружит, что он больше не нужен, он уничтожит себя сам. Чтобы эта функция работала корректно, программы должны уведомлять объекты, при создании нового указателя на объект и при уничтожении указателя.

Все COM-объекты являются производными от COM-объекта IUnknown, предоставляющего три функции: AddRef(), Release() и QueryInterface(). Функции AddRef() и Release() увеличивают и уменьшают счетчик ссылок на объект. Функция QueryInterface() применяется для поиска дополнительных интерфейсов объекта (или определения того, что интерфейс не поддерживается данным объектом). Один из аргументов функции QueryInterface() — Глобальный Уникальный Идентификатор (GUID), который идентифицирует искомый интерфейс.

Все API DirectX построены на основе COM. Это, однако, не говорит о том, что вы должны быть профессионалом в COM, чтобы применять DirectX. Фактически, использование COM-объектов подобно использованию объектов C++. Ниже приведены некоторые правила, которые вам надо соблюдать при работе с COM.

COM-объекты и объекты C++ не могут быть производными друг от друга. Простейший способ получения класса C++ из COM-объекта, состоит во «внедрении» COM-объекта в классы C++ и написании функций-оболочек (wrapper functions) для каждой функции COM. Каждый раз при создании копии указателя на COM-объект должна быть вызвана функция объекта AddRef() чтобы известить объект о создании дополнительной ссылки. Это не относится к созданию объекта. Обычно API DirectX выполняет эту работу за вас и включает вызов функции AddRef() в функцию, создающую COM-объект. Каждый раз, когда указатель на COM-объект больше не нужен, должна быть вызвана функция объекта Release(). Функция QueryInterface() не всемогуща. Она возвратит интерфейсы объекта, только если объект поддерживает их. Попытка получить произвольные интерфейсы от объекта может потерпеть неудачу.

Если вы хотите узнать больше о COM, загрузите спецификацию с сайта Microsoft (www.microsoft.com).






Conv3ds


Direct3D предоставляет для создания X-файлов утилиту CONV3DS, преобразующую файлы 3D Studio (.3DS) в X-файлы. У утилиты CONV3DS есть ряд параметров командной строки. Наиболее часто применяемые параметры перечислены в таблице 3.1.


Таблица 3.1. Параметры утилиты CONV3DS


Параметр Описание
m Создает единую сеть вместо иерархии фреймов
t Создает текстовый X-файл
A Включает в файл данные анимации (если они есть)
f Не импортировать данные о перемещении фрейма




Цвет испускаемого света


Испускаемый свет (emissive light) — это свет, исходящий от самого объекта. Испускаемый свет применяется при представлении таких источников освещения, как лампы и неоновые трубки. По умолчанию объекты не испускают света (цвет испускаемого света — черный). Для контроля испускаемого света используются функции GetEmissive() и SetEmissive().

СОВЕТ Испускаемый свет в цветовых моделях Ramp и RGB. Цветовая модель Ramp не поддерживает цветного освещения, однако испускаемый свет не зависит от источников освещения, и объекты могут испускать цветной свет как при использовании цветовой модели Ramp так и в цветовой модели RGB.



Цвет отраженного света


Вы можете настраивать цвет отраженного света с помощью функций GetSpecular() и SetSpecular(). По умолчанию цвет отраженного света — белый.



Цвета текстуры


После создания экземпляра интерфейса Direct3DRMTexture можно вызывать функции GetColors() и SetColors() для управления количеством цветов, используемых Direct3D для представления текстуры. Посредством функций GetShades() и SetShades() можно осуществлять более точный контроль процесса визуализации текстуры.

Количество цветов текстуры (контролируемое посредством функций GetColors() и SetColors()) определяет число цветов, присутствующих на самой текстуре. Функции GetShades() и SetShades() позволяют контролировать, сколько оттенков будет использовано для представления каждого из цветов текстуры. Например, для двухцветной текстуры функция GetColors() возвратит значение 2, а функция GetShades() возвратит значение 16 (поскольку 16 — это используемое по умолчанию количество оттенков). В этом примере каждый из двух цветов текстуры будет представляться шестнадцатью различными оттенками.

Сокращение числа цветов или оттенков текстуры ухудшает качество получаемого изображения, но позволяет отдельным текстурам быть полезными для других. Например, если текстура использует много цветов, но применяется так, что ее качество на столь существенно, то количество цветов и оттенков этой текстуры может быть сокращено, благодаря чему резервируется большее количество цветов и оттенков для текстур, чей вид важнее.



Цветовые модели


И программные и аппаратные устройства поддерживают две цветовых модели: RGB и Ramp. Цветовая модель RGB поддерживает цветное освещение, а цветовая модель Ramp — нет. Благодаря этому устройства Ramp превосходят по быстродействию устройства RGB. Устройства Ramp также называют монохромными устройствами из-за их одноцветной обработки источников освещения. Это, однако, может ввести в заблуждение, так как в режиме Ramp монохроматическими являются только источники освещения. Сетки и грани в режиме Ramp используют все цветовые возможности.



D3DCOLOR


Тип D3DCOLOR применяется в Direct3D для представления цветов. Цвет имеет красную, зеленую, синюю и альфа составляющие. Значение каждой составляющей может варьироваться от нуля (отсутствие компонента) до единицы (максимальная интенсивность компонента).

Фактически дело обстоит несколько сложнее. Тип D3DCOLOR представляется типом DWORD, и поэтому, он не может хранить четыре значения с плавающей точкой. При сохранении значения цветовых составляющих умножаются на 255 и помещаются в соответствующие разряды значения типа DWORD. Для этой цели Direct3D предоставляет макроопределение. Присвоить значение переменной типа D3DCOLOR можно с помощью макроопределения D3DRGB или D3DRGBA:

D3DCOLOR color=D3DRGB(1,1,1); // создаем переменную D3DCOLOR // для белого цвета D3DCOLOR color=D3DRGBA(1,1,1,0); // создаем переменную D3DCOLOR // для белого цвета // с нулевой альфа-составляющей

Значения, передаваемые макроопределениям D3DRGB и D3DRGBA должны быть в диапазоне от нуля до единицы. Макроопределение выполняет умножение и преобразование значений. К тому же не требуется выполнять приведение к типу D3DVALUE, поскольку макроопределение осуществляет приведение типа автоматически.

Чтобы извлечь отдельные цветовые составляющие из значения типа D3DCOLOR применяются функции D3DRMColorGetRed(), D3DRMColorGetGreen(), D3DRMColorGetBlue() и D3DRMColorGetAlpha().



D3DRMBOX


Direct3D использует структуру D3DRMBOX для описания размеров объекта. Интерфейсы Direct3DRMMesh и Direct3DRMMeshBuilder предоставляют функцию GetBox(), применяемую для получения размеров объекта. Структура D3DRMBOX содержит две структуры D3DVECTOR:

typedef struct _D3DRMBOX { D3DVECTOR min, max; } D3DRMBOX;

Хотя используются структуры типа D3DVECTOR, данные в них описывают точки, а не векторы. Структуры min и max применяются для указания противоположных углов минимального возможного параллелепипеда, который мог бы содержать рассматриваемый объект.



D3DRMQUATERNION


Кватернионы описывают вращение. В главе2 для описания вращения мы применяли вектор и значение вращения. Вектор определял ось вращения, а значение — угол поворота. Кватернионы инкапсулируют вектор и значение в одной структуре:

typedef struct _D3DRMQUATERNION { D3DVALUE s; D3DVECTOR v; } D3DRMQUATERNION; typedef D3DRMQUATERNION *LPD3DRMQUATERNION;

Для инициализации кватернионов применяется функция D3DRMQuaternionFromRotation(). Функция получает вектор и значение вращения и создает кватернион.

Кватернионы удобны для вычисления промежуточных значений вращения. Например, функция D3DRMQuaternionSlerp() принимает в качестве аргументов два кватерниона и число. Функция вычисляет промежуточный кватернион между двумя векторами. Передаваемое в качестве параметра число определяет, в каком месте между двумя указанными кватернионами будет расположен новый. Например, если указать значение 0.5, новый кватернион будет создан точно между двумя исходными.



D3DRMVERTEX


Структура D3DRMVERTEX применяется в Direct3D для описания вершин сеток и определена следующим образом:

typedef struct _D3DRMVERTEX{ D3DVECTOR position; D3DVECTOR normal; D3DVALUE tu, tv; D3DCOLOR color; } D3DRMVERTEX;

Структура position описывает местоположение вершины. Вектор normal задает нормаль вершины (для метода визуализации Гуро) или вектор грани (при равномерной закраске). Значения tu и tv определяют координаты точки текстуры, которая отображается на данную вершину. Значение color задает цвет вершины.

Структура D3DRMVERTEX используется функциями GetVertices() и SetVertices() интерфейса Direct3DRMMesh. Функция GetVertices() заполняет массив структур D3DRMVERTEX значениями соответствующих вершин. Эти значения можно затем изменить и передать функции SetVertices(), что приведет к изменению характеристик сетки. Этот способ могут использовать такие методы анимации, как анимация вершин и анимация текстур. Также с помощью функций GetVertices() и SetVertices() программа может изменить задаваемые по умолчанию нормали граней или вершин.



D3DVALUE


D3DVALUE— это основной тип данных в Direct3D. Тип D3DVALUE объявлен через тип float и применяется в Direct3D для представления координат вершин, интенсивности освещения, скорости вращения и т.д.

В 32-разрадных версиях C++, таких как Visual C++, числа для которых явно не указан тип, воспринимаются как числа типа int (если десятичная точка отсутствует) или double (если в числе есть десятичная точка). Другими словами, если в вашей программе встречается неспецифицированное число с плавающей точкой, компилятор выделит для него восемь байт (как для числа двойной точности), а не четыре (как для числа с плавающей точкой одинарной точности). По этой причине, а также из-за того, что код, использующий тип D3DVALUE будет более переносимым, в программах Direct3D часто используются значения типа D3DVALUE. Если вы уверены, что программа не будет переноситься на другие платформы, и вам неприятно наличие многочисленных приведений к типу D3DVALUE в коде (что довольно понятно), применяйте для указания компилятору типа значения суффикс «f» (в этом случае вы должны использовать десятичную точку). Приведем ряд примеров:

d3dfunction((D3DVALUE)3) // стандартный и безопасный способ d3dfunction((D3DVALUE)3.0) // стандартный и безопасный способ d3dfunction(3) // воспринимается как int и вызывает // предупреждение компилятора d3dfunction(3.0) // воспринимается как double и // вызывает предупреждение компилятора d3dfunction(3.0f) // допустимо, но уменьшает // переносимость d3dfunction(3f) // недопустимо, должна использоваться // десятичная точка



D3DVECTOR


Структура D3DVECTOR определена следующим образом:

typedef struct _D3DVECTOR { union { D3DVALUE x; D3DVALUE dvX; }; union { D3DVALUE y; D3DVALUE dvY; }; union { D3DVALUE z; D3DVALUE dvZ; }; } D3DVECTOR, *LPD3DVECTOR;

Объединения позволяют использовать переменные x и dvX (для примера) как взаимозаменяемые. Структура D3DVECTOR повсеместно применяется в Direct3D для представления не только векторов, но и точек.



Декалы


Декал (decal) — это текстура, добавляемая к сцене без присоединения к грани или сетке. Декалы визуализируются в сцене в соответствии с их местоположением, благодаря чему они увеличиваются или уменьшаются в зависимости от расстояния до зрителя. Декалы также подчиняются правилам скрытия невидимых поверхностей. Если декал находится позади объекта, он закрывается этим объектом.

Декалы имеют один существенный недостаток: они всегда расположены лицевой поверхностью к зрителю и не могут просматриваться с разных углов. Это значительно ограничивает область их применения. Если их расположить вдалеке от камеры, они могли бы использоваться, например, для представления картин в сцене музея или мониторов в рубке космического корабля.

Несмотря на указанный недостаток, декалы полезны при визуализации двумерных объектов сцены. Эффекты, реализация которых посредством сеток и граней оказывается слишком ресурсоемкой (например, взрывы) часто могут быть эффективно реализованы с применением декалов.

Интерфейс Direct3DRMTexture предоставляет ряд функций для работы с декалами:

GetDecalOrigin() GetDecalScale() GetDecalSize() GetDecalTransparency() GetDecalTransparentColor() SetDecalOrigin() SetDecalScale() SetDecalSize() SetDecalTransparency() SetDecalTransparentColor()

Большинство этих функций используются только с декалами. Однако функции прозрачности применяются для управления прозрачностью и декалов и текстур, присоединенных к сеткам и граням.




Direct3D


Direct3D— это набор интерфейсов модели компонентных объектов Microsoft (Microsoft Component Object Model, COM) представляющих графические конструкции, такие как сетки и грани, и прикладные конструкции, такие как области просмотра и устройства. В этой главе мы скажем несколько слов о каждом из интерфейсов.

Хотя мы и обсудим интерфейсы и их функции, данная глава не является справочным руководством. Мы не будем сосредотачиваться на списках параметров или возвращаемых значениях, а только обсудим обеспечиваемую интерфейсом функциональность.

Перед тем как погрузиться в дискуссию об интерфейсах Direct3D, вам необходимо познакомиться с Microsoft COM. В следующем разделе мы кратко обсудим модель COM. По общепринятому соглашению имена COM-интерфейсов начинаются с префикса «I» (I — сокращение от «Interface»). В нашем обсуждении мы опустим этот префикс.



Direct3DRM: основной интерфейс


Как было упомянуто ранее, Direct3D— это набор COM-интерфейсов. Все интерфейсы, составляющие Direct3D, зависят от одного главного: Direct3DRM (RM обозначает Retained Mode — абстрактный режим). Объект Direct3DRM представляет непосредственно Direct3D и создается функцией Direct3DRMCreate():

LPDIRECT3DRM d3drm; Direct3DRMCreate(&d3drm);

Тип LPDIRECT3DRM — это указатель на интерфейс Direct3DRM. Функция Direct3DRMCreate() создает объект и инициализирует указатель на интерфейс. После того, как функция Direct3DRMCreate() успешно завершится (мы поговорим о кодах возврата в конце этой главы), интерфейс Direct3DRM готов к использованию.



Direct3DRMAnimation: интерфейс анимации


В Direct3D термин анимация (animation) имеет два значения. Анимацией называется перемещение объектов в сцене, кроме того, анимация— это еще и название интерфейса, который поддерживает создание и воспроизведение анимации по ключевым кадрам.



Direct3DRMAnimationSet: интерфейс анимационного набора


Анимационный набор (animation set)— это коллекция объектов анимации, используемая для представления анимированной сцены в целом. Обычно анимационные наборы создаются путем импортирования анимированных сцен из анимационных пакетов, например, 3D Studio. Каждый объект сцены представляется объектом анимации, а все объекты анимации образуют анимационный набор.

Интерфейс Direct3DRMAnimationSet применяется для управления анимационными наборами и создается функцией CreateAnimationSet() интерфейса Direct3DRM.



Direct3DRMDevice: интерфейс устройства


Устройства Direct3D— это объекты, которые создают визуализированное изображение. Direct3D поддерживает несколько типов устройств. Программы могут выбрать устройство из списка доступных устройств или поручить Direct3D выбрать устройство автоматически. Есть два основных типа устройств — программные и аппаратные. Программные устройства позволяют программам работать на компьютерах, которые не оборудованы аппаратными ускорителями трехмерной графики. Аппаратные устройства доступны только на компьютерах, оборудованных соответствующими платами, и позволяют Direct3D полностью использовать возможности, предоставляемые аппаратными средствами.

Устройство представляется интерфейсом Direct3DRMDevice и может быть создано, посредстаом функций интерфейса Direct3DRM. Рассмотрим три способа создания устройства:

Создать объект отсечения (clipper object) DirectDraw, а затем создать устройство функцией CreateDeviceFromClipper(). Это самый простой и наиболее надежный метод создания устройства. Создать первичную поверхность DirectDraw с вторичным буфером (back-buffer) (позволяющим переключать страницы) и создать устройство функцией CreateDeviceFromSurface(). Этот метод используется для инициализации приложений Direct3D, которые будут работать в полноэкранном режиме. Инициализировать непосредственный режим Direct3D (Immediate Mode) и создать устройство функцией CreateDeviceFromD3D().

После создания устройства оно используется для определения параметров механизма визуализации и выполнения визуализации сцен.



Direct3DRMFace: интерфейс грани


Сетки представляют собой набор граней, следовательно, создание сеток означает создание граней. В большинстве случаев вы будете модифицировать существующие грани, а не создавать новые. Например, интерфейс конструктора сеток позволяет получить доступ к существующим граням с помощью функции GetFaces(). Также возможно создать грань с нуля, а затем добавить ее к конструктору сеток. В любом случае можно настроить атрибуты грани: цвет, текстуру, вершины ит.д. Грани представлены интерфейсом Direct3DRMFace.

Интерфейс Direct3DRMFace предоставляет функции GetColor() и SetColor(), позволяющие получить и установить цвет грани.



Direct3DRMFrame: интерфейс фрейма


Фреймы (frame) являются важной частью абстрактного режима Direct3D. Использование этого термина может привести к путанице, поскольку общепринятое его значение— «кадр анимации». В Direct3D значение этого термина происходит от словосочетания «система координат» (frame of reference). Фреймы применяются для размещения объектов в трехмерном пространстве. Объекты, такие как сетки, грани, камеры и источники света не имеют определенного местоположения или ориентации. Но если эти объекты присоединяются к фрейму, они получают свое местоположение и ориентацию от этого фрейма. В результате, при перемещении фрейма будут перемещаться все присоединенные к нему объекты.



Direct3DRMLight: интерфейс источника света


Direct3D поддерживает пять различных типов источников света: рассеянный свет, точечный источник света, направленный свет, параллельный свет и зональное освещение, или прожектор. Единственный общий для всех источников света параметр— цвет. Для каждого поддерживаемого Direct3D типа источника света может быть указано местоположение и ориентация, но в некоторых случаях эти параметры игнорируются.

Источники света представлены интерфейсом Direct3DRMLight и создаются функциями CreateLight() и CreateLightRGB() интерфейса Direct3DRM. Обе функции требуют, чтобы вы указали цвет и тип источника света, хотя в дальнейшем эти параметры могут быть в любой момент изменены.

Местоположение и ориентация источников света определяется посредством фреймов, поэтому перед использованием в сцене источник света должен быть присоединен к фрейму. Для этой цели интерфейс Direct3DRMFrame предоставляет функцию AddLight().



Direct3DRMMaterial: интерфейс материала


Материал определяет поведение света, попадающего на грани и сетки. Объект может быть сделан блестящим, матовым и, кроме того, задание свойств материала позволяет имитировать светящиеся объекты.

Экземпляр интерфейса Direct3DRMMaterial создается функцией CreateMaterial() интерфейса Direct3DRM. Интерфейс материала позволяет настраивать три параметра: мощность отраженного света, цвет отраженного света и цвет испускаемого света. Полученный в результате материал может быть назначен грани, сетке или конструктору сеток.



Direct3DRMMesh: интерфейс сетки


Интерфейс Direct3DRMMesh разработан для более быстрой работы с сетками. К сожалению, интерфейс сетки не так прост в использовании, как интерфейс конструктора сеток. Сетки могут быть созданы при помощи функции CreateMesh() интерфейса Direct3DRM и посредством функции CreateMesh() интерфейса Direct3DRMMeshBuilder.



Direct3DRMMeshBuilder: интерфейс конструктора сеток


Интерфейс Direct3DRMMeshBuilder— это высокоуровневый, удобный инструмент для манипуляций с сетками, предоставляющий 38 функций для создания и модификации сеток. Конструктор сеток, как следует из его названия, создает сетки, но сам сеткой не является. Однако, конструктор сеток может использоваться как удобная замена сетки и добавляться в сцену в качестве визуального элемента. Когда конструкторы сеток добавляются в сцену, они создают и используют внутреннюю сетку. Чтобы создать конструктор сеток, воспользуйтесь функцией CreateMeshBuilder() интерфейса Direct3DRM, как показано ниже.

LPDIRECT3DRMMESHBUILDER meshbuilder; d3drm->CreateMeshBuilder(&meshbuilder);



Direct3DRMShadow: интерфейс тени


Библиотека Direct3D разрабатывалась для создания быстродействующих приложений. В связи с этим иногда приходится приносить в жертву производительности точность и реализм. Хорошим примером является поддержка теней в Direct3D, поскольку методы визуализации, применяемые в Direct3D не вычисляют тени. Поддержка теней сводится к добавлению к сцене объектов, иммитирующих эффект отбрасывания тени. Эта имитация является очень упрощенной и имеет насколько ограничений.

Для создания тени требуется задать следующие элементы:

объект, отбрасывающий тень; источник света, используемый при вычислении параметров тени; плоскость, на которой отображается тень.

Первым ограничением является необходимость явно указывать источник освещения. Каждый источник освещения, который может отбрасывать тень, должен иметь собственный объект тени. Поддержка теней не является возможностью, которую достаточно просто разрешить или запретить.

Другое ограничение связано с необходимостью указывать плоскость на которую отбрасывается тень. Это значит, что вы не сможете получить тень на сложном объекте. Убедительные тени в Direct3D требуют плоских поверхностей.

Объекты теней являются экземплярами интерфейса Direct3DRMShadow и создаются посредством функции CreateShadow() интерфейса Direct3DRM. Интерфейс теней предоставляет только одну функцию: Init(). Функция Init() используется редко, поскольку функция CreateShadow() выполняет те же действия и проще в использовании.




Direct3DRMTexture: интерфейс текстуры


В Direct3D текстуры могут быть назначены для грани и сетки, либо добавлены непосредственно к сцене, как фоновое изображение или декал (decal). Текстуры могут быть загружены из файлов BMP, файлов PPM, из ресурсов программы или из памяти. Представляются текстуры интерфейсом Direct3DRMTexture.



Direct3DRMTextureWrap: интерфейс наложения текстур


Наложение текстуры — это объект, определяющий способ присоединения текстуры к сетке. Наложение текстуры контролирует стиль наложения (плоский, цилиндрический, сферический), ориентацию и параметры текстуры, такие как масштаб и начало координат.

Наложение текстуры создается с использованием упомянутых параметров и применяется к конструктору сеток или объекту сетки. Наложение текстуры определяет способ присоединения текстуры к каждой грани. Это позволяет значительно сократить объем работы, поскольку сетка может содержать тысячи граней.

Наложение текстуры представляется интерфейсом Direct3DRMTextureWrap и создается функцией CreateWrap() интерфейса Direct3DRM.




Direct3DRMViewport: интерфейс порта просмотра


Порт просмотра (viewport)— это термин, используемый в Direct3D для камеры. Порт просмотра определяет местоположение зрителя и направление просмотра сцены. Порт просмотра может применяться для настройки параметров поля зрения, переднего и заднего отсечения и перспективных преобразований. Порт просмотра можно анимировать, чтобы имитировать перемещение пользователя в виртуальном окружении.

Порт просмотра представляется интерфейсом Direct3DRMViewport и создается функцией CreateViewport() интерфейса Direct3DRM:

d3drm->CreateViewport(device, camera, 0, 0, device->GetWidth(), device->GetHeight(), &viewport);

Переменная d3drm является указателем на интерфейс Direct3DRM. Переменная device указывает на интерфейс Direct3DRMDevice. Переменная camera — это фрейм, определяющий местоположение и ориентацию порта просмотра. Мы подробнее обсудим фреймы далее в этой главе.



Direct3DWinDevice: интерфейс устройства Windows


Объект, обеспечивающий поддержку устройства Direct3D, является примером COM-объекта, поддерживающего несколько интерфейсов. Мы рассмотрели один интерфейс, через который можно использовать устройство — Direct3DRMDevice. Следующий интерфейс, с которым мы познакомимся — Direct3DWinDevice. Интерфейс Direct3DWinDevice представляет устройства, которые поддерживаются Windows. На рис. 3.2 показан объект устройства Direct3D и его интерфейсы.



Рис. 3.2. Объект устройства и его интерфейсы


Поскольку интерфейс Direct3DWinDevice является альтернативным интерфейсом устройства Direct3D, для получения интерфейса WinDevice приложения используют существующее устройство. Для этого применяется функция QueryInterface(), как показано в следующем примере кода:

LPDIRECT3DRMWINDEVICE windev; device->QueryInterface(IID_IDirect3DRMWinDevice, (void**)&windev);

Переменная device — это заранее инициализированный указатель на интерфейс Direct3DRMDevice. Для получения указателя на интерфейс Direct3DRMWinDevice применяется функция QueryInterface() интерфейса устройства. IID_IDirect3DRMWinDevice — это глобальный уникальный идентификатор (GUID) запрашиваемого интерфейса.

Интерфейс WinDevice поддерживает две функции: HandleActivate() и HandlePaint(). Обе эти функции уведомляют Direct3D о том, что были получены некоторые сообщения Windows. Программа, использующая Direct3D, должна вызывать функцию HandleActivate() при обработке сообщения WM_ACTIVATE. Аналогично, при обработке сообщения WM_PAINT программа должна вызвать функцию HandlePaint().




Доступ к граням


Интерфейс конструктора сеток позволяет также модифицировать и добавлять грани. Например, список созданных конструктором сеток граней может быть получен с помощью функции GetFaces(). Для получения количества граней в сетке применяется функция GetFaceCount(). Чтобы создать и добавить грани вызываются функции CreateFace(), AddFace() и AddFaces().



Доступ к вершинам


Конструктор сеток обеспечивает доступ к вершинам сетки. Число вершин сетки может быть получено с помощью функции GetVertexCount(). Данные вершин могут быть получены или установлены посредством функций GetVertices() и SetVertices(). Возможность доступа к вершинам сетки открывает большие возможности изменения конфигурации сетки с помощью указанных функций.



Доступ к вершинам


Для работы с позициями вершин интерфейс Direct3DRMMesh предоставляет функции GetVertices() и SetVertices(). Функция GetVertices() предназначена для получения текущей позиции вершины. После получения параметров вершины можно их изменить и переустановить посредством функции SetVertices(). Это рекомендуемая техника модификации формы сетки в критических по времени ситуациях, таких как анимация вершин и морфинг.

Подобно Direct3DRMMeshBuilder, интерфейс Direct3DRMMesh предоставляет функции Scale() и Translate().



Знакомство с Direct3D


В этой главе мы обратим внимание на Direct3D, поговорим об используемых концепциях и терминологии и взглянем на Direct3D API.



Группы граней в сетке


Интерфейс сетки практически целиком предназначен для манипуляций с группами. Группа— это набор граней внутри сетки, которые могут быть обработаны как единая сущность. Для создания и модификации групп используются следующие функции:

AddGroup() GetGroup() GetGroupColor() GetGroupCount() GetGroupMapping() GetGroupMaterial() GetGroupQuality() GetGroupTexture() SetGroupColor() SetGroupColorRGB() SetGroupMapping() SetGroupMaterial() SetGroupQuality() SetGroupTexture()

Использование этих функций не должно вызывать трудностей — достаточно создать одну или несколько групп. Группы создаются функцией AddGroup(), которая требует, чтобы параметры сетки были заданы на уровне вершин. Это значит, что при создании группы вы должны указать местоположение вершин, нормали и координаты текстур. В сетке могут быть созданы одна или несколько групп, причем параметры каждой группы могут быть легко и быстро изменены.



HRESULT


Большинство основных функций DirectX возвращают в качестве кода ошибки значение типа HRESULT. Тип HRESULT представляет собой 32-разрадное значение, индицирующее состояние функции в момент завершения. Direct3D предоставляет ряд констант, используемых при оценке возвращаемого значения. В идеальном случае функции возвращают константу D3DRM_OK, что свидетельствует об успешном завершении. Если при вызове функции возникает ошибка, возвращаемое значение указывает на характер проблемы.




Иерархия фреймов


Сцена Direct3D определяется как иерархия фреймов. Каждая сцена содержит корневой фрейм и произвольное число дочерних фреймов, присоединенных к корневому. Каждый дочерний фрейм может в свою очередь иметь собственные дочерние фреймы. Фреймы представлены интерфейсом Direct3DRMFrame и создаются функцией CreateFrame() интерфейса Direct3DRM.

LPDIRECT3DRMFRAME newframe; d3drm->CreateFrame(parentframe, &newframe);

В приведенном фрагменте кода объявляется указатель на фрейм, а затем он инициализируется функцией CreateFrame(). Переменная parentframe является указателем на фрейм, являющийся родителем нового фрейма. Чтобы создать корневой фрейм для новой сцены, значение этой переменной должно быть равно NULL.

Дочерние фреймы наследуют свои характеристики от родительских. Одной из наследуемых характеристик является система координат. Дочерние фреймы присоединяются к родительскому таким образом, что они следуют за ним — при перемещении родительского фрейма перемещаются и дочерние. Это позволяет создавать сложную анимацию частей объекта. Например, если вы хотите создать и анимировать вертолет (с вращающимися лопастями, разумеется), вы можете создать фрейм для корпуса вертолета, а затем создать дочерний фрейм для лопастей. Для анимации лопастей можно задать вращение для фреймов, к которым привязаны лопасти. Для анимации корпуса вертолета можно перемещать и изменять ориентацию фрейма к которому присоединен корпус. Поскольку фреймы лопастей являются дочерними по отношению к фрейму корпуса, они будут совершать те же перемещения, что и корпус.

В качестве системы отсчета фреймы могут использовать не только свой родительский фрейм. Многие функции позволяют указать, какой фрейм должен использоваться в качестве системы отсчета независимо от отношений «родитель-потомок». Гибкость иерархии фреймов — одна из причин исключительной мощности абстрактного режима Direct3D.



Изменение пути поиска файлов


Другая функция интерфейса Direct3DRM заключается в том, что он позволяет изменить пути поиска, используемые Direct3D для обнаружения файлов. Для получения и изменения пути применяются следующие функции:

AddSearchPath() GetSearchPath() SetSearchPath()

По умолчанию Direct3D устанавливает путь поиска файлов c:\dxsdk\sdk\media. С помощью перечисленных функций вы можете изменить этот путь или добавить другие пути, но изменения будут действовать для вашей программы только во время ее выполнения. Указанный путь не создается на пользовательском компьютере, так что ваша программа не должна зависеть от его существования.

ЗАМЕЧАНИЕ Изменение заданного по умолчанию пути поиска файлов. Заданный по умолчанию путь поиска файлов сохраняется в системном реестре Windows и может быть изменен с помощью редактора системного реестра Windows95 REGEDIT. Вы можете найти путь, отыскав запись реестра D3D Path.



Материалы грани


Внешний вид грани (блестящая, матовая ит.д.) может быть изменен с помощью функций GetMaterial() и SetMaterial(). Мы поговорим о материалах подробнее в разделе, посвященном интерфейсу Direct3DRMMaterial.



Мощность отраженного света


Отраженный свет (specular light)— это свет, который отражается от объекта и создает блики (солнечные зайчики). Параметры бликов влияют на вид объекта. Небольшие, яркие блики заставляют объект казаться блестящим. Большие блики придают объектам вид сделанных из пластика. Маленькие блики или их отсутствие приводят к тому, что объект кажется матовым.

Поведение бликов зависит от мощности отраженного света. Меньшие значения создают большие блики, а большие значения вызывают небольшие блики. Для контроля данного параметра интерфейс материала предоставляет функции GetPower() и SetPower().



Направленный свет


Направленный источник света является противоположностью точечному. Направленный источник света имеет ориентацию, но не имеет местоположения. Он испускает параллельные световые лучи, в связи с чем отсутствует определенное местоположение, откуда эти лучи исходят. Направление параллельных лучей задается вектором направления фрейма, к которому присоединен источник света.

Использование направленных источников света повышает быстродействие по сравнению с точечными источниками света, поэтому направленное освещение полезно при иммитации удаленных источников света.



Отсечение


Порт просмотра управляет передней и задней плоскостями отсечения. Для определения области перед камерой, в которой объекты будут видимы, можно использовать функции SetFront() и SetBack(). Объекты, расположенные за этой областью, не будут визуализироваться. Заданные по умолчанию значения для передней и задней плоскостей отсечения равны 1 и 100 соответственно.




Параллельный свет


Параллельный источник света является вариацией направленного. Параллельный источник света также испускает параллельные световые лучи, но они распространяются не в одном, а в двух противоположных направлениях.

На источник параллельного света оказывает влияние и его местоположение и ориентация. Ориентация устанавливает два направления, в которых распространяется свет, а местоположение задает испускающую свет плоскость.



Параметры анимации


Функции GetOptions() и SetOptions() применяются, чтобы определить поведение анимированных объектов. С их помощью можно задать следующие параметры:

линейная или сплайновая анимация; открытая или закрытая анимация; использование позиций; использование масштабирования и вращения.

Использование линейной анимации означает, что интерфейс анимации перемещает объекты между ключевыми фреймами по кратчайшему расстоянию. Сплайновая анимация использует для вычисления позиции объекта кривые, обеспечивая более плавное движение.

Параметр открытия/закрытия определяет, как объект анимации будет интерпретировать передаваемые функции SetTime() значения времени, которые выходят за заданный диапазон. В закрытой анимации время движется по замкнутому кругу. Это означает, что из выходящего за диапазон значения времени вычитается максимальное значение времени ключа, и закрытая анимация повторяется, даже если значение времени продолжает увеличиваться. В открытой анимации значения времени, выходящие за диапазон, игнорируются. Этот параметр добавлен исключительно для удобства, поскольку открытая анимация может быть повторена посредством перезапуска счетчика времени анимации с нуля.

Параметр использования позиций активизирует позиционные ключи анимации. Когда данный параметр отключен, позиционные ключи не оказывают эффекта. Деактивация позиционных ключей полезна, если необходимо, чтобы анимация управляла масштабированием и вращением объекта, но не его позицией.

Параметр использования масштабирования и вращения управляет активацией ключей масштабирования и вращения в анимации. Когда параметр отключен, ключи масштабирования и вращения не оказывают эффекта. Отключение параметра позволяет вам контролировать масштабирование и вращение объекта, в то время как его позиция определяется объектом анимации.




Параметры визуализации


Устройства могут применяться для изменения параметров визуализации. Например, функции GetQuality() и SetQuality() позволяют задать режим визуализации (Гуро, равномерная закраска и т.д.) используемый устройством при визуализации сцены. Отдельные объекты могут переопределять параметры визуализации только если задаваемая схема визуализации более простая, чем схема, заданная для устройства. По умолчанию для визуализации устанавливается режим равномерной закраски.

Функции GetShades() и SetShades() позволяют контролировать количество оттенков заданного цвета, используемых устройством при визуализации сцены. Параметр часто изменяется в зависимости от глубины цвета используемого видеорежима. По умолчанию используется 32 оттенка, но этого недостаточно для 24- и 32-разрядных видеорежимов. Можно поэкспериментировать с различными значениями параметра (значения должны быть степенями двойки), чтобы определить наилучшее для вашего приложения значение.

Функции GetDither() и SetDither() позволяют включить или выключить передачу полутонов (dithering). Передача полутонов — это техника, позволяющая эмулировать большее количество цветов, чем фактически доступно, и полезная для видеорежимов с малым количеством цветов (обычно 256 или меньше, но и для видеорежимов, которые поддерживают шестьдесят четыре тысячи цветов, эта методика также может быть полезна). По умолчанию передача полутонов разрешена.




Конструктор сеток позволяет манипулировать различными


Конструктор сеток позволяет манипулировать различными прааметрами отображения сеток, такими как цвет, текстуры и режим визуализации. Для этого используются следующие функции:
GetPerspective() GetQuality() GetTextureCoordinates() SetColor() SetColorRGB() SetPerspective() SetQuality() SetTexture() SetTextureCoordinates() SetTextureTopology() Функции SetColor() и SetColorRGB() применяются для назначения цветов граням сеток. Функция GetColor() отсутствует, поскольку нет никакой гарантии, что все грани сетки будут иметь один и тот же цвет.
Функции GetQuality() и SetQuality() применяются для установки режима визуализации сетки (каркасный, равномерная закраска, метод Гуро ит.д.). Однако, имеется одно ограничение: Direct3D изменит режим визуализации конструктора сеток, если параметры устройства, на котором сетка будут отображаться, настроены на более простой режим визуализации. Например, если параметры устройства настроены на использование каркасного режима, все конструкторы сеток, использующие равномерную закраску или метод Гуро, будут отображаться в каркасном режиме.
Функция SetTexture() назначает конструктору сеток указанную текстуру. С помощью функций GetTextureCoordinates(), SetTextureCoordinates() и SetTextureTopology() задаются атрибуты текстуры. Обычно вместо этих функций предпочтительнее использовать наложение текстуры, обсуждаемое далее в этой главе.
Функции GetPerspective() и SetPerspective() применяются для включения и отключения перспективной коррекции текстур. Перспективная коррекция текстур гарантирует, что текстуры корректно отображаются в соответствии с местоположением и ориентацией зрителя, но требует дополнительных вычислений. В общем случае коррекция перспективы необходима для текстур, наносимых на большие грани расположенные близко к зрителю. Для удаленных от зрителя сеток коррекция может быть отключена. Если во время анимации текстуры начинают скользить и перемещаться по граням сетки — настало время включить перспективную коррекцию.

Перемещение фреймов


Интерфейс фрейма предоставляет функции для пошаговой корректировки позиции фрейма. Эти функции задают атрибуты движения, которые будут применяться к фрейму при каждом обновлении сцены.

Функции GetRotation() и SetRotation() используются для управления атрибутами вращения фрейма. Вращение, заданное функцией SetRotation(), оказывает эффект при каждом обновлении сцены.



Перемещение и функции обратного вызова


Возможность размещать фреймы и назначать атрибуты движения очень важна, но ее недостаточно. Интерактивная графика требует, чтобы объекты в сцене могли взаимодействовать друг с другом и реагировать на действия пользователя. Интерфейс фрейма позволяет осуществлять коррекцию во время выполнения с помощью функций обратного вызова. Функции обратного вызова (callback) — это написанные вами функции, которые устанавливаются, или регистрируются в Direct3D. После регистрации Direct3D будет выполнять функцию обратного вызова всякий раз, когда рисуется новая сцена, что позволяет вам внести последние изменения в объекты сцены.

Функции обратного вызова устанавливаются с помощью функции AddMoveCallback(). Каждый объект фрейма может установить несколько функций обратного вызова и эти функции будут вызываться в порядке установки. Чтобы удалить функцию обратного вызова, используйте функцию DeleteMoveCallback().




Перемещение и масштабирование


Местоположение объектов определяется фреймами, но можно определить расположение сетки относительно присоединенного фрейма. Функция конструктора сеток Translate() позволяет задать смещение местоположения сетки. Благодаря этому можно присоединить к одному фрейму несколько сеток так, чтобы они не занимали одно и то же пространство.

Функция Scale() задает набор коэффициентов масштабирования для сетки. Масштабирование осуществляется в локальной системе координат сетки, как если бы центр сетки находился в начале координат. Можно задавать различные коэффициенты масштабирования для каждой из осей, чтобы сетка растягивалась и сжималась.



Поле зрения


Параметры поля зрения (field-of-view, FOV) могут настраиваться посредством функции SetField(). Значение FOV по умолчанию равно 0.5. Меньшие значения сужают угол зрения, подобно длиннофокусному объективу. Большие значения увеличивают угол зрения, имитируя эффект широкоугольного объектива. Отрицательные значения не допускаются.



Позиционирование фреймов


Интерфейс Direct3DRMFrame предоставляет ряд функций, используемых для позиционирования фреймов. К их числу относятся:

AddRotation() AddScale() AddTranslation() GetOrientation() GetPosition() LookAt() SetOrientation() SetPosition()

Функции GetPosition() и SetPosition() позволяют получить или задать местоположение фрейма. Аналогично, функции GetOrientation() и SetOrientation() позволяют задать ориентацию фрейма. Корме того, интерфейс предоставляет функцию LookAt() которая ориентирует фрейм, чтобы он был направлен (указывал) на другой фрейм. Функция LookAt() удобна в ситуации, когда камера или источник света следуют за другим объектом.

Функции SetPosition(), SetOrientation() и LookAt() устанавливают новые параметры объекта фрейма независимо от предыдущих. Кроме них интерфейс фрейма предоставляет функции AddTranslation(), AddRotation() и AddScale(), которые корректируют параметры фрейма, а не заменяют их. Функция AddTranslation() корректирует местоположение фрейма, согласно указанному перемещению. AddRotation() корректирует ориентацию фрейма, добавляя новое вращение к существующему. Функция AddScale() изменяет размеры фрейма относительно текущего размера.



Производительность


Благодаря предоставляемым мощности и простоте использования интерфейса Direct3DRMMeshBuilder, конструкторы сеток являются оптимальным выбором для большинства задач. Однако в некоторых ситуациях применение интерфейса конструктора сеток может привести к снижению производительности. Если вы используете конструктор сетки для загрузки данных, настройки параметров и размещения полученной сетки в сцене, не предусматривающей частого изменения параметров, применение интерфейса конструктора сеток будет оптимальным вариантом. Однако, если параметры сетки (цвет, текстуры, позиции вершин и т.д.) будут часто изменяться во время выполнения, конструктор сеток снизит производительность вашего приложения. Чуть позже мы обсудим альтернативные варианты работы с сетками.




Рассеяный свет


Рассеяный свет является самым простым типом источника света, поскольку имеет всего один параметр: цвет. Хотя источник рассеяного света и должен быть перед помещением в сцену присоединен к фрейму, он игнорирует местоположение и ориентацию фрейма. Поэтому источник рассеяного света может быть присоединен к любому фрейму сцены.

В сцене может быть любое количество источников рассеяного света. Получаемое в результате освещение будет определяться суммой параметров всех источников рассеяного света. Например, добавление в сцену трех источников рассеяного света с красным, зеленым и синим цветом, аналогично добавлению единственного источника рассеяного света с белым цветом.



Создание ключей


Интерфейс Direct3DRMAnimation позволяет конструировать анимационные последовательности на основе ключей (keys). Каждый ключ представляет собой коэффициенты перемещения, вращения или масштабирования, применяемые к объекту в заданной точке анимации. Затем интерфейс анимации может выполнить анимацию целиком, основываясь на нескольких ключах и автоматически вычисляя параметры объекта между ключевыми кадрами.

Для создания ключевых кадров в интерфейсе анимации применяются следующие функции:

AddPositionKey() AddRotateKey() AddScaleKey()

Каждая функция добавления ключа требует указания времени и преобразования. Время определяет момент анимации, в который ключ окажет действие. Преобразование — это позиционирование, поворот или масштабирование, которое должно произойти в ключевом кадре. Общая длина анимации определяется ключом с самым большим значением времени. Для удаления ключей из анимации применяется функция DeleteKey().



Создание объектов Direct3D


Главная цель интерфейса Direct3DRM — создание других объектов Direct3D. Большинство функций интерфейса Direct3DRM имеют префикс «Create» (создание). Функции, создающие объекты, перечислены ниже:

CreateAnimation() CreateAnimationSet() CreateDeviceFromClipper() CreateDeviceFromD3D() CreateDeviceFromSurface() CreateFace() CreateFrame() CreateLight() CreateLightRGB() CreateMaterial() CreateMesh() CreateMeshBuilder() CreateObject() CreateUserVisual() CreateShadow() CreateTexture() CreateTextureFromSurface() LoadTexture() CreateViewport() CreateWrap()

Обычно нет необходимости использовать все эти функции. Некоторые функции практически идентичны. Например, единственное различие между функциями CreateLight() и CreateLightRGB() состоит в том, каким образом задан цвет освещения.

Поскольку интерфейс Direct3DRM необходим для создания других объектов Direct3D, обычно программа создает объект Direct3DRM в первую очередь.



Создание сеток посредством конструктора сеток


Для создания экземпляра интерфейса Direct3DRMMesh может применяться конструктор сеток. Обычно конструктор сеток используется для загрузки сетки с диска, назначения цветов и текстур, настройки граней, вершин и нормалей. Затем функция CreateMesh() интерфейса Direct3DRMMeshBuilder используется для создания объекта Direct3DRMMesh. Эта техника удобна, но в результате все грани сетки будут принадлежать одной группе. Для создания сетки с несколькими группами необходимо применять функцию AddGroup().




Создание текстур


Простейший способ создания текстуры— использование функции LoadTexture() интерфейса Direct3DRM:

LPDIRECT3DRM texture; d3drm->LoadTexture("texture.bmp", &texture);

Функция LoadTexture() получает в качестве аргумента имя файла BMP или PPM и использует растровое изображение из файла для создания текстуры.

Также текстуры могут быть загружены из ресурсов программы с помощью функции LoadTextureFromResource(), как показано в следующем примере:

LPDIRECT3DRMTEXTURE texture; HRSRC id = FindResource(NULL, MAKEINTRESOURCE(IDR_SAMPLETEXTURE), "TEXTURE"); d3drm->LoadTextureFromResource(id, &texture);

Функция LoadTextureFromResource() интерфейса Direct3DRM получает в качестве параметра идентификатор ресурса и создает текстуру из ресурса, определяемого значением переменной id.

Для внутреннего представления текстур в Direct3D применяются поверхности DirectDraw. Функция LoadTextureFromSurface() позволяет использовать в качестве текстуры существующую поверхность DirectDraw.



Текстуры граней


Для присоединения текстур к граням используются следующие функции интерфейса Direct3DRMFace:

GetTexture() GetTextureCoordinateIndex() GetTextureCoordinates() GetTextureTopology() SetTexture() SetTextureCoordinates() SetTextureTopology()

Более подробно мы поговорим о текстурах во время обсуждения интерфейса Direct3DRMTexture.



Типы данных Direct3D


Direct3D определяет несколько типов данных, которые несомненно будут снова и снова применяться в ваших программах. В данном разделе мы обсудим эти типы данных.



Точечный источник света


Точечный источник света испускает лучи во всех направлениях, поэтому его ориентация не имееет значения. Местоположение точечного источника света определяет точку, из которой будут испускаться световые лучи.



Управление скоростью обновления


Кроме всего прочего, объект Direct3DRM предоставляет функцию Tick(), которая управляет скоростью выполнения программы. Каждый раз, когда вы вызываете функцию Tick(), Direct3D обновляет анимированные элементы сцены и визуализирует результат. Более частые вызовы Tick() приводят к более частому обновлению сцены; если функция Tick() вызывается редко, программа замедляется. Функция Tick() получает единственный параметр, контролирующий скорость анимации сцены. В большинстве ситуаций достаточно задать значение 1.0, но, задавая во время выполнения другие значения, можно управлять скоростью работы программы.




Установка времени в анимации


Для установки текущей позиции в созданной анимации применяется функция SetTime(). Передаваемые функции SetTime() значения зависят от значений, применявшихся при зоздании ключевых кадров.

Значения времени представляются числами с плавающей запятой, так что ключи могут быть установлены в любом месте анимации, даже если общая длина анимации равна 1. Это также позволяет воспроизводить анимацию в замедленном или ускоренном темпе, передавая малые или большие приращения функции SetTime().

Поскольку функции SetTime() могут передаваться любые значения, анимация может быть остановлена, запущена снова, ускорена, замедлена или даже воспроизведена в обратном порядке.



Установка времени в анимационных наборах


Аналогично интерфейсу Direct3DRMAnimation, интерфейс Direct3DRMAnimationSet предоставляет функцию SetTime(). В случае анимационного набора функция SetTime() устанавливает время для каждой анимации, входящей в набор.




Вершины грани


Параметрами вершин можно манипулировать с помощью следующих функций интерфейса Direct3DRMFace:

AddVertex() GetVertex() GetVertexCount() GetVertexIndex() GetVertices()

Возможность добавления вершин к грани позволяет создавать вогнутые грани. Здесь таится опасность, так как выполняющая визуализацию подсистема Direct3D не может рисовать вогнутые грани (или даже грани, которые имеют больше трех вершин). К счастью, абстрактный режим Direct3D автоматически делит грани на треугольники.




X-файлы


X-файлы являются родным форматом файлов Direct3D. Х-файлы могут хранить множество сеток, иерархию фреймов и полные анимации. Текстуры не могут храниться в X-файлах.

В DirectX2, Direct3D поддерживал только текстовые версии X-файлов. DirectX 3 и следующие версии поддерживают как текстовый, так и двоичный формат.

Текстовые X-файлы обычно больше по размеру и дольше загружаются, чем двоичные, но их легче просмотреть и отредактировать.

X-файлы могут быть созданы утилитой CONV3DS или программой Direct3D с помощью функции Save() интерфейса Direct3DRMMeshbuilder. Посредством функции Save() можно создать только X-файлы содержащие сетки.

СОВЕТ Ограничения конструктора сеток. Если вы добавляете к конструктору сеток иерархию фреймов, а затем вызываете функцию Save(), полученный X-файл будет содержать все объекты иерархии, но как части одной сетки, а иерархия фреймов будет утеряна.



Загрузка анимационных наборов


Анимационные наборы загружаются функцией Load() интерфейса Direct3DRMAnimationSet. Имя файла, передаваемое функции Load(), должно указывать на файл, содержащий завершенную анимированную сцену. Подобно другим функциям загрузки в Direct3D, функция Load() может выполнять чтение из файла, из ресурсов программы или из памяти.

Отдельные объекты анимации могут быть добавлены в анимационный набор или удалены из него с помощью функций AddAnimation() и DeleteAnimation().



Загрузка и сохранение


Функция Load() позволяет объектам конструктора сеток загружать сетки с диска, из ресурсов программы либо из памяти. Кроме того, функция Load() загружает любые назначенные сетке текстуры, если местоположение текстур указано в путях поиска Direct3D.

Функция Load() дает возможность выполнять функцию обратного вызова каждый раз при загрузке текстуры. Это позволяет изменять заданную по умолчанию загрузку текстуры и получать текстуры из заданных каталогов или из ресурсов программы.

Функция конструктора сеток Save() позволяет сохранить сетку как текстовый, двоичный или сжатый файл.



когда вы знаете, что представляют


Теперь, когда вы знаете, что представляют собой интерфейсы Direct3D и что они делают, можно приниматься за более веселое занятие — программирование. В главе 4 мы обсудим код приложения Direct3D.

Зональное освещение


Зональный источник света, или прожектор (spotlight), испускает свет в форме конуса. При этом используется местоположение фрейма для определения точки испускания света (вершины конуса) и ориентация фрейма для определения направления светового потока.

Излучаемый источником свет описывается двумя углами: углом светового пятна (umbra angle) и углом зоны освещенности (penumbra angle). Угол светового пятна определяет конус, в котором свет имеет максимальную интенсивность. Угол зоны освещенности описывает больший конус, который определяет границу освещенной области. Между двумя этими конусами освещенность постепенно изменется от цвета источника света до черного (отсутствие света).

Угол светового пятна и угол зоны освещенности могут быть установлены с помощью функций SetUmbra() и SetPenumbra() интерфейса Direct3DRMLight.