D3D Animation Basis(6)
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).
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;
}