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

140

Глава 4

Если флаг SkinnedMesh установлен в TRUE, то объект pSkinInfo является правильным, и вы готовы работать со скелетным мешем. Следующим шагом является создание еще одного объекта меша, который будет содержать меш, фактически деформируемый при изменении положения костей.

Создание контейнера вторичного меша

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

Давайте оставим их в покое и вместо этого создадим второй объект меша (ID3DXMesh), который будет содержать точную копию скелетного меша. Вам необходимо считать данные вершин из скелетного меша, наложить разнообразные преобразования костей и записать результирующие данные вершин в дублирующий контейнер меша (который я назвал вторичный меш или вторичный контейнер-меш), который используется при визуализации. Разумно, не правда ли?

Как я уже замечал ранее, вторичный меш в точности совпадает со скелетным мешем, начиная от количества вершин и заканчивая индексами. Самым простым методом копирования объекта скелетного меша является использование функции ID3DXMesh::CloseMeshFVF.

HRESULT ID3DXMesh::CloneMeshFVF(

DWORD Options, // Флаги атрибутов меша

DWORD FVF, // FVF используемый для копирования IDirect3DDevice9 *pDevice, // Используемое 3D устройство ID3DXMesh *ppCloneMesh); // объект вторичного меша

Параметр Options функции CloneMeshFVF абсолютно такой же, как и при вызове функций D3DXLoadMeshFromX, D3DXLoadMeshFromXof и D3DXLoadSkinMeshFromXof, так что выбирайте сами. Я рекомендую установить его в 0, но вы можете свободно изменять его.

Что касается параметра FVF, вам просто необходимо предоставить FVF объекта скелетного меша, используя его функцию GetFVF. Нe забывайте также указывать правильный объект IDirect3DDevice9 и указатель на объект ID3DXMesh, который будет вашим контейнером вторичного меша.

Вот небольшой кусочек кода, иллюстрирующий копирование скелетного меша для создания вторичного меша:

Работасоскелетнойанимацией

// pSkinMesh = объект ID3DXMesh

ID3DXMesh *pMesh; // контейнер вторичного меша pSkinMesh->CloneMeshFVF(0, pMesh->GetFVF(), pDevice, &pMesh);

Все эти разговоры о копировании напоминают мне Star Wars Episode II: Attack of the Clones. Хорошей новостью является то, что ваши скопированные меши не будут захватывать вселенную... или будут? Эти копии не способны ничего сделать без небольшой поддержки, так что давайте вернемся к работе и посмотрим, что у нас на очереди.

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

Сопоставление костей фреймам

Если вы просматривали .X файлы, вы могли заметить сходство объектов Frame и SkinWeights. Для каждой кости в вашей скелетной структуре есть соответствующий объект SkinWeights, встроенный в объект Mesh, который содержит имя объекта Frame (или ссылку Frame). Так и есть - каждая кость называется так же, как и соответствующий ей объект Frame!

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

Для этой книги я встроил данные сопоставления костей в структуру D3DXMESHCONTAINER_EX, описанную в главе 1. Структура D3DXMESHCONTAINER_EX (созданная специально для этой книги и описанная ниже) добавляет к структуре D3DXMESHCONTAINER массив объектов текстур, контейнер вторичного меша и данные прикрепления костей.

struct D3DXMESHCONTAINER_EX : D3DXMESHCONTAINER

{

IDirect3DTexture9 **pTextures; ID3DXMesh *pSkinMesh;

D3DXMATRIX **ppFrameMatrices; D3DXMATRIX *pBoneMatrices;

// .. дополнительнные данные и функции

};

142

Глава4

Для этой главы важными являются переменные ppFrameMatrices и pBoneMatrices. Массив ppFrameMatrices содержит преобразования из иерархии костей; одна матрица преобразования накладывается на каждую вершину, принадлежащую соответствующей кости. Единственной проблемой является то, что матрица преобразования костей хранится не в виде массива, а отдельно для каждой кости в иерархии.

Структура D3DXMESHCONTAINER_EX предоставляет указатель для каждой матрицы преобразования костей, содержащейся в иерархии объектов D3DXFRAME_EX в массиве указателей (ppFrameMatrices). Используя эти указатели, вы можете поместить каждое преобразование в созданный в результате обновления скелетного меша массив pBoneMatrices.

Вы можете создать массивы указателей и матриц после загрузки иерархии костей, взяв количество костей в иерархии и создав указатели и объекты D3DXMATRIX:

//pSkinInfo = объект скелетного меша

//Получить количество костей в иерархии DWORD NumBones = pSkinInfo->GetNumBones();

//Создать массив указателей D3DXMATRIX

//для указания на каждое преобразование костей D3DXMATRIX *ppFrameMatrices = new D3DXMATRIX*[NumBones];

//Создать массив объектов D3DXMATRIX для хранения фактических

//преобразований, используемых при обновлении скелетного меша D3DXMATRIX *pBoneMatrices = new D3DXMATRIX[NumBones];

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

Сначала я вам покажу, как определять соответствие кости фрейму. Помните, ранее в этой главе я заметил, что кости имеют такие же имена, как и фреймы. Используя функцию ID3DXSkinInfo::GetBoneName вы можете получить имя кости для сравнения с фреймом.

// Просмотреть все кости и получить имя каждой for(DWORD i=0;i<pSkinInfo->GetNumBones();i++) (

// Получить имя кости

const char *BoneName = pSkinInfo->GetBoneName(i);

Работа со скелетнойанимацией

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

//pRootFrame = корневой объект фрейма D3DXFAME_EX

//Находит совпадающее имя в фреймах

D3DXFRAME_EX *pFrame = pRootFrame->Find(BoneName);

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

// Сравнить фрейм с костью if(pFrame)

pMesh->ppFrameMatrices[i] = &pFrame->matCombined; else

pMesh->ppFrameMatrices[i] = NULL;

}

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

Управление скелетными мешами

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

Говоря об изменении положения фреймов, помните, что вы должны только вращать ваши кости; вы никогда не должны перемещать их. Масштабирование приемлемо, но будьте осторожны, помните, что преобразования распространяются по иерархии. Если вы масштабировали верхнюю руку персонажа, нижняя также будетотмасштабирована.

Ярассказывал об изменении положения различных костей ранее в этой главе,

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

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