- •Введение
- •Глава 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
- •Предметный указатель
Работа со скелетнойанимацией
Использование скелетной структуры и скелетного меша
Скелетная структура, как вы можете представить, является набором соединенных костей, образующих иерархию (иерархию костей, если быть точным). Одна кость, называемая корневой, является центральной точкой для всей скелетной структуры. Все кости присоединяются к корневой кости либо как родственники, либо как потомки.
Слово "кость" означает-объект ссылку на фрейм (объект-фрейм, который представлен структурой DirectX D3DXFRAME или шаблоном Frame внутри файла .X). Если бы вы посмотрели структуру D3DXFRAME, вы бы действительно обнаружили связанный список указателей (D3DXFRAME::pFrameSibling и D3DXFRAME::pFrameFirstChild), образующий иерархию. Указатель D3DXFRAME::pFrameSibling связывает между собой кости одного уровня иерархии, в то время как указатель D3DXFRAME::pFrameFirstChild привязывает дочерние кости, которые расположены на один уровень ниже в иерархии.
Обычно для создания скелетных структур, применяемых в ваших проектах, используются пакеты трехмерного моделирования. Экспортирование иерархии костей из .X файла является отличным примером. Microsoft реализовала экспортеры для 3D Studio Max и Maya, которые позволяют экспортировать данные скелетов и анимации в .X файлы, причем такую возможность экспорта предусматривают многие программы моделирования. Я предполагаю, что у вас есть программа1, с помощью которой можно экспортировать эти иерархии в .X файл.
Вы найдете множество вещей внутри .X файла, содержащих данные анимации. Первое (и наверное самое главное на данный момент), вы обнаружите иерархию шаблонов Frame, которая на самом деле является замаскированной иерархией костей. Если бы у вас была простая скелетная структура, подобная изображенной на рис. 4.1, тогда ваша иерархия фреймов выглядела бы подобно изображенной на том же рисунке.
Вы должны обнаружить стандартный объект данных Mesh, встроенный в иерархию объектов Frame. Объект Mesh содержит информацию об объекте скелетной анимации и костях, используемых в скелетной структуре. Так и есть - объекты Frame и Mesh содержат информацию о вашей скелетной структуре! Объект Mesh определяет, какие фреймы представляют кости, в то время как объект Frame определяет фактическую иерархию.
1. Можно взять из DirectX Extras с сайта Microsoft.— Примеч. научн. ред.
128 |
Глава4 |
Рис. 4.1. Расположенная слева скелетная структура представлена иерархией справа. Заметьте, что используются указатели D3DXFRAME для образования связанного списка родственных и дочерних кадров
Однако на данный момент кости играют незначительную роль. Т. к. кости зависят от иерархии фреймов, на данном этапе важно сконцентрироваться исключительно на фреймах. Вам просто нужно загрузить иерархию (например, из .X файла) и настроить ее для дальнейшего использования. Читайте далее, чтобы узнать, как загружать иерархии из .X.
Загрузка иерархий из .X
Не следует бить мертвую лошадь (как я могу сделать такую ужасную вещь?), но я хочу слегка коснуться загрузки иерархий фреймов из .X файлов. Хотя в главе 3 детально описаны использование .X файлов и загрузка иерархий фреймов, я хочу еще раз вернуться к этому, используя специальные структуры для хранения иерархии.
Для хранения иерархии фреймов вам необходимо использовать структуру D3DXFRAME (или показанную в главе 1 D3DXFRAME_EX). Как я уже замечал ранее, структура D3DXFRAME (или унаследованная D3DXFRAME_EX) содержит два указа-
Работа со скелетнойанимацией
теля, предназначенных для создания иерархии - pFrameSibling и pFrameFirstChild. Ваша задача связать каждый загружаемый из .X файла фрейм, используя эти два указателя.
Переберите все объекты данных из заданного .X файла, начав с корневого объекта фрейма. Когда вы обнаружите объект Frame, привяжите его как родственный или дочерний к предыдущему кадру. Продолжайте выполнять эти операции, пока не загрузите все фреймы. В этом примере используйте структуру D3DXFRAME_EX для хранения фреймов в иерархии.
Т.к. в главе 3 содержалось намного больше информации об анализе .X файлов,
япросто слегка напомню вам. Обычно вы открываете .X файл и перебираете каждый объект в нем. Для каждого найденного объекта Frame создаете соответствующий объект D3DXFRAME (или D3DXFRAME_EX) и привязываете его в иерархию объектов.
Для обработки .X файлов, вы можете создать класс, который бы выполнял всю работу за вас. Вы можете просто создать функцию ParseObject, принадлежащую классу, которая бы давала доступ к данным всех объектов. Опять же в главе 3 приведено подробное объяснение использования этого класса.
А теперь давайте посмотрим на функцию ParseObject, которая вызывается для всех перечисляемых объектов.
BOOL cXFrameParser::ParseObject( IDirectXFileData *pDataObj, IDirectXFileData *pParentDataObj, DWORD Depth,
void **Data, BOOL Reference)
{
const GUID *Type = GetObjectGUID(pDataObj);
//Если объект типа Frame (не ссылочный)
//тогда добавить его в иерархию
if(*Type == TID_D3DRMFrame && Reference == FALSE) {
// создать контейнер фрейма
D3DXFRAME_EX *pFrame = new D3DXFRAME_EX();
//Если есть, получить имя фрейма pFrame->Name = GetObjectName(pDataObj);
//Привязать объект в иерархию
if(Data == NULL) {
// Привязать как родственника корневого pFrame->pFrameSibling = m_RootFrame; m_RootFrame = pFrame; pFrame = NULL; Data = (void**)&m_RootFrame;
}else {
//Привязать как дочерний текущего
D3DXFRAME_EX *pFramePtr = (D3DXFRAME_EX*)*Data; pFrame->pFrameSibling = pFramePtr->pFrameFirstChild;
130
pFramePtr->pFrameFirstChild = pFrame; pFrame = NULL; Data = (void**)&pFramePtr->pFrameFirstChild;
}
}
// Загрузить матрицу преобразования фрейма if(*Type==TID_D3DRMFrameTransformMatrix && Reference==FALSE) {
D3DXFRAME_EX *Frame = (D3DXFRAME_EX*)*Data; if(Frame) {
Frame->TransformationMatrix = *(D3DXMATRIX*) \ GetObjectData(pDataObj, NULL);
Frame->matOriginal = Frame->TransformationMatrix;
}
}
// Анализировать дочерние объекты
return ParseChildObjects(pDataObj, Depth, Data, Reference);
}
Если вы еще не читали главу 3 (стыдно, если нет!), некоторые части приведенного выше кода могут немного смущать вас. Обычно функция ParseObject вызывается для каждого перечисляемого объекта. Внутри функции ParseObject вы проверяете тип текущего перечисляемого объекта (используя его шаблонный GUID). Если тип является Frame, вы создаете структуру фрейма и загружаете его имя в нее.
Далее вы привязываете фрейм в иерархию фреймов, что и выглядит немного странным. Класс cXFrameParser содержит два указателя - один для созданного корневого фрейм-объекта (m_RootFrame, член класса) и один для объекта данных (Data), который передается в качестве параметра функции ParseObject при каждом ее вызове. Указатель данных содержит данные последнего загруженного фрейм-объекта.
Как только вы начинаете анализировать .X файл, указатель Data установлен в NULL, означая, что не было загружено никаких фрейм-объектов. Когда вы загружаете фрейм-объект, вы проверяете указатель данных, чтобы определить указывает ли он на фрейм. Если нет, то предполагается, что текущий фрейм является родственником корневого фрейма. Если же указатель данных указывает на фрейм, то полагается что текущий перечисляемый фрейм является потомком указываемого указателем данных фрейма.
Знание того, является ли текущий фрейм родственным или дочерним, считается определяющим при создании иерархии. Родственные фреймы связываются, используя указатель pFrameSibling структуры D3DXFRAME, в то время как дочерние фреймы связываются, используя pFrameFirstChild. Сразу же после загрузки фрейма указатель данных устанавливается в новый фрейм или в предыдущий родственный фрейм. В конце концов, все фреймы связываются между собой как родственники или потомки.