// From F. Luna void LoadXFile(const std::wstring& filename, ID3DXMesh** meshOut, std::vector<Mtrl>& mtrls, std::vector<IDirect3DTexture9*>& texs) { // Step 1: Load the .x file from file into a system memory mesh. ID3DXMesh* meshSys = 0; ID3DXBuffer* adjBuffer = 0; ID3DXBuffer* mtrlBuffer = 0; DWORD numMtrls = 0; HR(D3DXLoadMeshFromX(filename.c_str(), D3DXMESH_SYSTEMMEM, g_app->m_pD3DDev, &adjBuffer, &mtrlBuffer, 0, &numMtrls, &meshSys), L"LoadXFile: D3DXLoadMeshFromX failed: "); // Step 2: Find out if the mesh already has normal info? D3DVERTEXELEMENT9 elems[MAX_FVF_DECL_SIZE]; HR(meshSys->GetDeclaration(elems),L"LoadXFile: GetDeclaration failed: "); bool hasNormals = false; D3DVERTEXELEMENT9 term = D3DDECL_END(); for(int i = 0; i < MAX_FVF_DECL_SIZE; ++i) { // Did we reach D3DDECL_END() {0xFF,0,D3DDECLTYPE_UNUSED, 0,0,0}? if(elems[i].Stream == 0xff ) break; if( elems[i].Type == D3DDECLTYPE_FLOAT3 && elems[i].Usage == D3DDECLUSAGE_NORMAL && elems[i].UsageIndex == 0 ) { hasNormals = true; break; } } // Step 3: Change vertex format to VertexPNT. D3DVERTEXELEMENT9 elements[64]; UINT numElements = 0; VertexPNT::Decl->GetDeclaration(elements, &numElements); ID3DXMesh* temp = 0; HR(meshSys->CloneMesh(D3DXMESH_SYSTEMMEM, elements, g_app->m_pD3DDev, &temp),L"LoadXFile: CloneMesh failed: "); ReleaseCOM(meshSys); meshSys = temp; // Step 4: If the mesh did not have normals, generate them. if( hasNormals == false) HR(D3DXComputeNormals(meshSys, 0),L"LoadXFile: D3DXComputeNormals failed: "); // Step 5: Optimize the mesh. //R(meshSys->Optimize(D3DXMESH_MANAGED | D3DXMESHOPT_COMPACT | D3DXMESHOPT_ATTRSORT | D3DXMESHOPT_VERTEXCACHE, // (DWORD*)adjBuffer->GetBufferPointer(), 0, 0, 0, meshOut), // L"LoadXFile: Optimize failed: "); *meshOut = meshSys; //ReleaseCOM(meshSys); // Done w/ system mesh. //ReleaseCOM(adjBuffer); // Done with buffer. // Step 6: Extract the materials and load the textures. if( mtrlBuffer != 0 && numMtrls != 0 ) { D3DXMATERIAL* d3dxmtrls = (D3DXMATERIAL*)mtrlBuffer->GetBufferPointer(); for(DWORD i = 0; i < numMtrls; ++i) { // Save the ith material. Note that the MatD3D property does not have an ambient // value set when its loaded, so just set it to the diffuse value. Mtrl m; m.ambient = d3dxmtrls[i].MatD3D.Diffuse; m.diffuse = d3dxmtrls[i].MatD3D.Diffuse; m.spec = d3dxmtrls[i].MatD3D.Specular; m.specPower = d3dxmtrls[i].MatD3D.Power; mtrls.push_back( m ); // Check if the ith material has an associative texture if( d3dxmtrls[i].pTextureFilename != 0 ) { // Yes, load the texture for the ith subset IDirect3DTexture9* tex = 0; std::wstring path = L"models/"; path.append(toWideString(d3dxmtrls[i].pTextureFilename,-1).c_str()); if(FAILED(D3DXCreateTextureFromFile(g_app->m_pD3DDev, path.c_str(), &tex))) { std::string error = "LoadXFile: D3DXCreateTextureFromFile Failed to load texture: "; error.append(toNarrowString(path.c_str(),-1)); throw std::runtime_error(error.c_str()); } texs.push_back( tex ); } else { // No texture for the ith subset texs.push_back( 0 ); } } } ReleaseCOM(mtrlBuffer); // done w/ buffer }