
- •Введение
- •Глава 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
- •Предметный указатель
Работа соскелетнойанимацией |
. |
Как я уже упоминал, вам необходимо просто вызвать функцию UpdateHierarchy, используя корневой фрейм. Не указывайте матрицу преобразования в качестве второго параметра, он будет использован при рекурсивных вызовах. Если же вы зададите матрицу преобразования, весь меш будет сдвинут на нее. Это то же самое, что установить матрицу преобразования мира для расположения объекта при визуализации.
// pRootFrame = корневой фрейм-объект D3DXFRAME_EX UpdateHierarchy(pRootFrame);
После того как вы познакомились со скелетной структурой и работой с иерархиями костей, пришло время перейти ко второй части анимации - накладным скелетным мешам, которые меняют форму в соответствии с расположением иерархии костей.
Работа со скелетными мешами
В первой половине этой главы вы научились управлять иерархией костей, которые являются основой скелетной анимации. Это все хорошо, но игра с воображаемыми костями не очень занимательна. Людям, играющим в ваши игры, необходимо видеть всю тяжелую работу в виде визуализированных мешей, где и приходит время скелетных мешей.
Скелетные меши очень похожи на обычные, с которыми вы уже знакомы. Используя объект D3DXMESHCONTAINER_EX (как вы видели в главе 1), вы можете хранить данные ваших мешей от вершин и индексов до материалов и данных текстур, все это находится в удобном объекте ID3DXMesh. Что же касается фактических данных скелетного меша, они расположены в специальном объекте ID3DXSkinInfo.
Я пока пропущу описание объекта ID3DXSkinInfo и вместо этого объясню, чем же скелетные меши отличаются от остальных. Скелетные меши меняют форму в соответствии с расположением скелетной структуры. Вершины меша вращаются и поворачиваются вместе с костями. Вершины меша делают скелетный меш уникальным. Вы будете иметь дело с изменением положения вершин при работе со скелетными мешами.
Посмотрите на рис. 4.3, на котором изображен скелет, окруженный простейшим мешем.
На рис. 4.3 каждая вершина присоединена к кости. Когда кость двигается, вместе с ней двигаются и присоединенные к ней вершины. Например, если повернуть кость на 45 градусов по оси х, присоединенные к ней вершины также повернутся на 45 градусов, при этом точка скрепления костей будет является центом вращения.

136 |
Глава 4 |
Рис. 4.3. При присоединении к скелетной структуре меш изменяется таким образом, чтобы каждая вершина соединялась с костью
Внимательно посмотрев на рис. 4.3 вы обнаружите, что некоторые вершины присоединены к нескольким костям. Так и есть - вы можете присоединять вершину более чем к одной кости. На самом деле, при использовании DirectX вы можете присоединять вершину к неограниченному числу костей, используя методы, которые вы изучите в этой книге. При движении кости, к которой присоединена вершина, вершина наследует не все движения. Например, если кость поворачивается на 60 градусов по оси z, присоединенная к ней вершина может повернуться только на 25 процентов от этого, т.е вершина повернется только на 15 градусов по оси z.
Точное значение процентного соотношения наследуемого вершиной движения назьшается весом вершины. Для каждой вершины скелетного меша назначается ее вес при присоединении ее к кости. Для вершин, присоединенных только к одной кости, это значение обычно 1.0, это говорит о том, что вершина наследует все движения
Работасоскелетнойанимацией |
137 |
кости. Для вершин, присоединенных к нескольким костям, веса делятся на количество костей и, обычно, вычисляются, используя расстояние до каждой кости. (Большинство программ трехмерного моделирования сделает это за вас.) Например, вершина присоединена к двум костям, это означает, что оба веса будут по 0.5. Вершина будет наследовать только 50 процентов движения каждой кости. Заметьте, что сумма весов одной вершины всегда равняется 1.
Цель использования весов скелета достаточно оригинальна. Позволяя определенным костям влиять на заданные вершины, вы можете создавать привлекательные эффекты, такие как морщинистая кожа, неровности мускулов, растяжение одежды, - все это в реальном времени при анимации ваших объектов!
Путь, используемый DirectX для обработки весов вершин, достаточно прост. После загрузки меша, который вы будете использовать как скелетный, и весов вершин (также называемых скелетными весами), вы можете преобразовать вершины, чтобы они соответствовали расположению, костей используя следующие шаги:
1.Перебрать все вершины. Для каждой вершины выполнить шаг 2.
2.Для каждой кости, к которой присоединена вершина, получить преобразование.
3.Каждое преобразование кости умножить на матрицу вершинных весов и наложить полученное преобразование на комбинированное преобразование вершин.
4.Повторить шаг 3 для каждой присоединенной кости, шаги 2-4 повторить для всех вершин. После завершения применить комбинированную матрицу преобразования на заданную вершину (из шага 1).
Ивсе таки, как получить веса вершин? Используя объект ID3DXSkinInfo, о котором я упоминал ранее, вы можете загружать веса из .X файлов. Скелетные веса хранятся в объекте Mesh, в конце его данных.
Каждой кости в скелетной структуре соответствует объект SkinWeights. Внутри объекта SkinWeights находится имя кости и следующее за ним количество присоединенных вершин. Заголовок скелетного меша определяет количество костей, к которым может быть присоединена каждая вершина. Если какая то из вершин присоединена к двум костям, тогда все вершины должны быть присоединены к двум костям. Для того чтобы вершины могли иметь разное количество костей, вы можете присваивать вес 0 ненужным костям.
Как я упоминал ранее, объект SkinWeights включает количество вершин, присоединенных к кости. Он перечисляет массив индексов вершин. После массива индексов вершин расположен массив значений весов вершин. Наконец, далее идет обратное преобразование костей для помощи в расположении вершин относительно соединений костей.
138 Глава 4
Посмотрите на пример объекта шаблона SkinWeights:
SkinWeights { "Bip01_R_UpperArm"; 4; 0, 3449, 3429, 1738;
0.605239, 0.605239, 0.605239, 0.979129; -0.941743, -0.646748, 0.574719, 0.000000, -0.283133, -0.461979, -0.983825, 0.000000, 0.923060, -1.114919, 0.257891, 0.000000, -65.499557, 30.497688, 12.852692, 1.000000;;
}
В этом объекте используется кость "Bip01_R_UpperArm". К ней присоединены четыре вершины с индексами 0, 3449, 3429 и 1738. Вершина 0 имеет вес 0.605239, вершина 1 - 0.605239 и так далее. Матрица преобразования выравнивает перечисленные вершины относительно соединения костей. Эта матрица очень важна. Без нее вершины будут вращаться относительно центра мира, а не соединения костей.
К счастью, вам не нужно напрямую работать с шаблоном SkinWeights. Эти данные обрабатываются при загрузке скелетных мешей из .X файлов, используя функции D3DX.
Загрузка скелетных мешей из .X
Загрузка скелетных мешей из .X файлов очень похожа на загрузку обычных мешей. Используя специализированный анализатор .X файлов, вы должны перечислить объекты, содержащиеся в .X файле, при помощи функции ParseObject. Когда придет время обрабатывать объект Mesh, вместо вызова функции D3DXLoadMeshFromXof для загрузки данных меша используйте D3DXLoadSkinMeshFromXof, которая имеет дополнительный параметр - указатель на объект ID3DXSkinInfo. Посмотрите на прототип функции D3DXLoadSkinMeshFromXof, чтобы понять о чем я.
HRESULT D3DXLoadSkinMeshFromXof(
IDirectXFileData *pXofObjMesh, // Объект .X файла DWORD Options, // Опции загрузки
IDirect3DDevice9 *pDevice, // Используемое 3D устройство ID3DXBuffer **ppAdjacency, // объект буфера смежности ID3DXBuffer **ppMaterials, // объект буфера материала ID3DXBuffer **ppEffectInstances, // объекты экземпляров эффектов DWORD *pMatOut, // # материалов
ID3DXSkinInfo **ppSkinInfo, // объект информации скелета!!! ID3DXMesh **ppMesh); // загруженный объект меш
Работа со скелетнойанимацией
Когда вы готовы загрузить меш из перечисленного шаблона Mesh, вызовите функцию D3DXLoadSkinMeshFromXof вместо D3DXLoadMeshFromXof. Убедитесь, что вы указали объект ID3DXSkinInfo, заданный в прототипе. Неважно, содержит ли шаблон Mesh скелетный меш, функция D3DXLoadSkinMeshFromXof загружает как обычные, так и скелетные меши. Вот пример:
//Определить структуры меша и информации скелетного меша ID3DXMesh *pMesh;
ID3DXSkinInfo *pSkinInfo;
//Определить буферы для хранения данных материалов и смежностей ID3DXBuffer *pMaterialBuffer = NULL, *pAdjacencyBuffer = NULL;
//DWORD для хранения количества загруженных материалов
DWORD NumMaterials;
// Загрузить скелетный меш из IDirectXFileDataObject pDataObj D3DXLoadSkinMeshFromXof(pDataObj, D3DXMESH_SYSTEMMEM, \
pDevice, &pAdjacencyBuffer, \ &pMaterialBuffer, NULL, \ &NumMaterials, &pSkinInfo, &pMesh);
Использование функции D3DXLoadSkinnedMeshFromXof еще не означает, что загруженный меш является скелетным. Сначала вам необходимо проверить объект pSkinInfo. Если он установлен в NULL, тогда скелетный меш не был загружен. Если же он правильный объект (не NULL), тогда вам необходимо проверить существование костей.
Самым простым способом проверить наличие костей является вызов ID3DXSkinInfo::GetNumBones. Эта функция возвращает количество костей, загруженных из шаблона Mesh. Если количество костей 0, то тогда их нет, и вы можете освобождать объект ID3DXSkinInfo (используя Release). Если же кости существуют, вы можете продолжать использованиe скелетного меша.
Посмотрите на этот пример, который тестирует, является ли загруженный меш скелетным. Если да, то проверяется наличие в меше костей.
// Установить флаг, если меш скелетный и есть кости BOOL SkinnedMesh = FALSE;
if(pSkinInfo && pSkinInfo->GetNumBones()) SkinnedMesh = TRUE;
else {
// Освободить данные объекта информации скелетного меша if(pSkinInfo) {
pSkinInfo->Release(); pSkinInfo = NULL;
}
}