- •Введение
- •Глава 1. Подготовка к изучению книги
- •Установка DirectX SDK
- •Выбор отладочных или рабочих версий библиотек
- •Настройка вашего компилятора
- •Установка директорий DirectX SDK
- •Привязывание к библиотекам DirectX
- •Установка используемого по умолчанию состояния символа
- •Использование вспомогательного кода книги
- •Использование вспомогательных объектов
- •Проверка вспомогательных функций
- •Двигаясь дальше по книге
- •Глава 2. Синхронизация анимации и движения
- •Использование движения, синхронизированного по времени
- •Считывание времени в Windows
- •Анимирование с использованием временных меток
- •Перемещение, синхронизированное со временем
- •Движение вдоль траекторий
- •Создание анализатора маршрутов .X файла
- •Создание внутриигровых кинематографических последовательностей
- •Посмотрите демонстрационные программы
- •TimedAnim
- •TimedMovement
- •Route
- •Cinematic
- •Глава 3. Использование формата файла .X
- •Работа с .X шаблонами и объектами данных
- •Определение шаблонов
- •Работа со стандартными шаблонами DirectX
- •Открытие .X файла
- •Перечисление объектов данных
- •Получение данных объекта
- •Создание класса .X анализатора
- •Загрузка мешей с использованием D3DX
- •Загрузка мешей, используя анализатор .X
- •Загрузка скелетных мешей
- •Загрузка анимации из .X
- •Загрузка специализированных данных из .X
- •Посмотрите демонстрационные программы
- •ParseFrame
- •Глава 4. Работа со скелетной анимацией
- •Начало скелетной анимации
- •Использование структур скелетов и иерархий костей
- •Использование скелетной структуры и скелетного меша
- •Загрузка иерархий из .X
- •Изменение положения костей
- •Обновление иерархии
- •Работа со скелетными мешами
- •Загрузка скелетных мешей из .X
- •Создание контейнера вторичного меша
- •Сопоставление костей фреймам
- •Обновление скелетного меша
- •Визуализация скелетных мешей
- •Глава 5. Использование скелетной анимации, основанной на ключевых кадрах
- •Использование наборов скелетных анимаций, основанных на ключевых кадрах
- •Использование ключей при анимации
- •Работа с четырьмя типами ключей
- •Считывание данных анимации из .X файлов
- •Прикрепление анимации к костям
- •Обновление анимации
- •Посмотрите демонстрационные программы
- •Глава 6. Комбинирование скелетных анимаций
- •Комбинирование скелетных анимаций
- •Соединение преобразований
- •Улучшение объектов скелетной анимации
- •Посмотрите демонстрационные программы
- •Глава 7. Создание кукольной анимации
- •Работа с физикой твердого тела
- •Создание твердого тела
- •Расположение и ориентирование твердых тел
- •Обработка движения твердых тел
- •Использование сил для создания движения
- •Соединение твердых тел с помощью пружин
- •Обеспечение обнаружения столкновений и ответной реакции
- •Создание систем кукольной анимации
- •Определение состояния твердого тела
- •Хранение костей
- •Создание класса управления куклой
- •Создание данных костей
- •Вычисление ограничивающего параллелепипеда кости
- •Установка сил
- •Объединение костей
- •Обработка столкновений
- •Восстановление соединений костей
- •Перестроение иерархии
- •Посмотрите демонстрационные программы
- •Глава 8. Работа с морфирующей анимацией
- •Морфинг в действии
- •Определение исходного и целевого меша
- •Морфинг мешей
- •Создание морфированного меша при помощи обработки
- •Визуализация морфированных мешей
- •Расчленение наборов
- •Создание морфирующего вершинного шейдера
- •Посмотрите демонстрационные программы
- •Глава 9. Использование морфирующей анимации, основанной на ключевых кадрах
- •Использование наборов морфируемой анимации
- •Создание шаблонов .X для морфируемой анимации
- •Загрузка данных морфируемой анимации
- •Визуализации морфированного меша
- •Получение данных морфируемого меша из альтернативных источников
- •Посмотрите демонстрационные программы
- •Глава 10. Комбинирование морфированных анимаций
- •Комбинирование морфированных анимаций
- •Использование базового меша в комбинированных морфированных анимациях
- •Вычисление разностей
- •Комбинирование разностей
- •Создание вершинных шейдеров комбинированного морфирования
- •Использование вершинного шейдера морфируемого комбинирования
- •Посмотрите демонстрационные программы
- •Глава 11. Морфируемая лицевая анимация
- •Основы лицевой анимации
- •Использование комбинированного морфирования
- •Использования фонем для речи
- •Создание лицевых мешей
- •Создание базового меша
- •Создание выражений лица
- •Создание мешей визем
- •Создание анимационных последовательностей
- •Создание последовательностей фонем
- •Использование анализатора файлов .X для последовательностей
- •Проигрывание лицевых последовательностей со звуком
- •Использование DirectShow для звука
- •Синхронизация анимации со звуком
- •Зацикливание воспроизведения звуков
- •Посмотрите демонстрационные программы
- •Глава 12. Использование частиц в анимации
- •Работа с частицами
- •Основы
- •Рисование частиц с помощью квадратных полигонов
- •Работа с точечными спрайтами
- •Улучшения визуализации частиц при помощи вершинных шейдеров
- •Оживление частиц
- •Передвижение частиц при помощи скорости
- •Использование интеллекта при обработке
- •Создание и уничтожение частиц
- •Управление частицами с помощью класса
- •Использование излучателей в проектах
- •Создание движков частиц в вершинных шейдерах
- •Посмотрите демонстрационные программы
- •Глава 13. Имитирование одежды и анимация мешей мягких тел
- •Имитация одежды в ваших проектах
- •Получение данных одежды из мешей
- •Приложение сил для создания движения
- •Воссоздание и визуализация меша одежды
- •Восстановление исходного меша
- •Добавление дополнительных пружин
- •Загрузка данных масс и пружин из .X файла
- •Создание анализатора .X данных одежды
- •Работа с обнаружением столкновений и реакцией на них
- •Определение объектов столкновений
- •Обнаружение и реакция на столкновения
- •Создание класса меша одежды
- •Использование мешей мягких тел
- •Восстановление мешей мягких тел
- •Посмотрите демонстрационные программы
- •Глава 14. Использование анимированных текстур
- •Использование анимации текстур в ваших проектах
- •Работа с преобразованиями текстур
- •Создание преобразования текстур
- •Установка матриц преобразования текстуры
- •Использование преобразования текстур в проектах
- •Использование файлов видео в качестве текстур
- •Импорт видео при помощи DirectShow
- •Создание специализированного фильтра
- •Работа со специализированным фильтром
- •Создание менеджера анимированных текстур
- •Окончание современной анимации
- •Веб-сайты
- •Рекомендуемые книги
- •DirectX 9.0 SDK
- •GoldWave Demo
- •Paint Shop Pro Trial Version
- •TrueSpace Demo
- •Microsoft Agent and LISET
- •Предметный указатель
Использование морфирующей анимации, основаннойна ключевыхкадрах
зовать 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 для перебора всех мешей, содержащихся в объекте, и поиска заданного имени меша. Если такой меш найден, указатель на него сохраняется в объекте ключа.
Когда наступает время визуализировать набор морфируемых анимаций, вы быстро просматриваете ключи, находите указатель меша и визуализируете его. Эти же самые последовательности действия могут быть использованы для визуализирования ваших собственных морфируемых анимаций. Просто переходите со мной к следующему разделу, и вы сможете визулизировать меш в мгновение ока!