Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
DirectX. Продвинутая Анимация (2004) [rus].pdf
Скачиваний:
335
Добавлен:
16.08.2013
Размер:
8.39 Mб
Скачать

164

Глава 5

Последним является код для считывания массива ключей преобразования.

case 4: // Матрица преобразования delete [] Anim->m_MatrixKeys; Anim->m_NumMatrixKeys= NumKeys;

Anim->m_MatrixKeys= new cAnimationMatrixKey[NumKeys]; for(i=0;i<NumKeys;i++) {

// Получить время Anim->m_MatrixKeys[i].m_Time=*DataPtr++; if(Anim->m_MatrixKeys[i].m_Time> \

m_AnimationSets->m_Length) m_AnimationSets->m_Length = \

Anim->m_MatrixKeys[i].m_Time;

//Пропустить количество далее следующих ключей (должно быть 16) DataPtr++;

//Получить значения матриц

D3DXMATRIX *mPtr = (D3DXMATRIX *)DataPtr; Anim->m_MatrixKeys[i].m_matKey = *mPtr; DataPtr += 16;

}

break;

}

}

Хорошо, передохните немного и давайте посмотрим, чего мы достигли. Пока что мы обработали каждый объект AnimationSet, Animation и AnimationKey (не беря во внимание ссылочный объект Frame, который содержит названия костей) и загрузили объекты ключей, содержащие данные анимации. Вы почти готовы начать анимирование!

Почти является правильным словом; остался один небольшой шаг - прикрепление объектов анимации к соответствующим им объектам костей.

Прикрепление анимации к костям

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

В данном примере иерархия костей будет представлена иерархией D3DXFRAME. Если вы используете DirectX 8, то могли заметить, что не можете использовать объект D3DXFRAME; его структура определена в DirectX 9. Не расстраивайтесь; вспомогательный код Direct3D, используемый во всех демонстрационных программах этой книги, компенсирует недостающую структуру наличием ложной версии D3DXFRAME,

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

которую вы можете использовать. Вы можете найти поддельную версию структуры D3DXFRAME в файле Direct3D.h, находящемся в директории этой главы компактдиска.

Структура D3DXFRAME использует два связанных списка указателей, которые применяются для создания иерархии. Из корневой структуры D3DXFRAME вы можете получать доступ к дочерним объектам, используя указатель D3DXFRAME::pFrameFirstChild, и к родственным объектам, используя указатель D3DXFRAME::pFrameSibling.

Следующая функция в классе cAnimationCollection, на которую вам необходимо обратить внимание, - Map. Используйте функцию Map для прикрепления указателя m_Bone анимационной структуры к фрейму, имеющему в иерархии фреймов то же самое имя.

Функция Map просматривает все объекты cAnimationSet и находящиеся в них объекты cAnimation. Название каждого объекта cAnimation сравнивается с названием каждого фрейма; если найдено совпадение, в указатель cAnimation::m_Bone устанавливается адрес фрейма.

Функция Map имеет в качестве параметра корневой фрейм иерархии.

void cAnimationCollection::Map(D3DXFRAME *RootFrame)

{

// Просмотреть все наборы анимаций cAnimationSet *AnimSet = m_AnimationSets; while(AnimSet != NULL) {

// Просмотреть все объекты анимаций cAnimation *Anim = AnimSet->m_Animations; while(Anim != NULL) {

//Просмотреть все фреймы в поисках совпадения Anim->m_Bone = FindFrame(RootFrame, Anim->m_Name);

//Перейти к следующему объекту анимации

Anim = Anim->m_Next;

}

// Перейти к следующему объекту набора анимаций AnimSet = AnimSet->m_Next;

}

}

Вто время как функция Map только просматривает все объекты cAnimationSet

иcAnimation, функция FindFrame рекурсивно обрабатывает иерархию фреймов в поисках соответствия заданному имени. Когда такое имя найдено, функция FindFrame возвращает указатель на найденный фрейм. Посмотрите на код FindFrame, от которого зависит функция Map.

166

D3DXFRAME *cAnimationCollection::FindFrame(D3DXFRAME *Frame, char *Name)

{

D3DXFRAME *FramePtr;

//Если нет фрейма, вернуть NULL if(!Frame)

return NULL;

//Вернуть текущий фрейм, если имя не задано if(!Name)

return Frame;

//Обработать дочерние фреймы

if((FramePtr = FindFrame(Frame->pFrameFirstChild, Name))) return FramePtr;

// Обработать родственные фреймы

if((FramePtr = FindFrame(Frame->pFrameSibling, Name))) return FramePtr;

// Ничего не найдено return NULL;

}

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

Обновление анимации

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

Вернувшись к классу cAnimationCollection, вы можете увидеть, что всего одна функция выполнит все это за вас. Предоставив функции cAnimationCollection::Update в качестве параметра название используемого набора анимаций и время в анимации, все матрицы преобразования во всей иерархии прикрепленных костей будут установлены и готовы к визуализации.

Посмотрите на функцию Update, чтобы иметь представление о том, как обновлять данные анимации.

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

void cAnimationCollection::Update(char *AnimationSetName, \ DWORD Time)

{

cAnimationSet *AnimSet = m_AnimationSets; DWORD i, Key, Key2;

// Искать совпадающее название набора анимации, если установлено if(AnimationSetName) {

// Искать совпадающее название набора анимации while(AnimSet != NULL) {

//Прекратить, если совпадение найдено if(!stricmp(AnimSet->m_Name, AnimationSetName)) break;

//Перейти к следующему объекту набора анимаций AnimSet = AnimSet->m_Next;

}

}

// Вернуть, если набор не был найден if(AnimSet == NULL)

return;

Функция Update начинает работу с просмотра наборов анимаций, загруженных в связанный список. Если вы установите значение NULL в качестве AnimationSetName, Update просто будет использовать первый набор анимаций в списке (который обычно является последним загруженным). Если при использовании заданного названия не было найдено совпадений, функция без промедления прекращает работу.

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

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

Вы уже видели, как просматривать список ключей для поиска тех, между которыми находится заданное время, так что я пропущу этот код. Смотрите его на компакт-диске книги; для получения дополнительной информации о демонстрационной программе BoneAnim читайте конец главы.

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

168

Глава5

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

Получение скелетныхданных меша из альтернативных источников

Формат файла Microsoft .X является не единственным, используемым для хранения данных мешей и анимаций. Есть еще два формата, сравнимые с ним по простоте использования, которые являются замечательными для хранения данных мешей и анимаций, - форматы chUmbaLum sOft's Milkshape 3D .MS3D и id Software's Quake 2 .MD2.

Формат файла Milkshape .MS3D похож на двоичный .X, за исключением того, что файл .MD3D хранит только один меш и иерархию костей. На самом деле, формат .MS3D является очень простым, т. к. не использует шаблоны; вместо этого в файле хранится заранее определенная последовательность структур.

Формат файла Quake 2 .MD2 является простым набором мешей, помещенных в один файл. Каждый меш представляет собой один кадр анимации из последовательности ее наборов. В то время как файлы .MS3D содержат скелетные анимации, формат .MD2 содержит только наборы морфируемых анимаций.

Замечание. Морфированная анимация мешей является еще одной привлекательной темой, освещенной в книге, так что я просто указал на двойственность программы MeshConv.Пока что просто игнорируйте любыеупоминания морфированной анимации и вернитесь к теме: преобразование наборов скелетных анимаций, основанных на ключевых кадрах из .MS3D в .X.

Итак, для скелетных анимаций вы можете использовать файлы .MS3D, а для морфируемых анимаций .MD2. Как же конкретно их использовать? Существует множество информации об этих форматах. Посмотрите книжку Focus On 3D Models (Premier Press, 2002) или веб-сайты http://www.gamedev.net или http://nehe.gamedev.net.

Компакт-диск содержит программу MeshConv, которую вы можете использовать для преобразования файлов .MS3D и .MD2 в .X. После запуска программы вы увидите диалоговое окно MeshConv, показанное на рис. 5.2.

Не дайте неказистости кнопок в программе MeshConv напугать вас - она конвертирует все файлы .MS3D и .MD2 files в .X, используя шаблоны, виденные вами в этой главе. Файлы .MS3D сохраняются, используя иерархию фреймов и один объект AnimationSet, в то время как файлы .MD2 сохраняются, используя набор объектов Mesh и MorphAnimationSet, которые хранят названия мешей, используемых для морфированной анимации.

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

Рис. 5.2. Диалоговое окно MeshConv содержит две кнопки, щелкнув на которые вы можете преобразовать файлы .MS3D и .MD2 в .X

Замечание. На компакт-диске содержится полностью комментированный исходный код программы MeshConv. Читайте конец этой главы, чтобы подробнее узнать о программах и их местоположениях.

Для преобразования файла (.MS3D или .MD2) в .X файл щелкните по соответствующей кнопке в диалоговом окне MeshConv. Появится диалоговое окно "Open File". Это диалоговое окно позволяет вам перемещаться по директориям для указания расположения конвертируемого файла. Выберете необходимый для конвертации файл и нажмите "Open".

Появится диалоговое окно "Save .X File". Вы можете использовать его для указания имени и положения файла, в котором вы хотите сохранить данные мешей и анимации. Введите имя файла и нажмите "Save". Через некоторое время вы должны увидеть окно сообщений, говорящее о том, что преобразование было выполнено успешно.

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

Для морфируемых анимаций (из .MD2) используется последовательность объектов Mesh, содержащих все цели морфирования меша из исходного файла. Всего один объект MorphAnimationSet поможет вам загрузить данные анимации в ваш проект, используя ранее изученные классы и технологии.

В качестве примера работы с конвертированным, при использовании программы MeshConv, .X файлом смотрите демонстрационные программы, включенные в эту главу. Вы правильно поняли - программы BoneAnim и MorphAnim используют конвертированные файлы .MS3D и .MD2 для иллюстрирования скелетной и морфируемой анимации. Посмотрите их и получайте удовольствие!

Соседние файлы в предмете Программирование на C++