The second load_mesh function is much like the first, except that
instead of loading an entire .X file into one D3DXMESHCONTAINER_EX object, you
are able to load a single mesh object (using the D3DXLoadSkinMeshFromXof
function) as pointed to by a ID3DXFileData object (used while parsing
an .X file). Here's the prototype:
HRESULT load_mesh(D3DXMESHCONTAINER_EX**
ret_mesh_container,
IDirect3DDevice9* device,
ID3DXFileData* xfile_data,
const char* texture_path,
DWORD new_fvf,
DWORD load_flags);
You'll notice that the xfile_data parameter is
here instead of the filename parameter used by the first LoadMesh function. The
xfile_data parameter is of the type
ID3DXFileData, which is an object that represents
the currently enumerated data object inside an .X file.
Calling the second load_mesh function is the same as calling the first (with
the exception of providing a pointer to the enumerated data object).
HRESULT load_mesh(D3DXMESHCONTAINER_EX** ret_mesh_container,
IDirect3DDevice9* device,
ID3DXFileData* xfile_data,
const char* texture_path,
DWORD new_fvf,
DWORD load_flags)
{
// error checking
if(ret_mesh_container == NULL || device == NULL || xfile_data == NULL || texture_path == NULL)
return E_FAIL;
// use system memory if converting FVF
if(new_fvf)
load_flags = D3DXMESH_SYSTEMMEM;
// load the mesh using D3DX routines
ID3DXMesh* mesh;
ID3DXSkinInfo* skin_info;
ID3DXBuffer* material_buffer;
ID3DXBuffer* adj_buffer;
DWORD num_materials;
HRESULT hr = D3DXLoadSkinMeshFromXof(xfile_data, load_flags, device, &adj_buffer, &material_buffer, NULL,
&num_materials, &skin_info, &mesh);
if(FAILED(hr))
return hr;
// free skin info if no bones
if(skin_info && skin_info->GetNumBones() == 0)
release_com(skin_info);
// convert to new FVF first as needed (not with skinned models)
if(new_fvf)
{
ID3DXMesh* clone_mesh;
hr = mesh->CloneMeshFVF(load_flags, new_fvf, device, &clone_mesh);
if(FAILED(hr))
{
release_com(mesh);
release_com(skin_info);
release_com(adj_buffer);
release_com(material_buffer);
return hr;
}
// free prior mesh and store new pointer
release_com(mesh);
mesh = clone_mesh; clone_mesh = NULL;
}
D3DXMESHCONTAINER_EX* mesh_container = new D3DXMESHCONTAINER_EX;
*ret_mesh_container = mesh_container;
// store mesh name (filename), type, and mesh pointer.
DWORD size;
xfile_data->GetName(NULL, &size);
if(size)
{
mesh_container->Name = new char[size];
xfile_data->GetName(mesh_container->Name, &size);
}
mesh_container->MeshData.Type = D3DXMESHTYPE_MESH;
mesh_container->MeshData.pMesh = mesh;
mesh_container->pSkinInfo = skin_info;
mesh = NULL;
skin_info = NULL;
// store adjacency information
DWORD adj_buffer_size = adj_buffer->GetBufferSize();
if(adj_buffer_size)
{
mesh_container->pAdjacency = (DWORD*) new char[adj_buffer_size];
memcpy(mesh_container->pAdjacency, adj_buffer->GetBufferPointer(), adj_buffer_size);
}
release_com(adj_buffer);
// create a duplicate mesh in case skinning is used
if(mesh_container->pSkinInfo)
{
mesh_container->MeshData.pMesh->CloneMeshFVF(0, mesh_container->MeshData.pMesh->GetFVF(), device,
&mesh_container->skin_mesh);
}
// build material list
mesh_container->NumMaterials = num_materials;
if(num_materials == 0)
{
// create a default material
mesh_container->NumMaterials = 1;
mesh_container->pMaterials = new D3DXMATERIAL[1];
mesh_container->textures = new IDirect3DTexture9*[1];
ZeroMemory(mesh_container->pMaterials, sizeof(D3DXMATERIAL));
mesh_container->pMaterials[0].MatD3D.Diffuse.r = 1.0f;
mesh_container->pMaterials[0].MatD3D.Diffuse.g = 1.0f;
mesh_container->pMaterials[0].MatD3D.Diffuse.b = 1.0f;
mesh_container->pMaterials[0].MatD3D.Diffuse.a = 1.0f;
mesh_container->pMaterials[0].MatD3D.Ambient = mesh_container->pMaterials[0].MatD3D.Diffuse;
mesh_container->pMaterials[0].MatD3D.Specular = mesh_container->pMaterials[0].MatD3D.Diffuse;
mesh_container->pMaterials[0].pTextureFilename = NULL;
mesh_container->textures[0] = NULL;
}
else
{
// load the materials
D3DXMATERIAL* xmaterials = (D3DXMATERIAL*) material_buffer->GetBufferPointer();
mesh_container->pMaterials = new D3DXMATERIAL[mesh_container->NumMaterials];
mesh_container->textures = new IDirect3DTexture9*[mesh_container->NumMaterials];
for(DWORD i = 0; i < mesh_container->NumMaterials; i++)
{
mesh_container->pMaterials[i].MatD3D = xmaterials[i].MatD3D;
mesh_container->pMaterials[i].MatD3D.Ambient = mesh_container->pMaterials[i].MatD3D.Diffuse;
mesh_container->textures[i] = NULL;
// load the texture if one exists
if(xmaterials[i].pTextureFilename)
{
char texture_file[MAX_PATH];
sprintf(texture_file, "%s%s", texture_path, xmaterials[i].pTextureFilename);
D3DXCreateTextureFromFile(device, texture_file, &mesh_container->textures[i]);
}
}
}
release_com(material_buffer);
mesh_container->MeshData.pMesh->OptimizeInplace(D3DXMESHOPT_ATTRSORT, NULL, NULL, NULL, NULL);
mesh_container = NULL;
return S_OK;
}