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

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

зовать MyMesh2 в качестве исходного меша и MyMesh3 в качестве целевого меша в морфируемой анимации. Значение скаляра, необходимого для морфинга, вычисляется на основе значений времени ключей.

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

Загрузка данных морфируемой анимации

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

class cMorphAnimationKey

{

public:

DWORD m_Time; // Время ключа

char *m_MeshName; // Имя используемого меша D3DXMESHCONTAINER_EX *m_MeshPtr; // Указатель на данные меша

public:

cMorphAnimationKey()

{

m_MeshName = NULL;

m_MeshPtr = NULL;

}

~cMorphAnimationKey()

{

delete [] m_MeshName; m_MeshName = NULL; m_MeshPtr = NULL;

}

};

class cMorphAnimationSet

{

public:

char *m Name; // Название анимации

DWORD m_Length; // Длительность анимации

cMorphAnimationSet *m_Next; // Следующая анимация в связанном списке

DWORD m_NumKeys; // # ключей анимации cMorphAnimationKey *m_Keys; // массив ключей

public:

cMorphAnimationSet()

{

266

m_Name = NULL; m_Length = 0; m_Next = NULL; m_NumKeys = 0; m_Keys = NULL;

}

~cMorphAnimationSet()

{

delete [] m_Name; m_Name = NULL; m_Length = 0;

m_NumKeys = 0;

delete [] m_Keys; m_Keys = NULL; delete m_Next; m_Next = NULL;

}

};

class cMorphAnimationCollection : public cXParser

{

protected:

DWORD m_NumAnimationSets; // # наборов анимаций cMorphAnimationSet *m_AnimationSets; // наборы анимаций

protected:

Анализировать .Х файл, искать данные пружин и масс BOOL ParseObject(IDirectXFileData *pDataObj,

IDirectXFileData *pParentDataObj, DWORD Depth,

void **Data, BOOL Reference);

public:

cMorphAnimationCollection()

{

m_NumAnimationSets = 0; m_AnimationSets = NULL;

}

~cMorphAnimationCollection() { Free(); }

BOOL Load(char *Filename); void Free();

void Map(D3DXMESHCONTAINER_EX *RootMesh); void Update(char *AnimationSetName, \

DWORD Time, BOOL Loop, \ D3DXMESHC0NTAINER_EX **ppSource, \ D3DXMESHCONTAINER_EX **ppTarget, \ float *Scalar);

};

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

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

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

Этот список объектов наборов анимации хранится в виде связанного списка, к которому вы получаете доступ при помощи указателя cMorphAnimationSet::m_Next. (Один набор анимации указывает на следующий набор в списке.) Весь список объектов наборов анимации хранится в объекте cMorphAnimationCollection, который содержит только указатель на корневой объект набора анимации. Для получения доступа к любому объекту набора анимации вам необходимо просмотреть все объекты наборов анимации в поисках заданного.

Вы должны быть знакомы с членами объекта cMorphAnimationSet (за исключением переменной m_Length, которая содержит длительность анимации, определяемой временем последнего ключа в массиве объектов cMorphAnimationKey). Вместо того чтобы просматривать весь массив ключей, для определения длительности анимации будет использоваться m_Length.

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

Для загрузки анимаций морфируемого меша вам необходимо унаследовать класс cMorphAnimationSet от cXParser, разработанного в главе 3. Наследование от класса cXParser предоставляет вам возможность получать доступ к функции ParseObject, которую вы будете использовать для получения данных анимации из объекта MorphAnimationSet.

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

В ближайшем рассмотрении конструктор, деструктор, Load и Free являются тривиальными функциями; я предоставляю вам возможность посмотреть самим на их код. Однако вас может заинтересовать код функции ParseObject. В принципе, необхо-

268

димо, чтобы функция ParseObject искала экземпляры объектов MorphAnimationSet и создавала объекты cMorphAnimationSet, содержащие данные анимации. Это может быть реализовано посредством следующего кода:

BOOL cMorphAnimationCollection::ParseObject( \ IDirectXFileData *pDataObj, \ IDirectXFileData *pParentDataObj, \ DWORD Depth, \

void **Data, BOOL Reference)

{

const GUID *Type = GetObjectGUID(pDataObj);

// Прочитать данные набора анимации if(*Туре == MorphAnimationSet) {

//Создать и привязать объект cMorphAnimationSet cMorphAnimationSet *AnimSet = new cMorphAnimationSet(); AnimSet->m_Next = m_AnimationSets;

m_AnimationSets = AnimSet;

//Увеличить # наборов анимации

m_NumAnimationSets++;

// Установить имя набора анимации AnimSet->m_Name = GetObjectName(pDataObj);

// Получить указатель на данные

DWORD *Ptr = (DWORD*)GetObjectData(pDataObj, NULL);

// Получить # ключей и создать массив объектов ключевых кадров AnimSet->m_NumKeys = *Ptr++;

AnimSet->m_Keys = new cMorphAnimationKey[AnimSet->m_NumKeys];

// Получить данные ключа - время и имя меша for(DWORD i=0;i<AnimSet->m_NumKeys;i++) { AnimSet->m_Keys[i].m_Time = *Ptr++;

AnimSet->m_Keys[i].m_MeshName = strdup((char*)*Ptr++);

}

/ Сохранить длительность анимации

AnimSet->m_Length = AnimSet->m_Keys[AnimSet->m_NumKeys-1].m_Time;

}

return ParseChildObjects(pDataObj, Depth, Data, Reference);

}

Единственным критическим местом в функции cMorphAnimationCollection::ParseObject является загрузка объекта набора морфируемых анимаций. После создания экземпляра объекта cMorphAnimationSet и привязывания его в связанный список объектов вам необходимо считать количество ключей, используемых в ани-

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

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

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

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

void cMorphAnimationCollection::Map( \ D3DXMESHCONTAINER_EX *RootMesh)

{

//Проверка ошибок if(!RootMesh)

return;

//Перебрать все анимации

cMorphAnimationSet *AnimSet = m_AnimationSets; while(AnimSet != NULL) {

//Перебрать все ключи в наборе анимаций и сопоставить меши

//указателю на меш ключа

if(AnimSet->m_NumKeys) {

for (DWORD i=0;i<AnimSet->m_NumKeys;i++) AnimSet->m_Keys[i].m_MeshPtr = \

RootMesh->Find(AnimSet->m_Keys[i].m_MeshName);

}

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

}

}

В функции Map я использовал функцию D3DXMESHCONTAINER_EX::Find для перебора всех мешей, содержащихся в объекте, и поиска заданного имени меша. Если такой меш найден, указатель на него сохраняется в объекте ключа.

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

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