Помните, что объекты данных являются контейнерами для данных, и если у вас возникают трудности с перечислением объектов данных, разумно предполагать, что вы имеете данные в каждом их них. После того как вы получили правильный объект IDirectXFileData, который указывает на перечисленный объект данных, вы можете получит имя экземпляра объекта, GUID шаблона и данные, используя три функции.
Первая функция IDirectXFileData::GetName получает имя экземпляра объекта данных.
HRESULT IDirectXFileData::GetName( LPSTR pstrNameBuf, // Буфер имени LPDWORD pdwBufLen) ; // Размер буфера имени
Функция GetName имеет два параметра - указатель на буфер, содержащий имя, и указатель на переменную, содержащую размер буфера имени (в байтах). Прежде чем получать имя, используя функцию GetName, вам необходимо получить его размер, задав значение NULL в качестве pstrNameBuf и указатель на DWORD для pdwBufLen.
// pData = загруженный объект IDirectXFileData // Получить размер имени в байтах DWORD Size;
pData->GetName(NULL, &Size);
После того как вы получили размер буфера имени, вы можете создать соответствующий буфер и считать имя.
// Создать буфер имени и получить его char *Name = new char[Size] ; pData->GetName(Name, &Size);
Хотя имя экземпляра объекта и помогает, на самом деле вам необходим GUID шаблона объекта, для определения, какой шаблон использует объект. Для получения GUID шаблона объекта используйте функцию IDirectXFileData::GetType.
HRESULT IDirectXFileData::GetType( const GUID ** ppguid) ;
Используя только один параметр - указатель на указатель const GUID, вы можете вызвать функцию GetType, используя следующий код:
const GUID *TemplateGUID = NULL; pData->GetType(&TemplateGUID);
После того как вы получили GUID, вы можете сравнить его с внешними GUID (например, с GUID стандартных или ваших специализированных шаблонов) и соответствующим образом обрабатывать данные. Например, для проверки является ли объект данных шаблоном "MeshNormals", вы можете использовать следующий код:
// TemplateGUID = GUID проверяемого шаблона if(*TemplateGUID == TID_D3DRMMeshNormals) { // Обработать шаблон MeshNormals
}
Конечно, знание GUID шаблона объекта может привести вас только сюда. Настоящим фокусом является получение данных объекта. Никаких проблем! Используя еще одну простую функцию, анализирующие способности будут практически завершены! Последняя используемая функция, позволяющая вам получать доступ к данным объекта, это GetData.
HRESULT IDirectXFileData::GetData(
LPCSTR szMember, // Установите в NULL
DWORD *pcbSize, // Размер данных
void **ppvData) ; // Указатель на данные
Для использования функции GetData вам необходимо предоставить указатель для доступа к буферу данных объекта и переменную DWORD, чтобы хранить размер буфера (в байтах). Вот небольшой код, который демонстрирует использование GetData для получения указателя на данные объекта и их размер.
char *DataPtr; DWORD DataSize;
pData->GetData(NULL, &DataSize, (void**)&DataPtr) ;
Указатель на буфер данных теперь указывает на непрерывный блок памяти, который имеет такую же структуру, как и определение шаблона объекта. Вы можете получить доступ к данным как к большому буферу или, если слукавить, можносоздать структуру, соответствующую определению шаблона, для более простого доступа. Например, предположим, что вы нашли стандартный шаблон ColorRGBA, который определен так:
template ColorRGBA {
<3 5FF44E0-6C7C-11cf-8F52-00403 33594A3> FLOAT red; FLOAT green;
FLOAT blue; FLOAT alpha;
}
Чтобы получить доступ к значениям red, green, blue и alpha, вам необходимо получить указатель и преобразовать его к типу float.
DWORD DataSize; float *DataPtr;
pData->GetData(NULL, &DataSize, (void**)&DataPtr); float red = *DataPtr++; float green = *DataPtr++; float blue = *DataPtr++; float alpha = *DataPtr++;
Хотя это нормальный подход, вы можете обрабатывать данные объекта более простым способом, используя соответствующую структуру С.
typedef struct {
float red, green, blue, alpha;
} sColorRGBA;
sColorRGBA *Color;
DWORD DataSize;
pData->GetData(NULL, &DataSize, (void**)&Color);
После реализации, предыдущий код дает вам возможность получать доступ к цветам, используя экземпляр структуры.
float red = Color->red; float blue = Color->blue; float green = Color->green; float alpha = Color->alpha;
Получать доступ к одиночным переменным просто, а как насчет строк и массивов? Массивы, как самый простой их двух случаев, хранятся непрерывно в памяти, что означает, что вы можете просто увеличивать указатель памяти, который содержит данные объекта. Например, нижеследующий код показывает, как получить доступ к массиву вещественных значений, хранимых в объекте, использующем шаблон FloatKeys.
Замечание. Обратите внимание, что GUID шаблона или имя класса не являются частью получаемыхданных, используя функциюIDirectXFileData::GetData.
/ / Получить размер данных объекта и указатель DWORD DataSize; DWORD *DataPtr;
pData->GetData(NULL, &DataSize, (void**)&DataPtr);
// Шаблон FloatKeys имеет значение DWORD вначале
// определяющее, как много вещественных значений в массиве
DWORD NumKeys = *DataPtr++;
// Next, an array of float values follows for(DWORD i=0;i<NumKeys;i++) {
float fValue = *(FLOAT*)DataPtr++;
Получить доступ к массивам оказалось не слишком сложно, а как насчет получения доступа к строкам? Опять же это простая работа, потому что строки хранятся как указатели на текстовые буферы, к которым вы можете получить доступ, как я сделал в следующем коде. (Я использую шаблон TextureFilename в качестве примера; он хранит имя файла текстуры.)
// Получить указатель на данные и их размер
DWORD DataSize; DWORD *DataPtr;
pData->GetData(NULL, &DataSize, (void**)&DataPtr);
// Получить доступ к текстовому буферу имени файла char *StringPtr = (char*)*DataPtr;
MessageBox(NULL, StringPtr, "Texture Filename", MB_OK);
Простым приведением указателя к типу char мы смогли отобразить имя файла, содержащегося в шаблоне TextureFilename. Я знаю, что теперь вы, наверное, кричите "почему я сразу не понял, как просто это?". Спокойно! Я тоже не сразу понял насколько просто работать с .X файлами. После того как секрет раскрыт, ничто не сможет остановить вас от использования .X файлов в ваших проектах. Вам просто необходимо реализовать всю функциональность анализатора .X в виде класса, еще более упростив работу с .X.
⇐Перечисление объектов данных || Оглавление || Создание класса .X анализатора⇒