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

270

Глава 9

Визуализации морфированного меша

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

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

void cMorphAnimationCollection::Update( \ char *AnimationSetName, \

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

Хотя функция Update и кажется большой, на самом деле она очень проста в использовании. В качестве параметра AnimationSetName вам необходимо указать имя используемого набора анимации, в качестве параметра Time указать время анимации и повторять ли ее циклически или нет (установите Loop в TRUE или FALSE).

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

Функция Update начинается с получения указателя на связанный список набора анимаций и очищения указателей, переданных функции.

{

cMorphAnimationSet *AnimSet = m_AnimationSets; // Очистить возвращаемые значения

*ppSource = NULL; *ppTarget = NULL; *Scalar = 0.0f;

Указатели очищаются на случай возникновения ошибки. Если возникает ошибка, вы можете проверить, установлены ли указатели в NULL. Если они имеют значение отличное от NULL, то это означает, что функция Update отработала корректно.

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

Двигаясь дальше в функции, вы просматривает список наборов анимаций в поисках той, которая имеет такое же имя, как и заданное в параметре AnimationSetName. Вы можете вынудить функцию Update использовать первый набор анимации в связанном списке, установив AnimationSetName в NULL.

Название анимации должно совпадать с названием, хранимым в .X файле. Название из .X файла является именем экземпляра объекта набора анимации. Например, следующий объект набора анимации имеет имя экземпляра Walk:

MorphAnimationSet Walk

{

2;

0; "Figure1";, 500; "Figure2";;

}

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

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

// Найти заданное имя набора анимации while(AnimSet !=NULL) {

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

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

}

}

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

return;

//Прекратить работу, если в наборе нет ключей if(!AnimSet->m_NumKeys)

return;

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

272 Глава 9

// Сравнить время с продолжительностью анимации if(Time > AnimSet->m_Length)

Time = (Loop==TRUE)?Time%(AnimSet->m_Length+1):AnimSet->m_Length;

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

// Просмотреть весь набор анимации и найти используемые ключи DWORD Key1 = AnimSet->m_NumKeys-1;

DWORD Key2 = AnimSet->m_NumKeys-1; for(DWORD i=0;i<AnimSet->m_NumKeys-1;i++) {

if(Time >= AnimSet->m_Keys[i].m_Time && \ Time < AnimSet->m_Keys[i+1].m_Time) (

// Нашли ключи, устанавливаем указатели и прерываем цикл Key1 = i;

Кеу2 = i+1; break;

}

}

Теперь, когда мы нашли ключи, используемые в морфированной анимации (хранящиеся как Key1 и Кеу2), можно вычислять значение скаляра морфирования на основе времени этих двух ключей.

// Вычислить используемое значение временного скаляра DWORD Key1Time = AnimSet->m_Keys[Key1].m_Time;

DWORD Key2Time = AnimSet->m_Keys[Key2].m_Time; float KeyTime = (float)(Time - Key1Time);

float MorphScale = 1.0f/(float)(Key2Time-Key1Time)*KeyTime;

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

// Установить указатели

*ppSource = AnimSet->m_Keys[Key1].m_MeshPtr; *ppTarget = AnimSet->m_Keys[Key2].m_MeshPtr; *Scalar = MorphScale;

}

Теперь, когда все классы и функции определены, можно возвращаться к работе! Посмотрите на пример использования только что созданных классов для загрузки и использования коллекции морфированных анимаций из файла MorphAnim.x. Сначала необходимо создать экземпляр объекта cAnimationCollection и загрузить последовательность наборов анимации.

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

cMorphAnimationCollection MorphAnim;

MorphAnim.Load("MorphAnim.x");

Также необходимо загрузить меши. Вы можете использовать удобные вспомогательные функции, разработанные в главе 1, для загрузки набора мешей (из упомянутого ранее файла MorphAnim.x).

D3DXMESHCONTAINER_EX *Meshes;

LoadMesh(SMeshes, NULL, pDevice, "MorphAnim.x");

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

MorphAnim.Map(MorphAnim);

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

Мы будем использовать анимацию MyAnimation2, и необходимо определить, как обновить ее в момент времени 700 (задав бесконечное повторение). Следующий код определит используемые исходный, целевой меши и значение скаляра:

//pAnimCollection = заранее загруженный объект

//cMorphAnimationCollection

//Time = значение DWORD, содержащее используемое время

//анимации, в данном случае 700

//Указатели на исходный и целевой меши, используемые для

//визуализации

D3DXMESHCONTAINER_EX *pSource, *pTarget;

//Значения скаляра, используемое для морфирования float Scalar;

//Вызвать Update, указав морфируемый меш и данные скаляра MorphAnim.Update("MyAnimation2", Time, TRUE, \

&pSource, &pTarget, &Scalar);

Теперь указатели исходного и целевого меша содержат меши, используемые при визуализации морфированного меша, и Scalar, который содержит значение скаляра. Все начинает проясняться; все, что остается сделать, - это нарисовать морфируемый меш, используя технологии, рассмотренные в главе 8. Если хотите,

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