- •Введение
- •Глава 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
- •Предметный указатель
114
Materials[i] = pMat[i].MatD3D;
//Копировать рассеянный цвет в окружающий Materials[i].Ambient = Materials[i].Diffuse;
//Загрузить текстуру, если задана Textures[i] = NULL; if(pMat[i].pTextureFilename) {
D3DXCreateTextureFromFile(pDevice, \
pMat[i].pTextureFilename, &Textures[i]);
}
}
}else {
//Создать материал по умолчанию, если не загрузился Materials = new D3DMATERIAL9[1];
Textures = new IDirect3DTexture9*[1];
//Установить по умолчанию белый материал без текстуры Textureыs[0] = NULL;
ZeroMemory(&Materials[0], sizeof(D3DMATERIAL9)); Materials[0].Diffuse.r = Materials[0].Ambient.r = 1.0f; Materials[0].Diffuse.g = Materials[0].Ambient.g = 1.0f;
Materials[0].Diffuse.b = Materials[0].Ambient.b = 1.0f; Materials[0].Diffuse.a = Materials[0].Ambient.a = 1.0f;
}
// Освободить буфер данных материала pMaterials->Release();
Вы можете видеть в предыдущем коде, что я добавил проверку случая, когда материал не был загружен, а создается материал, используемый по умолчанию. После загрузки материалов вы можете использовать интерфейс меша для визуализации. В главе 1 было показано, как использовать интерфейс меша для его визуализации. А пока вернемся к теме, о которой я говорил ранее - загрузка мешей, используя анализатор .X.
Загрузка мешей, используя анализатор .X
Как я и обещал, пришло время узнать, как присоединить функции загрузки мешей к классу анализатора .X. Т. к. мы будем непосредственно получать доступ к объектам мешей, необходимо использовать функцию D3DXLoadMeshFromXof для загрузки данных меша. Это означает, что вам необходимо анализировать каждый объект, ища при этом объекты "Mesh". Начнем с наследования класса анализатора, с которым будем работать.
class cXMeshParser : public cXParser
{
public:
ID3DXMesh *m_Mesh;
Использование формата файла .X
public:
cXMeshParser() { m_Mesh = NULL; }
~cXMeshParser() { if(m_Mesh) m_Mesh->Release(); }
BOOL ParseObject(IDirectXFileData *pDataObj, \ IDirectXFileData *pParentDataObj, \ DWORD Depth, \
void **Data, BOOL Reference);
};
Как вы можете видеть из объявления класса, я объявляю только один объект меша. Если вы хотите больше, вам необходимо создать связанный список (или какойлибо другой список) для хранения объектов меша. Я оставляю это вам, потому что мне просто необходимо продемонстрировать использование функции D3DXLoadMeshFromXof.
Перезагружая функцию ParseObject, позволим ей искать объекты Mesh.
BOOL cXMeshParser::ParseObject( \ IDirectXFileData *pDataObj, \ IDirectXFileData *pParentDataObj, \ DWORD Depth, \
void **Data, BOOL Reference)
{
//Пропустить ссылочные объекты if(Reference == TRUE)
return TRUE;
//Убедиться, что анализируемый объект - Mesh if(*GetObjectGUID(pDataObj) == D3DRM_TIDMesh) {
//это меш, использовать D3DXLoadMeshFromXof для его загрузки
ID3DXBuffer *Materials;
DWORD NumMaterials;
D3DXLoadMeshFromXof(pDataObj, 0, pDevice, NULL, \
&Materials, NULL, &NumMaterials, &m_Mesh);
//Закончить обработку информации о материалах
//Вернуть FALSE для завершения анализирования return FALSE;
}
// Анализировать дочерние объекты
return ParseChildObjects(pDataObj,Depth,Data,Reference);
}
Вот и все! Используя один быстрый вызов, вы загружаете меш из объекта Mesh! Если вы думаете, что это круто, у меня есть для вас кое-что новое - скелетные меши. Правильно, те изящные скелетные меши, о которых вы читали в главе 2, также легко использовать, как и стандартные меши. Читайте далее, чтобы узнать, как загружать скелетные меши из .X файлов.
116 Глава3
Загрузка скелетных мешей
Как я упоминал в главе 1, скелетный меш содержит иерархию костей (скелетную структуру), которую вы можете использовать для деформации меша, к которому присоединены кости. Хотя в главе 1 и описывалось использование скелетных мешей, я оставил вопрос загрузки данных скелетных мешей для этой главы, потому что вы можете загружать их данные, только используя класс анализатора .X. К счастью для вас, вы подготовлены!
Загрузка скелетных мешей из .X файлов похожа на загрузку обычных мешей. Перечисляя объекты данных, вы можете определить, из каких из них загружать данные скелетного меша и помещать их в объект ID3DXSkinMesh.
Сюрпризом является то, что данные скелетного меша хранятся в том же объекте, где и обычные меши, - Mesh. Если объект один и тот же, то как же мы можем отличать скелетные меши от обычных?
Единственным способом, чтобы определить содержит ли объект Mesh данные скелетного меша, является использовании функции D3DXLoadSkinMeshFromXof для загрузки меша в объект ID3DXSkinMesh. После загрузки данных меша вы можете получить только что загруженный объект скелетного меша для просмотра, есть ли в нем информация о костях (которая содержится в специально встраиваемом Mesh-объекте). Если информация о костях существует, то это скелетный меш. Если костей не существует, то меш является обычным и может быть преобразован
кобъекту ID3DXMesh.
Яначинаю забегать вперед, так что вернемся к ID3DXSkinMesh и D3DXLoadSkinMeshFromXof. Совсем как с обычными мешами, необходимо создать экземпляр объекта ID3DXSkinMesh.
ID3DXSkinMesh *SkinMesh = NULL;
В функции ParseObject необходимо заменить вызов D3DXLoadSkinMeshFromXofl. Вместо вызова D3DXLoadMeshFromXof будем использовать D3DXLoadSkinMeshFromXof.
Замечание.Пользователи DirectX 8 могут вырезать строку LPD3DXBUFFER* ppEffectInstancesизвызоваD3DXLoadSkinMeshFromXof.
HRESULT D3DXLoadSkinMeshFromXof(
LPDIRECTXFILEDATA pXofObjMesh,
DWORD Options,
LPDIRECT3DDEVICE9 pDevice,
LPD3DXBUFFER* ppAdjacency,
LPD3DXBUFFER* ppMaterials,
LPD3DXBUFFER* ppEffectInstances,
DWORD* pMatOut,
LPD3DXSKINMESH* ppMesh);
Использование формата файла .X
Я знаю, вы скажите, что D3DXLoadSkinMeshFromXof выглядит почти как D3DXLoadMeshFromXof, и вы будете правы! Загрузка скелетного меша, используя функцию D3DXLoadMeshFromXof, выглядит так:
D3DXLoadSkinMeshFromXof(pDataObj, 0, pDevice, NULL, \
&Materials, NULL, &NumMaterials, &SkinMesh);
После того как вы вызвали D3DXLoadSkinMeshFromXof, используя правильный объект Mesh, в вашем распоряжении появляется новый объект ID3DXSkinMesh.
Загрузка иерархии фреймов из .Xфайла
Системы скелетной анимации требуют иерархии фреймов (которые представлены структурой костей) для ориентации каждой кости при визуализации. Формат файла .X определяет шаблон данных ссылочных фреймов, который вы можете использовать для задания иерархии костей. Этот шаблон, Frame, просто ответственный за типы. Он позволяет встраивать объекты любого типа, так что вы можете ссылаться на ссылочный объект Frame, присваивая ему имя и позволяя адресовать все содержащиеся объекты.
Построение иерархии фреймов включает в себя анализ .X файла, в котором вы связываете каждый объект Frame между собой. Взаимоотношения очень важны - объект Frame может быть как родственником, так и потомком другого объекта Frame и может иметь неограниченное количество родственников и/или потомков, привязанных к нему.
В DirectX 9 вы можете получить доступ к специальной структуре DirectX, называемой D3DXFRAME, предназначенной для хранения каждого кадра в иерархии. Я говорил об этой структуре в главе 1. В этом разделе я использовал D3DXFRAME для хранения иерархии фреймов.
Каким образом вы будете анализировать и создавать объекты Frame, зависит от вас. Вы можете использовать библиотеку D3DX или анализировать/строить иерархию сами, используя специализированные анализаторы .X. Что лучше для вас? Принимая во внимание, что замечательно использовать библиотеку D3DX, я обнаружил, что методы использования библиотеки при загрузке иерархии фреймов сложны, необходимо создавать не менее двух используемых интерфейсов и самостоятельно написанный класс операций с памятью. Зачем волноваться, когда вы можете загружать иерархию, используя один маленький созданный вами класс анализирования .X?
118 |
Глава 3 |
Вместо этого возьмите проверенный анализатор .X (разработанный ранее в этой главе в разделе "Создание класса анализатора .X") и унаследуйте от него версию, которая ищет объекты Frame. Я начну, показав наследуемый класс, который можно использовать.
class cXFrameParser : public cXParser
{
public:
//объявить расширенную версию D3DXFRAME
//которая содержит конструктор и деструктор struct D3DXFRAME_EX : public D3DXFRAME {
D3DXFRAME_EX()
{
Name = NULL;
pFrameSibling = NULL; pFrameFirstChild = NULL;
}
~D3DXFRAME_EX()
{
delete [] Name;
delete pFrameFirstChild; delete pFrameSibling;
}
} D3DXFRAME_EX;
// создать корневой фрейм иерархии D3DXFRAME_EX *m_RootFrame;
public:
cXFrameParser() { m_RootFrame = NULL; } ~cXFrameParser() { delete m_RootFrame; }
BOOL BeginParse(void **Data)
{
// очистить иерархию
delete m_RootFrame; m_RootFrame = NULL;
}
BOOL ParseObject(IDirectXFileData *pDataObj, \ IDirectXFileData *pParentDataObj, \
DWORD Depth, \
void **Data, BOOL Reference)
{
//пропустить ссылочные фреймы if(Reference == TRUE)
return TRUE;
//убедиться, что анализируемый шаблон - Frame if(*GetObjectGUID(pDataObj) == TID_D3DRMFrame) {
//Создать структуру фрейма
D3DXFRAME_EX *Frame = new D3DXFRAME_EX();