Exemplo n.º 1
0
// 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
}