Окно программы XFile
Рисунок 11.1. Окно программы XFile
В данном примере используются следующие глобальные переменные:
ID3DXMesh* Mesh = 0; std::vector<D3DMATERIAL9> Mtrls(0); std::vector<IDirect3DTexture9*> Textures(0);
Здесь мы объявляем объект ID3DXMesh, который будет использоваться для хранения данных сетки, загружаемых из X-файла. Мы также объявляем векторы материалов и текстур, которые будут хранить используемые в сетке материалы и текстуры.
Начнем с реализации нашей стандартной функции Setup. Сначала мы загружаем X-файл:
bool Setup() { HRESULT hr = 0;
// // Загрузка данных из X-файла // ID3DXBuffer* adjBuffer = 0; ID3DXBuffer* mtrlBuffer = 0; DWORD numMtrls = 0;
hr = D3DXLoadMeshFromX( "bigship1.x", D3DXMESH_MANAGED, Device, &adjBuffer, &mtrlBuffer, 0, &numMtrls, &Mesh);
if(FAILED(hr)) { ::MessageBox(0, "D3DXLoadMeshFromX() - FAILED", 0, 0); return false; }
После того, как данные из X-файла загружены мы должны перебрать все элементы массива D3DXMATERIAL и загрузить текстуры, на которые ссылается сетка:
// // Извлечение материалов и загрузка текстур //
if(mtrlBuffer != 0 && numMtrls != 0) { D3DXMATERIAL* mtrls=(D3DXMATERIAL*)mtrlBuffer-> GetBufferPointer();
for(int i = 0; i < numMtrls; i++) { // При загрузке в свойстве MatD3D не устанавливается // значение для фонового света, поэтому установим его сейчас mtrls[i].MatD3D.Ambient = mtrls[i].MatD3D.Diffuse;
// Сохраняем i-ый материал Mtrls.push_back(mtrls[i].MatD3D);
// Проверяем, связана ли с i-ым материалом текстура if( mtrls[i].pTextureFilename != 0 ) { // Да, загружаем текстуру для i-ой подгруппы IDirect3DTexture9* tex = 0; D3DXCreateTextureFromFile( Device, mtrls[i].pTextureFilename, &tex);
// Сохраняем загруженную текстуру Textures.push_back(tex); } else { // Нет текстуры для i-ой подгруппы Textures.push_back(0); } } } d3d::Release<ID3DXBuffer*>(mtrlBuffer); // закончили работу с буфером . . // Пропущен код, не относящийся к теме данной главы . // (т.е.
установка освещения, матриц вида и проекции и т.д.) . return true; } // конец функции Setup()
В функции Display мы в каждом кадре слегка разворачиваем сетку, чтобы она вращалась. Сетка визуализируется с помощью простого цикла, поскольку ее подгруппам присвоены номера, идущие в порядке 0, 1, 2, ..., n– 1, где n — это количество подгрупп:
bool Display(float timeDelta) { if(Device) { // // Обновление: поворот сетки //
static float y = 0.0f; D3DXMATRIX yRot; D3DXMatrixRotationY(&yRot, y); y += timeDelta;
if( y >= 6.28f ) y = 0.0f;
D3DXMATRIX World = yRot;
Device->SetTransform(D3DTS_WORLD, &World);
// // Визуализация //
Device->Clear(0, 0, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffffffff, 1.0f, 0);
Device->BeginScene();
for(int i = 0; i < Mtrls.size(); i++) { Device->SetMaterial(&Mtrls[i]); Device->SetTexture(0, Textures[i]); Mesh->DrawSubset(i); }
Device->EndScene(); Device->Present(0, 0, 0, 0); } return true; }