Direct3D для Visual C++ Урок 14. Вывод модели из x-файла
На предыдущих уроках мы с вами сами строили модели - например, для постоения модели куба мы вычислили положение 12 треугольников и. п. Все это мы делали ручками. А теперь представьте себе, что вы имеете дело с настоящей моделью - которая состоит из тысяч треугольников. Высчитывать их вершины вручную - неблагодарное дело. Поэтому это обычно делается так - модель рисует профессиональный 3D-художник в каком-нибудь 3D-редакторе - например, в 3D max'е. Потом модель конвертируется из формата 3D-редактора (3d max'а
в нашем случае) в специальный формат, который понимает DirectX - в так называемый x-файл. Т. е. x-файл и будет содержать нашу модель. Эта модель, кстати, называется меш (от английского mesh - сетка).
Назначение их следующее: pMesh - собственно наш меш, pBuffer - вспомогательный бефер, необходимый для создания меша, pMeshMaterial - материалы, использующиеся в меше, pMeshTextures - текстуры, использующиеся в меше, dwNum - число текстур и материалов меша.
В-третьих, нам надо написать отдельную функцию для инициализации меша (его зарузки и т. п.):
HRESULT InitMesh()
{
// Загрузка меша из файла.if(FAILED(D3DXLoadMeshFromX("tiger.x",
D3DXMESH_SYSTEMMEM, g_pd3dDevice, NULL, &pBuffer, NULL, &dwNum, &pMesh)))
{
return E_FAIL;
}
D3DXMATERIAL* d3dxMaterials = (D3DXMATERIAL*)pBuffer->GetBufferPointer();
// Выделение памяти для материалов и текстур.
pMeshMaterial = new D3DMATERIAL9[dwNum];
pMeshTextures = new LPDIRECT3DTEXTURE9[dwNum];
// Заполнение массивов для материалов и текстур данными.for (DWORD i = 0; i < dwNum; i++)
{
pMeshMaterial[i] = d3dxMaterials[i].MatD3D;
pMeshMaterial[i].Ambient = pMeshMaterial[i].Diffuse;
// Загрузка текстуры.if(FAILED(D3DXCreateTextureFromFile(g_pd3dDevice,
d3dxMaterials[i].pTextureFilename, &pMeshTextures[i])))
{
pMeshTextures[i] = NULL;
}
}
pBuffer->Release();
return S_OK;
}
Код должен быть ясен из комментария. Разумеется, x-файл, указанный в параметре функции D3DXLoadMeshFromX, должен существовать.
Следующий, четвертый шаг - это функция для непосредственного рисования меша. Вот ее текст:
VOID DrawMesh()
{
for (DWORD i = 0; i < dwNum; i++)
{
g_pd3dDevice->SetMaterial(&pMeshMaterial[i]);
g_pd3dDevice->SetTexture(0, pMeshTextures[i]);
pMesh->DrawSubset(i);
}
}
Обратите внимание, что для примитивов, из которых состоит наш меш, мы устанавливаем разные материалы и текстуры (такое случается часто для сложных моделей).
С написанием новых функций все. Теперь осталось эти функции где-то применить. InitMesh мы вызываем в WinMain:
int WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
...
if(!SUCCEEDED(InitD3D(hWnd)))
{
return 0;
}
InitMesh();
...
А DrawMesh - в функции Render (часть старого кода для рисования надо просто убрать):