Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Programming / GameProg / RPG_Programming_2ed.pdf
Скачиваний:
243
Добавлен:
12.02.2016
Размер:
12.06 Mб
Скачать

Джим Адамс

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

// g_pD3DDevice

= ранее

инициализированный объект устройства

//

pD3DXMesh

= ранее

загруженный объект ID3DXMesh

//

matWorld

= матрица мирового преобразования сетки

// Начало сцены if(SUCCEEDED(g_pD3DDevice->BeginScene())) {

//Устанавливаем матрицу мирового преобразования сетки g_pD3DDevice->SetTransform(D3DTS_WORLD, &matWorld);

//Перебираем в цикле каждый материал в сетке for(DWORD i = 0; i < g_dwNumMaterials; i++) {

//Устанавливаем материал и текстуру

g_pD3DDevice->SetMaterial(&g_pMaterialList[i]); g_pD3DDevice->SetTexture(0, g_pTextureList[i]);

// Рисуем подгруппу сетки pD3DXMesh->DrawSubset(i);

}

// Завершение сцены g_pD3DDevice->EndScene();

}

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

Скелетные сетки

Одна из самых захватывающих возможностей Direct3D — скелетные сетки. Как я уже упоминал, скелетные сетки могут динамически деформироваться. Это достигается путем подсоединения отдельных вершин сетки к структуре лежащих в основе «костей» или иерархии фреймов. Скелетные сетки используют кости для определения своей формы; при перемещении костей сетка соответствующим образом деформируется.

Кости представляются как иерархия фреймов внутри X-файла. При моделировании сетки вы выстраиваете фреймы в структуру «предок– потомок». Когда изменяется ориентация родительского фрейма, присоединенные к нему дочерние фреймы наследуют родительское преобразование и комбинируют его со своими собственными преобразованиями. Это упрощает анимацию — вы перемещаете

netlib.narod.ru

155

Глава 2. Рисование с DirectX Graphics

единственный фрейм и все, присоединенные к нему фреймы перемещаются следом.

Для загрузки и использования скелетных сеток вы имеете дело непосредственно с объектами данных X-файла, как это делалось ранее в разделе «Разбор X-файлов». (Я же говорил вам, что этот код еще пригодится.) Для разбора объектов вам потребуется управлять списком фреймов (и их иерархией).

Загрузка скелетных сеток

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

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

данных сетки из X-файла, созданию содержащего сетку объекта ID3DXMesh и созданию объекта ID3DXSkinInfo, описывающего

соединение костей и вершин, что необходимо для деформации сетки.

Поскольку код для разбора иерархии фреймов и загрузки сеток достаточно сложен, он приводится на сопроводительном CD-ROM к этой книге (в папке \BookCode\Chap02\XFile). Я слышу ваши вздохи, но не волнуйтесь — код хорошо прокомментирован и я прямо сейчас уделю время его исследованию. Сперва вы находите несколько структур, содержащих иерархию фреймов (заполненную матрицами преобразования фреймов) и сетки.

Функция LoadMesh использует слегка модифицированную версию

показанной ранее (в разделе «Разбор X-файлов») функции разбора. Объекты данных фреймов, после того, как они перечислены в функции LoadFile,

добавляются к иерархии фреймов. Затем перечисляются другие объекты, находящиеся внутри объектов фреймов, обеспечивая иерархию наборами дочерних объектов.

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

добавляется к связанному списку сеток. Фреймы содержат указатели на сетки, так что вы можете использовать одну и ту же сетку несколько раз (используя обращение по ссылке).

После того, как сетка загружена, функция загрузки сопоставляет кости сетки с соответствующими им фреймами и загружает материалы сетки.

Чтобы загрузить скелетную сетку или набор сеток, вызовите функцию LoadMesh, передав ей имя X-файла. В свою очередь, LoadFile вызывает функцию ParseXFile. Затем, после возврата из функции LoadFile, вы

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

156

netlib.narod.ru

Джим Адамс

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

Абсолютно верно, для использования скелетной сетки вам необходимо создать два контейнера сеток. Первая сетка — это та, которая загружена из

X-файла. Это всего лишь стандартная сетка, использующая объект ID3DXMesh для хранения своих данных. Ваша задача сейчас —

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

Для создания клонированной сетки, вызовите функцию объекта сетки

CloneMeshFVF:

HRESULT ID3DXMesh::CloneMeshFVF(

// Параметры сетки (установите 0)

DWORD

Options,

DWORD

FVF,

// Новый FVF

LPDIRECT3DDEVICE9

pDevice,

// Устройство для создания сетки

LPD3DXMESH

*ppCloneMesh);

// Новый объект сетки

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

// pMesh = объект ID3DXMesh, загруженный из X-файла

ID3DXMesh *pSkinMesh = NULL;

pMesh->CloneMeshFVF(0, pMesh->GetFvF(), pD3DDevice, &pSkinMesh);

Теперь, когда у вас есть второй контейнер сетки (объект скелетной сетки), вы можете начать изменять структуру костей скелетной сетки, обновлять секту и визуализировать результат на экране!

Обновление и визуализация скелетной сетки

Чтобы модифицировать преобразования костей, вы создаете массив объектов D3DXMATRIX (по одной матрице для кости). Так, если в вашей скелетной сетке используется 10 костей, то вам необходимо 10 объектов D3DXMATRIX

для хранения преобразований каждой кости.

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

Когда вы закончите играться с преобразованиями, можно обновить вершины скелетной сетки и визуализировать сетку. Для обновления скелетной сетки вам необходимо заблокировать буфер вершин исходной сетки и буфер вершин скелетной сетки (созданного вами клона сетки):

void *Src, *Dest; pMesh->LockVertexBuffer(0, (void**)&Src);

pSkinnedMesh->LockVertexBuffer(0, (void**)&Dest);

netlib.narod.ru

157

Соседние файлы в папке GameProg