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

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();

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