Ejemplo n.º 1
0
//====================================================================================
// フレームの削除(XFileの各パーツ単位のこと 腕とか足とかのパーツ作るイメージ)
//====================================================================================
HRESULT CInheritanceHierarchy::DestroyFrame(LPD3DXFRAME pFrameToFree)
{
	SAFE_DELETE_ARRAY(pFrameToFree->Name);

	// 始まり
	if(pFrameToFree->pFrameFirstChild)
	{
		DestroyFrame(pFrameToFree->pFrameFirstChild);
	}

	// つながり
	if(pFrameToFree->pFrameSibling)
	{
		DestroyFrame(pFrameToFree->pFrameSibling);
	}

	// 大枠
	if(pFrameToFree->pMeshContainer)
	{
		DestroyMeshContainer(pFrameToFree->pMeshContainer);
	}

	SAFE_DELETE(pFrameToFree);
	return S_OK;
}
Ejemplo n.º 2
0
//フレーム削除
HRESULT MyAllocateHierarchy::DestroyFrame(THIS_ LPD3DXFRAME pFrameToFree)
{
	SDELETE(pFrameToFree->Name);

	if (pFrameToFree->pMeshContainer)
		DestroyMeshContainer(pFrameToFree->pMeshContainer);

	if (pFrameToFree->pFrameSibling)
		DestroyFrame(pFrameToFree->pFrameSibling);

	if (pFrameToFree->pFrameFirstChild)
		DestroyFrame(pFrameToFree->pFrameFirstChild);

	return D3D_OK;
}
Ejemplo n.º 3
0
//-----------------------------------------------------------------------------
// Desc: 在这里是调用了成员函数 GenerateGameSkinMesh(pMeshContainer);
//       是在这里加载了蒙皮信息
//-----------------------------------------------------------------------------
HRESULT DexAllocateHierarchy::CreateMeshContainer(LPCSTR Name, 
	CONST D3DXMESHDATA *pMeshData,
	CONST D3DXMATERIAL *pMaterials, 
	CONST D3DXEFFECTINSTANCE *pEffectInstances, 
	DWORD NumMaterials, 
	CONST DWORD *pAdjacency, 
	LPD3DXSKININFO pSkinInfo, 
	LPD3DXMESHCONTAINER *ppNewMeshContainer) 
{
	HRESULT hr;
	stDexMeshContainerEx *pMeshContainer = NULL;
	LPDIRECT3DDEVICE9 device = NULL;
	UINT NumFaces;
	UINT iMaterial;
	UINT iBone, cBones;

	LPD3DXMESH pMesh = NULL;

	*ppNewMeshContainer = NULL;

	// this sample does not handle patch meshes, so fail when one is found
	if (pMeshData->Type != D3DXMESHTYPE_MESH)
	{
		hr = E_FAIL;
		return hr;
	}

	// get the pMesh interface pointer out of the mesh data structure
	pMesh = pMeshData->pMesh;
	pMesh->GetDevice( &device );

	// this sample does not FVF compatible meshes, so fail when one is found
	if (pMesh->GetFVF() == 0)
	{
		hr = E_FAIL;
		return hr;
	}

	// allocate the overloaded structure to return as a D3DXMESHCONTAINER
	pMeshContainer = new stDexMeshContainerEx;
	if (pMeshContainer == NULL)
	{
		hr = E_OUTOFMEMORY;
		return hr;
	}
	memset(pMeshContainer, 0, sizeof(stDexMeshContainerEx));

	// make sure and copy the name.  All memory as input belongs to caller, interfaces can be addref'd though
	hr = AllocateName(Name, &pMeshContainer->Name);
	if (FAILED(hr))
	{
		if (pMeshContainer != NULL)
		{
			DestroyMeshContainer(pMeshContainer);
		}
		return hr;
	}

	NumFaces = pMesh->GetNumFaces();

	// if no normals are in the mesh, add them
	if (!(pMesh->GetFVF() & D3DFVF_NORMAL))
	{
		pMeshContainer->MeshData.Type = D3DXMESHTYPE_MESH;

		// clone the mesh to make room for the normals
		hr = pMesh->CloneMeshFVF( pMesh->GetOptions(), 
			pMesh->GetFVF() | D3DFVF_NORMAL, 
			device, &pMeshContainer->MeshData.pMesh );
		if (FAILED(hr))
		{
			if (pMeshContainer != NULL)
			{
				DestroyMeshContainer(pMeshContainer);
			}
			return hr;
		}

		// get the new pMesh pointer back out of the mesh container to use
		// NOTE: we do not release pMesh because we do not have a reference to it yet
		pMesh = pMeshContainer->MeshData.pMesh;

		// now generate the normals for the pmesh
		D3DXComputeNormals( pMesh, NULL );
	}
	else  // if no normals, just add a reference to the mesh for the mesh container
	{
		pMeshContainer->MeshData.pMesh = pMesh;
		pMeshContainer->MeshData.Type = D3DXMESHTYPE_MESH;

		pMesh->AddRef();
	}

	// allocate memory to contain the material information.  This sample uses
	//   the D3D9 materials and texture names instead of the EffectInstance style materials
	pMeshContainer->NumMaterials = max(1, NumMaterials);
	pMeshContainer->pMaterials = new D3DXMATERIAL[pMeshContainer->NumMaterials];
	pMeshContainer->ppTextures = new LPDIRECT3DTEXTURE9[pMeshContainer->NumMaterials];
	pMeshContainer->pAdjacency = new DWORD[NumFaces*3];
	if ((pMeshContainer->pAdjacency == NULL) || (pMeshContainer->pMaterials == NULL))
	{
		hr = E_OUTOFMEMORY;
		if (pMeshContainer != NULL)
		{
			DestroyMeshContainer(pMeshContainer);
		}
		return hr;
	}

	memcpy(pMeshContainer->pAdjacency, pAdjacency, sizeof(DWORD) * NumFaces*3);
	memset(pMeshContainer->ppTextures, 0, sizeof(LPDIRECT3DTEXTURE9) * pMeshContainer->NumMaterials);

	// if materials provided, copy them
	if (NumMaterials > 0)            
	{
		memcpy(pMeshContainer->pMaterials, pMaterials, sizeof(D3DXMATERIAL) * NumMaterials);

		for (iMaterial = 0; iMaterial < NumMaterials; iMaterial++)
		{
			if (pMeshContainer->pMaterials[iMaterial].pTextureFilename != NULL)
			{
				//TCHAR file[1000];
				//FindMediaFile(file,pMeshContainer->pMaterials[iMaterial].pTextureFilename);
				
				// 根据纹理的文件名创建纹理资源,如果创建失败,纹理指针必须赋成NULL
				// MessageNULL(file);
				//D3DXCreateTextureFromFileEx(device, file, 
				//	D3DX_DEFAULT_NONPOW2, 
				//	D3DX_DEFAULT_NONPOW2, 
				//	D3DX_FROM_FILE, 0, D3DFMT_UNKNOWN, D3DPOOL_MANAGED, 
				//	D3DX_FILTER_NONE, D3DX_FILTER_NONE, D3DCOLOR_XRGB(0,0,0), NULL, NULL, 
				//	&pMeshContainer->ppTextures[iMaterial]);
				string texname = "model/";  //轉到model文件夾中去找紋理
				texname += pMeshContainer->pMaterials[iMaterial].pTextureFilename;
				if( FAILED( D3DXCreateTextureFromFile( device, texname.c_str(),
					&pMeshContainer->ppTextures[iMaterial] ) ) )
				{
					getLog()->BeginLog();
					getLog()->Log(log_allert, "load model texture %s failed! \n", texname.c_str());
					pMeshContainer->ppTextures[iMaterial] = NULL;
					getLog()->EndLog();
				}

				// don't remember a pointer into the dynamic memory, just forget the name after loading
				pMeshContainer->pMaterials[iMaterial].pTextureFilename = NULL;
			}
		}
	}
	else // if no materials provided, use a default one
	{
		pMeshContainer->pMaterials[0].pTextureFilename = NULL;
		memset(&pMeshContainer->pMaterials[0].MatD3D, 0, sizeof(D3DMATERIAL9));
		pMeshContainer->pMaterials[0].MatD3D.Diffuse.r = 0.5f;
		pMeshContainer->pMaterials[0].MatD3D.Diffuse.g = 0.5f;
		pMeshContainer->pMaterials[0].MatD3D.Diffuse.b = 0.5f;
		pMeshContainer->pMaterials[0].MatD3D.Specular = pMeshContainer->pMaterials[0].MatD3D.Diffuse;
	}

	// if there is skinning information, save off the required data and then setup for HW skinning
	if (pSkinInfo != NULL)
	{
		// first save off the SkinInfo and original mesh data
		pMeshContainer->pSkinInfo = pSkinInfo;
		pSkinInfo->AddRef();

		pMeshContainer->pOrigMesh = pMesh;
		pMesh->AddRef();

		// Will need an array of offset matrices to move the vertices from the figure space to the bone's space
		cBones = pSkinInfo->GetNumBones();
		pMeshContainer->pBoneOffsetMatrices = new D3DXMATRIX[cBones];
		if (pMeshContainer->pBoneOffsetMatrices == NULL)
		{
			hr = E_OUTOFMEMORY;
			if (pMeshContainer != NULL)
			{
				DestroyMeshContainer(pMeshContainer);
			}
			return hr;
		}

		// get each of the bone offset matrices so that we don't need to get them later
		for (iBone = 0; iBone < cBones; iBone++)
		{
			pMeshContainer->pBoneOffsetMatrices[iBone] = *(pMeshContainer->pSkinInfo->GetBoneOffsetMatrix(iBone));
		}

		// GenerateGameSkinMesh will take the general skinning information and transform it to a HW friendly version
		hr = GenerateGameSkinMesh(device, pMeshContainer );
		if (FAILED(hr))
		{       
			if (pMeshContainer != NULL)
			{
				DestroyMeshContainer(pMeshContainer);
			}
			return hr;
		}
	}

	*ppNewMeshContainer = pMeshContainer;
	pMeshContainer = NULL;

	// call Destroy function to properly clean up the memory allocated 
	if (pMeshContainer != NULL)
	{
		DestroyMeshContainer(pMeshContainer);
	}
	return hr;
}
Ejemplo n.º 4
0
/*
==================
Callback called when a mesh data is encountered during the .x file load
Name - name of the Mesh (const char*)
meshData - the mesh data
materials - material array
effectInstances - effect files / settings for the mesh
numMaterials - number of materials in the mesh
adjacency - adjacency array
pSkinInfo - skin info.
etNewMeshContainer - output pointer to assign our newly created mesh container
==================
*/
HRESULT XMeshHierarchy::CreateMeshContainer(
    LPCSTR Name,
    CONST D3DXMESHDATA *meshData,
    CONST D3DXMATERIAL *materials,
    CONST D3DXEFFECTINSTANCE *effectInstances,
    DWORD numMaterials,
    CONST DWORD *adjacency,
    LPD3DXSKININFO pSkinInfo,
    LPD3DXMESHCONTAINER* retNewMeshContainer)
{
    // Create a mesh container structure to fill and initilaise to zero values
    // Note: I use my extended version of the structure (D3DXMESHCONTAINER_EXTENDED) defined in MeshStructures.h
    D3DXMESHCONTAINER_EXTENDED *newMeshContainer=new D3DXMESHCONTAINER_EXTENDED;
    ZeroMemory(newMeshContainer, sizeof(D3DXMESHCONTAINER_EXTENDED));

    // Always a good idea to initialise return pointer before proceeding
    *retNewMeshContainer = 0;

    // The mesh name (may be 0) needs copying over
    if (Name && strlen(Name))
    {
        newMeshContainer->Name = Debug->DuplicateCharString(Name);
    }
    else
    {

    }

    // The mesh type (D3DXMESHTYPE_MESH, D3DXMESHTYPE_PMESH or D3DXMESHTYPE_PATCHMESH)
    if (meshData->Type!=D3DXMESHTYPE_MESH)
    {
        // This demo does not handle mesh types other than the standard
        // Other types are D3DXMESHTYPE_PMESH (progressive mesh) and D3DXMESHTYPE_PATCHMESH (patch mesh)
        DestroyMeshContainer(newMeshContainer);
        return E_FAIL;
    }

    newMeshContainer->MeshData.Type = D3DXMESHTYPE_MESH;

    // Adjacency data - holds information about triangle adjacency, required by the ID3DMESH object
    DWORD dwFaces = meshData->pMesh->GetNumFaces();
    newMeshContainer->pAdjacency = new DWORD[dwFaces*3];
    memcpy(newMeshContainer->pAdjacency, adjacency, sizeof(DWORD) * dwFaces*3);

    // Get the Direct3D device, luckily this is held in the mesh itself (Note: must release it when done with it)
    LPDIRECT3DDEVICE9 pd3dDevice = 0;
    meshData->pMesh->GetDevice(&pd3dDevice);

    // Can just assign pointer and add a ref rather than need to clone
    newMeshContainer->MeshData.pMesh=meshData->pMesh;
    newMeshContainer->MeshData.pMesh->AddRef();

    // Create material and texture arrays. Note that I always want to have at least one
    newMeshContainer->NumMaterials = max (numMaterials, 1);
    newMeshContainer->exMaterials = new D3DMATERIAL9[newMeshContainer->NumMaterials];
    newMeshContainer->exTextures  = new LPDIRECT3DTEXTURE9[newMeshContainer->NumMaterials];

    ZeroMemory(newMeshContainer->exTextures, sizeof(LPDIRECT3DTEXTURE9) * newMeshContainer->NumMaterials);

    if (numMaterials > 0)
    {
        // Load all the textures and copy the materials over
        for(DWORD i = 0; i < numMaterials; ++i)
        {
            newMeshContainer->exTextures[i] = 0;
            newMeshContainer->exMaterials[i]=materials[i].MatD3D;

            if(materials[i].pTextureFilename)
            {
                char mTexturePath [2048];
                mTexturePath [0] = 0;
                strcat (mTexturePath, mPath);
                strcat (mTexturePath, "\\");
                strcat (mTexturePath, materials[i].pTextureFilename);

                // Use the D3DX function to load the texture
                if(FAILED(D3DXCreateTextureFromFile(pd3dDevice, mTexturePath,
                                                    &newMeshContainer->exTextures[i])))
                {
                    Debug->Header ("Could not load texture:", 3);
                    Debug->DataChar (mTexturePath, 1);
                    return 0;
                }
            }
        }
    }
    else
        // make a default material in the case where the mesh did not provide one
    {
        ZeroMemory(&newMeshContainer->exMaterials[0], sizeof( D3DMATERIAL9 ) );
        newMeshContainer->exMaterials[0].Diffuse.r = 0.5f;
        newMeshContainer->exMaterials[0].Diffuse.g = 0.5f;
        newMeshContainer->exMaterials[0].Diffuse.b = 0.5f;
        newMeshContainer->exMaterials[0].Specular = newMeshContainer->exMaterials[0].Diffuse;
        newMeshContainer->exTextures[0]=0;
    }


    // If there is skin data associated with the mesh copy it over
    if (pSkinInfo)
    {
        // save off the SkinInfo
        newMeshContainer->pSkinInfo = pSkinInfo;
        pSkinInfo->AddRef();

        // Need an array of offset matrices to move the vertices from the figure space to the bone's space
        UINT numBones = pSkinInfo->GetNumBones();
        newMeshContainer->exBoneOffsets = new D3DXMATRIX[numBones];

        // Create the arrays for the bones and the frame matrices
        newMeshContainer->exFrameCombinedMatrixPointer = new D3DXMATRIX*[numBones];

        // get each of the bone offset matrices so that we don't need to get them later
        for (UINT i = 0; i < numBones; i++)
            newMeshContainer->exBoneOffsets[i] = *(newMeshContainer->pSkinInfo->GetBoneOffsetMatrix(i));

        Debug->Header ("Mesh has skinning info. Number of bones is:", 3);
        Debug->DataInt (numBones, 1);

        // Note: in the Microsoft samples a GenerateSkinnedMesh function is called here in order to prepare
        // the skinned mesh data for optimial hardware acceleration. As mentioned in the notes this sample
        // does not do hardware skinning but instead uses software skinning.
    }
    else
    {
        Debug->Header ("Mesh has no skinning info", 1);

        // No skin info so 0 all the pointers
        newMeshContainer->pSkinInfo = 0;
        newMeshContainer->exBoneOffsets = 0;
        newMeshContainer->exSkinMesh = 0;
        newMeshContainer->exFrameCombinedMatrixPointer = 0;
    }

    // When we got the device we caused an internal reference count to be incremented
    // So we now need to release it
    pd3dDevice->Release();

    // The mesh may contain a reference to an effect file
    if (effectInstances)
    {
        if (effectInstances->pEffectFilename)
            Debug->Header ("This .x file references an effect file. Effect files are not handled by IndieLib", 1);
    }

    // Set the output mesh container pointer to our newly created one
    *retNewMeshContainer = newMeshContainer;

    return S_OK;
}
Ejemplo n.º 5
0
/**
 * \brief callback called when a mesh data is encountered during the .x file load
 * \param Name - name of the Mesh (const char*)
 * \param meshData - the mesh data
 * \param materials - material array
 * \param effectInstances - effect files / settings for the mesh
 * \param numMaterials - number of materials in the mesh
 * \param adjacency - adjacency array 
 * \param pSkinInfo - skin info.
 * \param retNewMeshContainer - output pointer to assign our newly created mesh container
 * \return success code
 * \author Keith Ditchburn \date 17 July 2005
*/
HRESULT CMeshHierarchy::CreateMeshContainer(
    LPCSTR Name,
    CONST D3DXMESHDATA *meshData,
    CONST D3DXMATERIAL *materials,
    CONST D3DXEFFECTINSTANCE *effectInstances,
    DWORD numMaterials,
    CONST DWORD *adjacency,
    LPD3DXSKININFO pSkinInfo,
    LPD3DXMESHCONTAINER* retNewMeshContainer)
{    
	// Create a mesh container structure to fill and initilaise to zero values
	// Note: I use my extended version of the structure (D3DXMESHCONTAINER_EXTENDED) defined in MeshStructures.h
	D3DXMESHCONTAINER_EXTENDED *newMeshContainer=new D3DXMESHCONTAINER_EXTENDED;
	ZeroMemory(newMeshContainer, sizeof(D3DXMESHCONTAINER_EXTENDED));

	// Always a good idea to initialise return pointer before proceeding
	*retNewMeshContainer = 0;

	// The mesh name (may be 0) needs copying over
	if (Name && strlen(Name))
	{
		newMeshContainer->Name=CUtility::DuplicateCharString(Name);
		CUtility::DebugString("Added mesh: "+ToString(Name)+"\n");
	}
	else
	{
		CUtility::DebugString("Added Mesh: no name given\n");
	}

	// The mesh type (D3DXMESHTYPE_MESH, D3DXMESHTYPE_PMESH or D3DXMESHTYPE_PATCHMESH)
	if (meshData->Type!=D3DXMESHTYPE_MESH)
	{
		// This demo does not handle mesh types other than the standard
		// Other types are D3DXMESHTYPE_PMESH (progressive mesh) and D3DXMESHTYPE_PATCHMESH (patch mesh)
		DestroyMeshContainer(newMeshContainer);
		return E_FAIL;
	}

	newMeshContainer->MeshData.Type = D3DXMESHTYPE_MESH;
	
	// Adjacency data - holds information about triangle adjacency, required by the ID3DMESH object
	DWORD dwFaces = meshData->pMesh->GetNumFaces();
	newMeshContainer->pAdjacency = new DWORD[dwFaces*3];
	memcpy(newMeshContainer->pAdjacency, adjacency, sizeof(DWORD) * dwFaces*3);
	
	// Get the Direct3D device, luckily this is held in the mesh itself (Note: must release it when done with it)
	LPDIRECT3DDEVICE9 pd3dDevice = 0;
	meshData->pMesh->GetDevice(&pd3dDevice);


	D3DVERTEXELEMENT9 decl[MAX_FVF_DECL_SIZE];
	meshData->pMesh->GetDeclaration(decl);

	HRESULT res;

	DWORD dwVertexStride = meshData->pMesh->GetNumBytesPerVertex ();
	DWORD dwNumDeclarations = 0;
	bool haveNormals = false;

	for (int i=0; (i < MAX_FVF_DECL_SIZE) && (decl[i].Stream != 0xFF); i++)	{
		if (decl[dwNumDeclarations].Usage == D3DDECLUSAGE_NORMAL) 
			haveNormals = true;
		if (decl[dwNumDeclarations].Usage == D3DDECLUSAGE_TANGENT) {
			dwNumDeclarations = 0;
			break;
		}
		dwNumDeclarations++;
	}

	if (dwNumDeclarations) {
		if (!haveNormals) {
			// normals	
			decl[dwNumDeclarations].Stream = 0;	
			decl[dwNumDeclarations].Offset = (WORD)dwVertexStride;	
			decl[dwNumDeclarations].Type = D3DDECLTYPE_FLOAT3;	
			decl[dwNumDeclarations].Method = D3DDECLMETHOD_DEFAULT;	
			decl[dwNumDeclarations].Usage = D3DDECLUSAGE_NORMAL;	
			decl[dwNumDeclarations].UsageIndex = 0;

			dwVertexStride += sizeof(float)*3;
			dwNumDeclarations++;

		}

		// tangent	
		decl[dwNumDeclarations].Stream = 0;	
		decl[dwNumDeclarations].Offset = (WORD)dwVertexStride;	
		decl[dwNumDeclarations].Type = D3DDECLTYPE_FLOAT3;	
		decl[dwNumDeclarations].Method = D3DDECLMETHOD_DEFAULT;	
		decl[dwNumDeclarations].Usage = D3DDECLUSAGE_TANGENT;	
		decl[dwNumDeclarations].UsageIndex = 0;

		dwNumDeclarations++;

		// ending element	
		memset (&decl[dwNumDeclarations], 0, sizeof(D3DVERTEXELEMENT9));	
		decl[dwNumDeclarations].Stream = 0xFF;	
		decl[dwNumDeclarations].Type = D3DDECLTYPE_UNUSED;
	}

	res = meshData->pMesh->CloneMesh(meshData->pMesh->GetOptions(),decl,pd3dDevice,&newMeshContainer->MeshData.pMesh); 
	assert(res == D3D_OK);

	if (!haveNormals) {
		res = D3DXComputeNormals(newMeshContainer->MeshData.pMesh,newMeshContainer->pAdjacency); // compute normals                                      
		assert(res == D3D_OK);
	}

	res = D3DXComputeTangent(newMeshContainer->MeshData.pMesh,0,0,1,TRUE,NULL); // compute tangent(u)                                       
	assert(res == D3D_OK);

	//newMeshContainer->MeshData.pMesh=meshData->pMesh;
	newMeshContainer->MeshData.pMesh->AddRef();

	// Create material and texture arrays. Note that I always want to have at least one
	newMeshContainer->NumMaterials = max(numMaterials,1);
	newMeshContainer->exMaterials = new D3DMATERIAL9[newMeshContainer->NumMaterials];
	newMeshContainer->exTextures  = new LPDIRECT3DTEXTURE9[newMeshContainer->NumMaterials];

	ZeroMemory(newMeshContainer->exTextures, sizeof(LPDIRECT3DTEXTURE9) * newMeshContainer->NumMaterials);

	if (numMaterials>0)
	{
		// Load all the textures and copy the materials over		
		for(DWORD i = 0; i < numMaterials; ++i)
		{
			newMeshContainer->exTextures[i] = 0;	
			newMeshContainer->exMaterials[i]=materials[i].MatD3D;

			if(materials[i].pTextureFilename)
			{
				std::string texturePath(materials[i].pTextureFilename);
				if (CUtility::FindFile(&texturePath))
				{
					// Use the D3DX function to load the texture
					if(FAILED(D3DXCreateTextureFromFile(pd3dDevice, texturePath.c_str(),
						&newMeshContainer->exTextures[i])))
					{
						CUtility::DebugString("Could not load texture: "+texturePath+"\n");					
					}
				}
				else
				{
					CUtility::DebugString("Could not find texture: "+ToString(materials[i].pTextureFilename)+"\n");					
				}
			}
		}
	}
	else    
	// make a default material in the case where the mesh did not provide one
    {
		ZeroMemory(&newMeshContainer->exMaterials[0], sizeof( D3DMATERIAL9 ) );
        newMeshContainer->exMaterials[0].Diffuse.r = 0.5f;
        newMeshContainer->exMaterials[0].Diffuse.g = 0.5f;
        newMeshContainer->exMaterials[0].Diffuse.b = 0.5f;
        newMeshContainer->exMaterials[0].Specular = newMeshContainer->exMaterials[0].Diffuse;
		newMeshContainer->exTextures[0]=0;
    }

	// If there is skin data associated with the mesh copy it over
	if (pSkinInfo)
	{
		// save off the SkinInfo
	    newMeshContainer->pSkinInfo = pSkinInfo;
	    pSkinInfo->AddRef();

	    // Need an array of offset matrices to move the vertices from the figure space to the bone's space
	    UINT numBones = pSkinInfo->GetNumBones();
	    newMeshContainer->exBoneOffsets = new D3DXMATRIX[numBones];

		// Create the arrays for the bones and the frame matrices
		newMeshContainer->exFrameCombinedMatrixPointer = new D3DXMATRIX*[numBones];

	    // get each of the bone offset matrices so that we don't need to get them later
	    for (UINT i = 0; i < numBones; i++)
	        newMeshContainer->exBoneOffsets[i] = *(newMeshContainer->pSkinInfo->GetBoneOffsetMatrix(i));

		CUtility::DebugString("Mesh has skinning info.\n Number of bones is: "+ToString(numBones)+"\n");
        // Note: in the Microsoft samples a GenerateSkinnedMesh function is called here in order to prepare
		// the skinned mesh data for optimial hardware acceleration. As mentioned in the notes this sample
		// does not do hardware skinning but instead uses software skinning.
	}
	else	
	{
		// No skin info so 0 all the pointers
		newMeshContainer->pSkinInfo = 0;
		newMeshContainer->exBoneOffsets = 0;
		newMeshContainer->exSkinMesh = 0;
		newMeshContainer->exFrameCombinedMatrixPointer = 0;
	}

	// When we got the device we caused an internal reference count to be incremented
	// So we now need to release it
	pd3dDevice->Release();

	// The mesh may contain a reference to an effect file
	if (effectInstances)
	{
		if (effectInstances->pEffectFilename)
			CUtility::DebugString("This .x file references an effect file. Effect files are not handled by this demo\n");
	}
	
	// Set the output mesh container pointer to our newly created one
	*retNewMeshContainer = newMeshContainer;    

	return S_OK;
}
Ejemplo n.º 6
0
//======================================================================
// <<<メッシュ コンテナ オブジェクトの割り当て要求の実装>>>
//	Name			 : [in] メッシュの名前
//	pMeshData		 : [in] メッシュデータ構造体へのポインタ
//	pMaterials		 : [in] メッシュに使うマテリアルの配列
//	pEffectInstances : [in] メッシュに使うエフェクトインスタンスの配列
//	NumMaterials	 : [in] マテリアル配列内のマテリアルの数
//	pAdjacency		 : [in] メッシュの隣接性配列
//	pSkinInfo		 : [in] スキンデータが見つかった場合のスキンメッシュオブジェクトへのポインタ
//	ppNewMeshContainer : [out, retval] 作成されたメッシュコンテナを返す
//======================================================================
HRESULT CAllocateHierarchy::CreateMeshContainer( LPCSTR Name, 
        CONST D3DXMESHDATA *pMeshData,
        CONST D3DXMATERIAL *pMaterials, 
        CONST D3DXEFFECTINSTANCE *pEffectInstances, 
        DWORD NumMaterials, 
        CONST DWORD *pAdjacency, 
        LPD3DXSKININFO pSkinInfo, 
        LPD3DXMESHCONTAINER *ppNewMeshContainer) 
{
	HRESULT hr = S_OK;

	*ppNewMeshContainer = NULL;

	// patch meshes を扱う事はできない
	if( pMeshData->Type != D3DXMESHTYPE_MESH )
	{
		return E_FAIL;
	}

	LPD3DXMESH pMesh = pMeshData->pMesh;

	// FVF で記述されたメッシュ以外は読めぬ
	if( pMesh->GetFVF() == 0 )
	{
		return E_FAIL;
	}

	UINT NumFaces = pMesh->GetNumFaces();

	// メッシュ作成
	CXMesh *pCXMesh	= NULL;
	
	try
	{
		pCXMesh = new CXMesh;
	}
	
	catch ( std::bad_alloc& )
	{
		// メモリが足りない
		return E_OUTOFMEMORY;
	}

	// 名前設定
	pCXMesh->SetName( Name );

	// メッシュタイプ設定
	pCXMesh->MeshData.Type = D3DXMESHTYPE_MESH;

	LPDIRECT3DDEVICE9 pD3DDevice = NULL;

	// デバイスを取得
	if( FAILED( pMesh->GetDevice( &pD3DDevice ) ) )
	{
		hr = E_FAIL;
		goto e_Exit;
	}

	// Xファイルに法線が無かったら計算で求める
	if( !( pMesh->GetFVF() & D3DFVF_NORMAL ) )
	{
		////FVFに法線を追加した新しいメッシュにする////
        hr = pMesh->CloneMeshFVF( pMesh->GetOptions(), 
                                  pMesh->GetFVF() | D3DFVF_NORMAL, 
                                  pD3DDevice, &pCXMesh->MeshData.pMesh );

        if( FAILED( hr ) )
		{
			goto e_Exit;
		}

		// 引数で渡されたメッシュへのポインタに新しいメッシュへのポインタをセット
		// pMeshへの参照はこの時点で存在しないので、ここではreleaseをかけない
		pMesh = pCXMesh->MeshData.pMesh;

		D3DXComputeNormals( pMesh, NULL );
	}
	
	// 法線があった
	else
	{
		// リファレンスを増やすだけ
		pCXMesh->MeshData.pMesh = pMesh;
		pMesh->AddRef();
	}

	// マテリアル用のメモリを確保
	pCXMesh->NumMaterials = max( 1, NumMaterials );

	try
	{
		pCXMesh->pMaterials		= new D3DXMATERIAL[pCXMesh->NumMaterials];
		pCXMesh->m_ppTextures	= new LPDIRECT3DTEXTURE9[pCXMesh->NumMaterials];
		pCXMesh->pAdjacency		= new DWORD[NumFaces * 3];
	}
	
	catch ( std::bad_alloc& )
	{
		// メモリが足りない
		goto e_Exit;
	}

	memcpy( pCXMesh->pAdjacency, pAdjacency, sizeof( DWORD ) * NumFaces * 3 );
	memset( pCXMesh->m_ppTextures, 0, sizeof( LPDIRECT3DTEXTURE9 ) * pCXMesh->NumMaterials );

	// マテリアルのコピー
	if( NumMaterials > 0 )
	{
		memcpy( pCXMesh->pMaterials, pMaterials, sizeof( D3DXMATERIAL ) * NumMaterials );

		for( UINT i=0; i<NumMaterials; i++ )
		{
			if( pCXMesh->pMaterials[i].pTextureFilename != NULL )
			{
				// テクスチャを読み込む
				if( FAILED( D3DXCreateTextureFromFileEx(
								pD3DDevice, pCXMesh->pMaterials[i].pTextureFilename, D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, D3DUSAGE_RENDERTARGET, D3DFMT_UNKNOWN, D3DPOOL_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, m_KeyColor, NULL, NULL,
								&pCXMesh->m_ppTextures[i] ) ) )
				{
					
					// 読み込み失敗
					pCXMesh->m_ppTextures[i] = NULL;
				}
				
				pD3DDevice->SetTexture(0, pCXMesh->m_ppTextures[i]);
				pD3DDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
				pD3DDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
				pD3DDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
				
				pD3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
				pD3DDevice->SetRenderState(D3DRS_ALPHATESTENABLE, true);
				pD3DDevice->SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_GREATER);
				pD3DDevice->SetRenderState(D3DRS_ALPHAREF, 8);
				
			}
		}
	}
	// マテリアルが無いので適当にセット
	else
	{
		pCXMesh->pMaterials[0].pTextureFilename = NULL;
		memset( &pCXMesh->pMaterials[0].MatD3D, 0, sizeof( D3DMATERIAL9 ) );
		pCXMesh->pMaterials[0].MatD3D.Diffuse.r = 0.5f;
		pCXMesh->pMaterials[0].MatD3D.Diffuse.g = 0.5f;
		pCXMesh->pMaterials[0].MatD3D.Diffuse.b = 0.5f;
		pCXMesh->pMaterials[0].MatD3D.Specular = pCXMesh->pMaterials[0].MatD3D.Diffuse;
	}

	// ワンスキン形式のXファイルだった時の処理
	if( pSkinInfo != NULL )
	{
		/* スキンメッシュ用の処理*/

		/*pSkinInfo と pMesh をセット*/
		pCXMesh->pSkinInfo = pSkinInfo;
		pSkinInfo->AddRef();
		
		pCXMesh->m_pOrigMesh = pMesh;
		pMesh->AddRef();

		/* Bone Offset Matrices 保存用のメモリを確保*/
		UINT NumBones = pSkinInfo->GetNumBones();

		try
		{
			pCXMesh->m_pBoneOffsetMatrices = new D3DXMATRIX[NumBones];
		}
		
		catch ( std::bad_alloc& )
		{
			// メモリが足りない
			goto e_Exit;
		}

		/*Bone Offset Matrices 読み込み*/
		for( UINT i = 0; i < NumBones; i++ )
		{
			//memcpy(&pCXMesh->m_pBoneOffsetMatrices[i], pCXMesh->pSkinInfo->GetBoneOffsetMatrix(i), sizeof(D3DMATRIX) );
			pCXMesh->m_pBoneOffsetMatrices[i] = *(pCXMesh->pSkinInfo->GetBoneOffsetMatrix( i ) );			
		}
		
		// ジェネレート処理
		hr = m_pModel->GenerateSkinnedMesh( m_pD3DX9, pCXMesh, m_MaxBlend );

		if( FAILED( hr ) )
		{
			goto e_Exit;
		}
		
	}

	// メッシュコンテナの割り当て。
	// CXMeshクラスは D3DXMESHCONTAINER を継承している
	*ppNewMeshContainer = pCXMesh;

	pCXMesh = NULL;

e_Exit:
	// 開放処理
	F_RELEASE( pD3DDevice );

	if( pCXMesh != NULL )
	{
		DestroyMeshContainer( pCXMesh );
	}

	return hr;
}
Ejemplo n.º 7
0
HRESULT CD3DAllocate::CreateMeshContainer(THIS_ LPCSTR name,
   CONST D3DXMESHDATA *mesh, CONST D3DXMATERIAL *mats,
   CONST D3DXEFFECTINSTANCE *effects, unsigned long numMats,
   CONST unsigned long *indices, LPD3DXSKININFO skin,
   LPD3DXMESHCONTAINER* outContainer)
{    
   stD3DContainerEx *meshCon = new stD3DContainerEx;
   ZeroMemory(meshCon, sizeof(stD3DContainerEx));

   *outContainer = NULL;
   meshCon->Name = NULL;

   if(name)
      {
         int len = strlen(name) + 1;

         meshCon->Name = new char[len];
         memcpy(meshCon->Name, name, len * sizeof(char));
      }

   if(mesh->Type != D3DXMESHTYPE_MESH)
      {
         // D3DXMESHTYPE_PMESH are progressive meshes.
         // D3DXMESHTYPE_PATCHMESH are patch meshes.
         // In this code we only handle normal meshes.
         DestroyMeshContainer(meshCon);
         return E_FAIL;
      }

   meshCon->MeshData.Type = D3DXMESHTYPE_MESH;

   // Copy indices.
   unsigned long numFaces = mesh->pMesh->GetNumFaces();
   meshCon->pAdjacency = new unsigned long[numFaces * 3];
   memcpy(meshCon->pAdjacency, indices, sizeof(unsigned long) * numFaces * 3);

   // Get D3D Device.
   LPDIRECT3DDEVICE9 d3dDevice = NULL;
   mesh->pMesh->GetDevice(&d3dDevice);

   // Get mesh's declaration.
   D3DVERTEXELEMENT9 elements[MAX_FVF_DECL_SIZE];
   if(FAILED(mesh->pMesh->GetDeclaration(elements)))
      return E_FAIL;

   // Clone mesh to get copy of mesh.
   mesh->pMesh->CloneMesh(D3DXMESH_MANAGED, elements, d3dDevice,
                          &meshCon->MeshData.pMesh);

   // Allocate materials and textures.
   meshCon->NumMaterials = max(numMats, 1);
   meshCon->mat = new D3DMATERIAL9[meshCon->NumMaterials];
   meshCon->textures  = new LPDIRECT3DTEXTURE9[meshCon->NumMaterials];
   ZeroMemory(meshCon->mat, sizeof(D3DMATERIAL9) * meshCon->NumMaterials);
   ZeroMemory(meshCon->textures, sizeof(LPDIRECT3DTEXTURE9) * meshCon->NumMaterials);

   if(numMats > 0)
      {
         // If any materials get them and any textures.
         for(unsigned long i = 0; i < numMats; ++i)
            {
               meshCon->textures[i] = NULL;	
               meshCon->mat[i] = mats[i].MatD3D;

               if(mats[i].pTextureFilename)
                  {
                     if(FAILED(D3DXCreateTextureFromFile(d3dDevice, mats[i].pTextureFilename,
                        &meshCon->textures[i]))) meshCon->textures[i] = NULL;
                  }
            }
      }
	else    
      {
         // Set to default material and null texture.
         ZeroMemory(&meshCon->mat[0], sizeof(D3DMATERIAL9));

         meshCon->mat[0].Diffuse.r = 0.5f;
         meshCon->mat[0].Diffuse.g = 0.5f;
         meshCon->mat[0].Diffuse.b = 0.5f;
         meshCon->mat[0].Specular = meshCon->mat[0].Diffuse;
         meshCon->textures[0] = NULL;
      }


   // Nullify.
   meshCon->pSkinInfo = NULL;
   meshCon->boneMatrices = NULL;

	if(skin)
	   {
	      // If skin mesh allocate and get bones.
         meshCon->pSkinInfo = skin;
         skin->AddRef();

         unsigned int numBones = skin->GetNumBones();
         meshCon->boneMatrices = new D3DXMATRIX*[numBones];
	   }

   // Release reference count.
   if(d3dDevice) d3dDevice->Release(); d3dDevice = NULL;

   *outContainer = meshCon;    

   return S_OK;
}
//-----------------------------------------------------------------------------
// Name: CMultiAnimAllocateHierarchy::CreateMeshContainer()
// Desc: Called by D3DX during the loading of a mesh hierarchy. At a minumum,
//       the app should allocate a D3DXMESHCONTAINER or a child of it and fill
//       in the members based on the parameters here.  The app can further
//       customize the allocation behavior here.  In our case, we initialize
//       m_amxBoneOffsets from the skin info for convenience reason.
//       Then we call ConvertToIndexedBlendedMesh to obtain a new mesh object
//       that's compatible with the palette size we have to work with.
//-----------------------------------------------------------------------------
HRESULT CMultiAnimAllocateHierarchy::CreateMeshContainer( THIS_
    LPCSTR Name,
    CONST D3DXMESHDATA *pMeshData,
    CONST D3DXMATERIAL *pMaterials,
    CONST D3DXEFFECTINSTANCE *pEffectInstances,
    DWORD NumMaterials,
    CONST DWORD *pAdjacency,
    LPD3DXSKININFO pSkinInfo, 
    LPD3DXMESHCONTAINER *ppNewMeshContainer )
{
    assert( m_pMA );

    * ppNewMeshContainer = NULL;

    HRESULT hr = S_OK;

    MultiAnimMC * pMC = new MultiAnimMC;
    if( pMC == NULL )
    { hr = E_OUTOFMEMORY; goto e_Exit; }

    ZeroMemory( pMC, sizeof( MultiAnimMC ) );

    // if this is a static mesh, exit early; we're only interested in skinned meshes
    if( pSkinInfo == NULL )
    {
        hr = S_OK;
        goto e_Exit;
    }

    // only support mesh type
    if( pMeshData->Type != D3DXMESHTYPE_MESH )
    { hr = E_FAIL; goto e_Exit; }

    if( Name )
        pMC->Name = (CHAR *) HeapCopy( (CHAR *) Name );
    else
        pMC->Name = (CHAR *) HeapCopy( "<no_name>" );

    // copy the mesh over
    pMC->MeshData.Type = pMeshData->Type;
    pMC->MeshData.pMesh = pMeshData->pMesh;
    pMC->MeshData.pMesh->AddRef();

    // copy adjacency over
    {
        DWORD dwNumFaces = pMC->MeshData.pMesh->GetNumFaces();
        pMC->pAdjacency = new DWORD[ 3 * dwNumFaces ];
        if( pMC->pAdjacency == NULL )
        { hr = E_OUTOFMEMORY; goto e_Exit; }

        CopyMemory( pMC->pAdjacency, pAdjacency, 3 * sizeof( DWORD ) * dwNumFaces );
    }

    // ignore effects instances
    pMC->pEffects = NULL;

    // alloc and copy materials
    pMC->NumMaterials = max( 1, NumMaterials );
    pMC->pMaterials = new D3DXMATERIAL           [ pMC->NumMaterials ];
    pMC->m_apTextures = new LPDIRECT3DTEXTURE9   [ pMC->NumMaterials ];
    if( pMC->pMaterials == NULL || pMC->m_apTextures == NULL )
    { hr = E_OUTOFMEMORY; goto e_Exit; }

    if( NumMaterials > 0 )
    {
        CopyMemory( pMC->pMaterials, pMaterials, NumMaterials * sizeof( D3DXMATERIAL ) );
        for( DWORD i = 0; i < NumMaterials; ++ i )
        {
            if( pMC->pMaterials[ i ].pTextureFilename )
            {
                // CALLBACK to get valid filename
                WCHAR sNewPath[ MAX_PATH ];
                WCHAR wszTexName[ MAX_PATH ];
                if( MultiByteToWideChar( CP_ACP, 0, pMC->pMaterials[ i ].pTextureFilename, -1, wszTexName, MAX_PATH ) == 0 )
                    pMC->m_apTextures[ i ] = NULL;
                else
                    if( SUCCEEDED( DXUTFindDXSDKMediaFileCch( sNewPath, MAX_PATH, wszTexName ) ) )
                    {
                        // create the D3D texture
                        if( FAILED( D3DXCreateTextureFromFile( m_pMA->m_pDevice,
                            sNewPath,
                            &pMC->m_apTextures[ i ] ) ) )
                            pMC->m_apTextures[ i ] = NULL;
                    }
                    else
                        pMC->m_apTextures[ i ] = NULL;
            }
            else
                pMC->m_apTextures[ i ] = NULL;
        }
    }
    else    // mock up a default material and set it
    {
        ZeroMemory( & pMC->pMaterials[ 0 ].MatD3D, sizeof( D3DMATERIAL9 ) );
        pMC->pMaterials[ 0 ].MatD3D.Diffuse.r = 0.5f;
        pMC->pMaterials[ 0 ].MatD3D.Diffuse.g = 0.5f;
        pMC->pMaterials[ 0 ].MatD3D.Diffuse.b = 0.5f;
        pMC->pMaterials[ 0 ].MatD3D.Specular = pMC->pMaterials[ 0 ].MatD3D.Diffuse;
        pMC->pMaterials[ 0 ].pTextureFilename = NULL;
    }

    // save the skininfo object
    pMC->pSkinInfo = pSkinInfo;
    pSkinInfo->AddRef();

    // Get the bone offset matrices from the skin info
    pMC->m_amxBoneOffsets = new D3DXMATRIX[ pSkinInfo->GetNumBones() ];
    if( pMC->m_amxBoneOffsets == NULL )
    { hr = E_OUTOFMEMORY; goto e_Exit; }
    {
        for( DWORD i = 0; i < pSkinInfo->GetNumBones(); ++ i )
            pMC->m_amxBoneOffsets[ i ] = * (D3DXMATRIX *) pSkinInfo->GetBoneOffsetMatrix( i );
    }

    //
    // Determine the palette size we need to work with, then call ConvertToIndexedBlendedMesh
    // to set up a new mesh that is compatible with the palette size.
    //
    {
        UINT iPaletteSize = 0;
        m_pMA->m_pEffect->GetInt( "MATRIX_PALETTE_SIZE", (INT *) & iPaletteSize );
        pMC->m_dwNumPaletteEntries = min( iPaletteSize, pMC->pSkinInfo->GetNumBones() );
    }

    // generate the skinned mesh - creates a mesh with blend weights and indices
    hr = pMC->pSkinInfo->ConvertToIndexedBlendedMesh( pMC->MeshData.pMesh,
        D3DXMESH_MANAGED | D3DXMESHOPT_VERTEXCACHE,
        pMC->m_dwNumPaletteEntries,
        pMC->pAdjacency,
        NULL,
        NULL,
        NULL,
        &pMC->m_dwMaxNumFaceInfls,
        &pMC->m_dwNumAttrGroups,
        &pMC->m_pBufBoneCombos,
        &pMC->m_pWorkingMesh );
    if( FAILED( hr ) )
        goto e_Exit;

    // Make sure the working set is large enough for this mesh.
    // This is a bone array used for all mesh containers as a working
    // set during drawing.  If one was created previously that isn't 
    // large enough for this mesh, we have to reallocate.
    if( m_pMA->m_dwWorkingPaletteSize < pMC->m_dwNumPaletteEntries )
    {
        if( m_pMA->m_amxWorkingPalette )
            delete [] m_pMA->m_amxWorkingPalette;

        m_pMA->m_dwWorkingPaletteSize = pMC->m_dwNumPaletteEntries;
        m_pMA->m_amxWorkingPalette = new D3DXMATRIX[ m_pMA->m_dwWorkingPaletteSize ];
        if( m_pMA->m_amxWorkingPalette == NULL )
        {
            m_pMA->m_dwWorkingPaletteSize = 0;
            hr = E_OUTOFMEMORY;
            goto e_Exit;
        }
    }

    // ensure the proper vertex format for the mesh
    {
        DWORD dwOldFVF = pMC->m_pWorkingMesh->GetFVF();
        DWORD dwNewFVF = ( dwOldFVF & D3DFVF_POSITION_MASK ) | D3DFVF_NORMAL | D3DFVF_TEX1 | D3DFVF_LASTBETA_UBYTE4;
        if( dwNewFVF != dwOldFVF )
        {
            LPD3DXMESH pMesh;
            hr = pMC->m_pWorkingMesh->CloneMeshFVF( pMC->m_pWorkingMesh->GetOptions(),
                dwNewFVF,
                m_pMA->m_pDevice,
                &pMesh );
            if( FAILED( hr ) )
                goto e_Exit;

            pMC->m_pWorkingMesh->Release();
            pMC->m_pWorkingMesh = pMesh;

            // if the loaded mesh didn't contain normals, compute them here
            if( ! ( dwOldFVF & D3DFVF_NORMAL ) )
            {
                hr = D3DXComputeNormals( pMC->m_pWorkingMesh, NULL );
                if( FAILED( hr ) )
                    goto e_Exit;
            }
        }
    }

    // Interpret the UBYTE4 as a D3DCOLOR.
    // The GeForce3 doesn't support the UBYTE4 decl type.  So, we convert any
    // blend indices to a D3DCOLOR semantic, and later in the shader convert
    // it back using the D3DCOLORtoUBYTE4() intrinsic.  Note that we don't
    // convert any data, just the declaration.
    D3DVERTEXELEMENT9 pDecl[ MAX_FVF_DECL_SIZE ];
    D3DVERTEXELEMENT9 * pDeclCur;
    hr = pMC->m_pWorkingMesh->GetDeclaration( pDecl );
    if( FAILED( hr ) )
        goto e_Exit;

    pDeclCur = pDecl;
    while( pDeclCur->Stream != 0xff )
    {
        if( ( pDeclCur->Usage == D3DDECLUSAGE_BLENDINDICES ) && ( pDeclCur->UsageIndex == 0 ) )
            pDeclCur->Type = D3DDECLTYPE_D3DCOLOR;
        pDeclCur++;
    }

    hr = pMC->m_pWorkingMesh->UpdateSemantics( pDecl );
    if( FAILED( hr ) )
        goto e_Exit;

e_Exit:

    if( FAILED( hr ) )
    {
        if( pMC )
            DestroyMeshContainer( pMC );
    }
    else
        * ppNewMeshContainer = pMC;

    return hr;
}
Ejemplo n.º 9
0
HRESULT AllocateHierarchy::CreateMeshContainer(
	LPCSTR Name,
	CONST D3DXMESHDATA *pMeshData,
	CONST D3DXMATERIAL *pMaterials,
	CONST D3DXEFFECTINSTANCE *pEffectInstances,
	DWORD NumMaterials,
	CONST DWORD *pAdjacency,
	LPD3DXSKININFO pSkinInfo,
	LPD3DXMESHCONTAINER *ppNewMeshContainer)
{
    HRESULT hr;
    D3DXMESHCONTAINER_DERIVED *pMeshContainer = NULL;
    UINT NumFaces;
    UINT iMaterial;
    UINT iBone, cBones;
    LPDIRECT3DDEVICE9 pd3dDevice = NULL;

    LPD3DXMESH pMesh = NULL;

    *ppNewMeshContainer = NULL;

    // this sample does not handle patch meshes, so fail when one is found
    if (pMeshData->Type != D3DXMESHTYPE_MESH)
    {
        hr = E_FAIL;
        goto e_Exit;
    }

    // get the pMesh interface pointer out of the mesh data structure
    pMesh = pMeshData->pMesh;

    // this sample does not FVF compatible meshes, so fail when one is found
    if (pMesh->GetFVF() == 0)
    {
        hr = E_FAIL;
        goto e_Exit;
    }

    // allocate the overloaded structure to return as a D3DXMESHCONTAINER
    pMeshContainer = new D3DXMESHCONTAINER_DERIVED;
    if (pMeshContainer == NULL)
    {
        hr = E_OUTOFMEMORY;
        goto e_Exit;
    }
    memset(pMeshContainer, 0, sizeof(D3DXMESHCONTAINER_DERIVED));

    // make sure and copy the name.  All memory as input belongs to caller, interfaces can be addref'd though
    hr = AllocateName(Name, &pMeshContainer->Name);
    if (FAILED(hr))
        goto e_Exit;        

    pMesh->GetDevice(&pd3dDevice);
    NumFaces = pMesh->GetNumFaces();

    // if no normals are in the mesh, add them
    if (!(pMesh->GetFVF() & D3DFVF_NORMAL))
    {
        pMeshContainer->MeshData.Type = D3DXMESHTYPE_MESH;

        // clone the mesh to make room for the normals
        hr = pMesh->CloneMeshFVF( pMesh->GetOptions(), 
                                    pMesh->GetFVF() | D3DFVF_NORMAL, 
                                    pd3dDevice, &pMeshContainer->MeshData.pMesh );
        if (FAILED(hr))
            goto e_Exit;

        // get the new pMesh pointer back out of the mesh container to use
        // NOTE: we do not release pMesh because we do not have a reference to it yet
        pMesh = pMeshContainer->MeshData.pMesh;

        // now generate the normals for the pmesh
        D3DXComputeNormals( pMesh, NULL );
    }
    else  // if no normals, just add a reference to the mesh for the mesh container
    {
        pMeshContainer->MeshData.pMesh = pMesh;
        pMeshContainer->MeshData.Type = D3DXMESHTYPE_MESH;

        pMesh->AddRef();
    }
        
    // allocate memory to contain the material information.  This sample uses
    //   the D3D9 materials and texture names instead of the EffectInstance style materials
    pMeshContainer->NumMaterials = max(1, NumMaterials);
    pMeshContainer->pMaterials = new D3DXMATERIAL[pMeshContainer->NumMaterials];
    pMeshContainer->ppTextures = new LPDIRECT3DTEXTURE9[pMeshContainer->NumMaterials];
    pMeshContainer->pAdjacency = new DWORD[NumFaces*3];
    if ((pMeshContainer->pAdjacency == NULL) || (pMeshContainer->pMaterials == NULL))
    {
        hr = E_OUTOFMEMORY;
        goto e_Exit;
    }

    memcpy(pMeshContainer->pAdjacency, pAdjacency, sizeof(DWORD) * NumFaces*3);
    memset(pMeshContainer->ppTextures, 0, sizeof(LPDIRECT3DTEXTURE9) * pMeshContainer->NumMaterials);

    // if materials provided, copy them
    if (NumMaterials > 0)            
    {
        memcpy(pMeshContainer->pMaterials, pMaterials, sizeof(D3DXMATERIAL) * NumMaterials);

        for (iMaterial = 0; iMaterial < NumMaterials; iMaterial++)
        {
            if (pMeshContainer->pMaterials[iMaterial].pTextureFilename != NULL)
            {
                string strTexturePath;
				string strFilename = _pSkinmesh->GetMeshname();
				strFilename = strFilename + "\\" + pMeshContainer->pMaterials[iMaterial].pTextureFilename;
				strTexturePath = MODEL_DIR(strFilename.c_str());
				if( FAILED( Moon_CreateTexture( pd3dDevice, const_cast<char*>(strTexturePath.c_str()), 
                                                        &pMeshContainer->ppTextures[iMaterial] ) ) )
                    pMeshContainer->ppTextures[iMaterial] = NULL;


                // don't remember a pointer into the dynamic memory, just forget the name after loading
                pMeshContainer->pMaterials[iMaterial].pTextureFilename = NULL;
            }
        }
    }
    else // if no materials provided, use a default one
    {
        pMeshContainer->pMaterials[0].pTextureFilename = NULL;
        memset(&pMeshContainer->pMaterials[0].MatD3D, 0, sizeof(D3DMATERIAL9));
        pMeshContainer->pMaterials[0].MatD3D.Diffuse.r = 0.5f;
        pMeshContainer->pMaterials[0].MatD3D.Diffuse.g = 0.5f;
        pMeshContainer->pMaterials[0].MatD3D.Diffuse.b = 0.5f;
        pMeshContainer->pMaterials[0].MatD3D.Specular = pMeshContainer->pMaterials[0].MatD3D.Diffuse;
    }

    // if there is skinning information, save off the required data and then setup for HW skinning
    if (pSkinInfo != NULL)
    {
        // first save off the SkinInfo and original mesh data
        pMeshContainer->pSkinInfo = pSkinInfo;
        pSkinInfo->AddRef();

        pMeshContainer->pOrigMesh = pMesh;
        pMesh->AddRef();

        // Will need an array of offset matrices to move the vertices from the figure space to the bone's space
        cBones = pSkinInfo->GetNumBones();
        pMeshContainer->pBoneOffsetMatrices = new D3DXMATRIX[cBones];
        if (pMeshContainer->pBoneOffsetMatrices == NULL)
        {
            hr = E_OUTOFMEMORY;
            goto e_Exit;
        }

        // get each of the bone offset matrices so that we don't need to get them later
        for (iBone = 0; iBone < cBones; iBone++)
        {
            pMeshContainer->pBoneOffsetMatrices[iBone] = *(pMeshContainer->pSkinInfo->GetBoneOffsetMatrix(iBone));
        }

        // GenerateSkinnedMesh will take the general skinning information and transform it to a HW friendly version
        hr = _pSkinmesh->GenerateSkinmesh(pMeshContainer);
        if (FAILED(hr))
            goto e_Exit;
    }

    *ppNewMeshContainer = pMeshContainer;
    pMeshContainer = NULL;
e_Exit:
    SAFE_RELEASE(pd3dDevice);

    // call Destroy function to properly clean up the memory allocated 
    if (pMeshContainer != NULL)
    {
        DestroyMeshContainer(pMeshContainer);
    }

    return hr;
}