STDMETHODIMP cAllocateHierarchy::CreateMeshContainer( THIS_ LPCSTR Name,
	CONST D3DXMESHDATA *pMeshData,
	CONST D3DXMATERIAL *pMaterials, 
	CONST D3DXEFFECTINSTANCE *pEffectInstances,
	DWORD NumMaterials,
	CONST DWORD *pAdjacency,
	LPD3DXSKININFO pSkinInfo,
	LPD3DXMESHCONTAINER *ppNewMeshContainer )
{
	ST_BONE_MESH* pBoneMesh = new ST_BONE_MESH;
	ZeroMemory(pBoneMesh, sizeof(ST_BONE_MESH));

	pBoneMesh->MeshData.Type = pMeshData->Type;
	assert(pMeshData->Type == D3DXMESHTYPE_MESH);
	pMeshData->pMesh->AddRef();
	pBoneMesh->MeshData.pMesh = pMeshData->pMesh;

	for (DWORD i = 0; i < NumMaterials; ++i)
	{
		pBoneMesh->vecMaterial.push_back(pMaterials[i].MatD3D);
		std::string sTextureFile("/");
		sTextureFile += std::string(pMaterials[i].pTextureFilename);
		LPDIRECT3DTEXTURE9 pTexture = g_pTextureManager->GetTexture(m_sFolder + sTextureFile);
		pBoneMesh->vecTexture.push_back(pTexture);
	}

	if(pAdjacency)
	{
		pBoneMesh->pAdjacency = new DWORD[pMeshData->pMesh->GetNumVertices()];
		memcpy(pBoneMesh->pAdjacency, pAdjacency, pMeshData->pMesh->GetNumVertices() * sizeof(DWORD));
	}
	pSkinInfo->AddRef();
	pBoneMesh->pSkinInfo = pSkinInfo;
	// step 1. pSkinInfo 저장
	// step 2. 원본 메쉬 복사
	// step 3. pSkinInfo->GetNumBones()를 통해 영향력을 미치는 모든 본에 대한 매트릭스 들을 세팅
	// ppBoneMatrixPtrs, pBoneOffsetMatrices, pCurrentBoneMatrices를 동적할당
	// step 4. 동적 할당된 pBoneOffsetMatrices 매트릭스에 값 저장.
	// pSkinInfo->GetBoneOffsetMatrix(i)
	
	*ppNewMeshContainer = pBoneMesh;

	return S_OK;
}
//-----------------------------------------------------------------------------
// 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;
}
Beispiel #3
0
//-----------------------------------------------------------------------------
// 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
                TCHAR sNewPath[ MAX_PATH ];
                TCHAR tszTexName[ MAX_PATH ];
                if( FAILED( DXUtil_ConvertAnsiStringToGenericCch( tszTexName,
                    pMC->pMaterials[ i ].pTextureFilename,
                    MAX_PATH ) ) )
                    pMC->m_apTextures[ i ] = NULL;
                else
                    if( SUCCEEDED( DXUtil_FindMediaFileCch( sNewPath, MAX_PATH, tszTexName ) ) )
                    {
                        // 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( ParaMaterial ) );
        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 Matrix4[ 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 ] = * (Matrix4 *) 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 Matrix4[ 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 Color.
    // The GeForce3 doesn't support the UBYTE4 decl type.  So, we convert any
    // blend indices to a Color 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;
}
Beispiel #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;
}
Beispiel #5
0
//---------------------------------
HRESULT CAllocateHierarchy::CreateMeshContainer (LPCSTR Name, const D3DXMESHDATA *pMeshData, \
		const D3DXMATERIAL *pMaterials,const D3DXEFFECTINSTANCE *pEffectInstances, \
		DWORD NumMaterials, const DWORD *pAdjacency, LPD3DXSKININFO pSkinInfo, \
		LPD3DXMESHCONTAINER *ppNewMeshContainer)
{
	DWORD i, j;
	D3DXMESHCONTAINER_DERIVED *pMeshContainer;
	LPD3DXMESH pMesh, pTempMesh;
	HRESULT hr = E_FAIL;

	*ppNewMeshContainer = NULL;

	//podporované su iba bezne meshe
	if (pMeshData->Type != D3DXMESHTYPE_MESH)
		return E_FAIL;

	//alokácia derivovanej štruktúry kvôli návratovej hodnote - LPD3DXMESHCONTAINER
	pMeshContainer = new D3DXMESHCONTAINER_DERIVED;
	if (pMeshContainer == NULL)
		return E_OUTOFMEMORY;

	pMesh = pMeshData->pMesh;
	pMesh->AddRef();

	pMeshContainer->NumMaterials = max (1, NumMaterials);
	pMeshContainer->dwNumPaintings = 1;
	pMeshContainer->dwNumCoords = 1;
	if (m_localData.xmlTextures)
	{
		const char *szTemp;
		if (szTemp = g_pXML->Attr (m_localData.xmlTextures, "paint_num"))
			pMeshContainer->dwNumPaintings = (DWORD)atoi (szTemp);
		if (szTemp = g_pXML->Attr (m_localData.xmlTextures, "coord_num"))
			pMeshContainer->dwNumCoords = (DWORD)atoi (szTemp);
	}
	pMeshContainer->dwNumPaintings = max (1, pMeshContainer->dwNumPaintings);
	pMeshContainer->dwNumCoords = max (1, pMeshContainer->dwNumCoords);
	if (pMeshContainer->dwNumPaintings <= m_localData.dwUseThisPainting)
		m_localData.dwUseThisPainting = 0;		// chyba, pozadovana painting-verzia nie je v xml definovana

	//////////////////////////////////////////////////////////////////////////
	// mesh cloning - tangent, binormal, tex. koordinaty - pocitaju sa len pre modely s viac ako jednou texturovou vrstvou
	if (pMeshContainer->dwNumCoords > 1)
	{
		const DWORD dwRealNumCoords = (pMesh->GetFVF() & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT;
		const int intTexCoordsToAdd = pMeshContainer->dwNumCoords - dwRealNumCoords;
		DWORD dwVertexStride = pMesh->GetNumBytesPerVertex ();

		D3DVERTEXELEMENT9 meshDeclaration[MAX_FVF_DECL_SIZE];
		if (SUCCEEDED (pMesh->GetDeclaration (meshDeclaration)))
		{
			DWORD dwNumDeclarations = 0;
			for (i=0; (i < MAX_FVF_DECL_SIZE) && (meshDeclaration[i].Stream != 0xFF); i++)
				dwNumDeclarations++;
			// pridanie deklaracie pre tangent
			meshDeclaration[dwNumDeclarations].Stream = 0;
			meshDeclaration[dwNumDeclarations].Offset = (WORD)dwVertexStride;
			meshDeclaration[dwNumDeclarations].Type = D3DDECLTYPE_FLOAT3;
			meshDeclaration[dwNumDeclarations].Method = D3DDECLMETHOD_DEFAULT;
			meshDeclaration[dwNumDeclarations].Usage = D3DDECLUSAGE_TANGENT;
			meshDeclaration[dwNumDeclarations].UsageIndex = 0;
			dwNumDeclarations++;
			// pridanie deklaracie pre binormal
			meshDeclaration[dwNumDeclarations].Stream = 0;
			meshDeclaration[dwNumDeclarations].Offset = (WORD)(dwVertexStride + 3*sizeof(float));
			meshDeclaration[dwNumDeclarations].Type = D3DDECLTYPE_FLOAT3;
			meshDeclaration[dwNumDeclarations].Method = D3DDECLMETHOD_DEFAULT;
			meshDeclaration[dwNumDeclarations].Usage = D3DDECLUSAGE_BINORMAL;
			meshDeclaration[dwNumDeclarations].UsageIndex = 0;
			dwNumDeclarations++;
			// pridanie texturovych koordinatov
			for (int k=0; k<intTexCoordsToAdd; k++)
			{
				meshDeclaration[dwNumDeclarations].Stream = 0;
				meshDeclaration[dwNumDeclarations].Offset = (WORD)(dwVertexStride + 6*sizeof(float) + k*2*sizeof(float));
				meshDeclaration[dwNumDeclarations].Type = D3DDECLTYPE_FLOAT2;
				meshDeclaration[dwNumDeclarations].Method = D3DDECLMETHOD_DEFAULT;
				meshDeclaration[dwNumDeclarations].Usage = D3DDECLUSAGE_TEXCOORD;
				meshDeclaration[dwNumDeclarations].UsageIndex = BYTE(k + dwRealNumCoords);
				dwNumDeclarations++;
			}
			// ukoncovaci element
			memset (&meshDeclaration[dwNumDeclarations], 0, sizeof(D3DVERTEXELEMENT9));
			meshDeclaration[dwNumDeclarations].Stream = 0xFF;
			meshDeclaration[dwNumDeclarations].Type = D3DDECLTYPE_UNUSED;

			if (FAILED (pMesh->CloneMesh (pMesh->GetOptions(), meshDeclaration, g_pD3DDevice, &pTempMesh)))
				goto e_Exit;

			pMesh->Release ();
			pMesh = pTempMesh;
		}

		//////////////////////////////////////////////////////////////////////////
		const DWORD	dwVertexCount = pMesh->GetNumVertices ();
		dwVertexStride = pMesh->GetNumBytesPerVertex ();

		// uprava koordinatov, ak je to potrebne
		for (i=dwRealNumCoords; i < pMeshContainer->dwNumCoords; i++)
		{
			LPVOID	pData;
			DWORD	dwUseThisCoords = 0xFFFFFFFF,dwTexCoordOffsetSrc = 0xFFFFFFFF, dwTexCoordOffsetDst = 0xFFFFFFFF;
			if (m_localData.xmlTextures)
			{
				ezxml_t pTextureTag, pCoordsTag;
				const char *szTemp;
				char szCoordsTag[16];
				if (pTextureTag = g_pXML->Child (m_localData.xmlTextures, "texture0"))
				{
					sprintf (szCoordsTag, "coords%u", i);
					if (pCoordsTag = g_pXML->Child (pTextureTag, szCoordsTag))
						if (szTemp = g_pXML->Attr (pCoordsTag, "usecoords"))
						{
							dwUseThisCoords = (DWORD) atoi (szTemp);
							if (dwUseThisCoords >= i) dwUseThisCoords = 0;
						}
				}
			}
			if ((i > dwRealNumCoords) && (dwUseThisCoords == 0xFFFFFFFF))
				dwUseThisCoords = 0;

			// ak je v xml definovany usecoords, tak kopirovat koordinaty
			if (dwUseThisCoords != 0xFFFFFFFF)
			{
				for (j=0; (j < MAX_FVF_DECL_SIZE) && (meshDeclaration[j].Stream != 0xFF); j++)
					if (meshDeclaration[j].Usage == D3DDECLUSAGE_TEXCOORD)
						if (meshDeclaration[j].UsageIndex == dwUseThisCoords)
							dwTexCoordOffsetSrc = meshDeclaration[j].Offset;
						else if (meshDeclaration[j].UsageIndex == i)
							dwTexCoordOffsetDst = meshDeclaration[j].Offset;
				if ((dwTexCoordOffsetSrc == 0xFFFFFFFF) || (dwTexCoordOffsetDst == 0xFFFFFFFF))
					continue;	// chyba

				if (SUCCEEDED (pMesh->LockVertexBuffer (0, &pData)))
				{
					LPBYTE pVertexData = (LPBYTE)pData;
					// kopirovanie koordinatov z vrstvy dwUseThisCoords
					for (j=0; j<dwVertexCount; j++)
					{
						memcpy ((pVertexData + dwTexCoordOffsetDst), (pVertexData + dwTexCoordOffsetSrc), 2*sizeof(float));
						pVertexData += dwVertexStride;
					}
					pMesh->UnlockVertexBuffer ();
				}
			}
		}
		// vypocet tangent a binormal
		if (!CalculateMeshTangents (pMesh, 1))
			g_pConsole->Message(MSG_CON_ERR, "MeshLoader: CalculateMeshTangents() function failed");
	}

	//////////////////////////////////////////////////////////////////////////
	// nacitanie informacii o materialoch a texturach z x suboru
	pMeshContainer->pMaterials	= new D3DXMATERIAL[pMeshContainer->NumMaterials];
	pMeshContainer->pTextures	= new LPDIRECT3DTEXTURE9 [pMeshContainer->NumMaterials * pMeshContainer->dwNumCoords * pMeshContainer->dwNumPaintings];
	pMeshContainer->p7MTmaterials = new DWORD [pMeshContainer->NumMaterials];

	if ((pMeshContainer->pMaterials == NULL) || (pMeshContainer->pTextures == NULL) || \
														(pMeshContainer->p7MTmaterials == NULL))
		{hr = E_OUTOFMEMORY; goto e_Exit;}
	memset (pMeshContainer->pMaterials, 0, sizeof(D3DXMATERIAL) * pMeshContainer->NumMaterials);
	memset (pMeshContainer->pTextures, 0, sizeof(LPDIRECT3DTEXTURE9) * pMeshContainer->NumMaterials * pMeshContainer->dwNumCoords * pMeshContainer->dwNumPaintings);
	memset (pMeshContainer->p7MTmaterials, 0xFF, sizeof(DWORD) * pMeshContainer->NumMaterials);

	// nacitanie materialov
	if (NumMaterials > 0)
	{
		for (i=0; i<NumMaterials; i++)
		{
			pMeshContainer->pMaterials[i].MatD3D = pMaterials[i].MatD3D;
			// do x suboru sa neexportuje udaj o ambient zlozke materialov, upravit podla potreby
			pMeshContainer->pMaterials[i].MatD3D.Ambient = D3DXCOLOR (1.0f, 1.0f, 1.0f, 1.0f);
			// vypnut Power ak nie je zadana Specular zlozka
			D3DCOLORVALUE &colorSpec = pMeshContainer->pMaterials[i].MatD3D.Specular;
			if ((colorSpec.r == 0) && (colorSpec.g == 0) && (colorSpec.b == 0))
				pMeshContainer->pMaterials[i].MatD3D.Power = 0.0f;

			// nacitanie 7mt materialu, ak je k danemu povrchu priradeny
			#define MATERIAL_FLOAT_TOLERANCE		0.001f
			for (j=0; j < m_localData.dw7mtMaterialsNum; j++)
				if (m_localData.Mesh7mtMaterials[j].sz7mtMaterialName != NULL)
				{
					// porovnanie textur ak su dostupne
					if ((m_localData.Mesh7mtMaterials[j].szTextureName != NULL) && (pMaterials[i].pTextureFilename != NULL))
						if (stricmp (m_localData.Mesh7mtMaterials[j].szTextureName, pMaterials[i].pTextureFilename) != 0)
							continue;
					// porovnanie materialov
					if (fabs (m_localData.Mesh7mtMaterials[j].material.rDif - pMaterials[i].MatD3D.Diffuse.r) > MATERIAL_FLOAT_TOLERANCE) continue;
					if (fabs (m_localData.Mesh7mtMaterials[j].material.gDif - pMaterials[i].MatD3D.Diffuse.g) > MATERIAL_FLOAT_TOLERANCE) continue;
					if (fabs (m_localData.Mesh7mtMaterials[j].material.bDif - pMaterials[i].MatD3D.Diffuse.b) > MATERIAL_FLOAT_TOLERANCE) continue;
					if (fabs (m_localData.Mesh7mtMaterials[j].material.aDif - pMaterials[i].MatD3D.Diffuse.a) > MATERIAL_FLOAT_TOLERANCE) continue;
					if (fabs (m_localData.Mesh7mtMaterials[j].material.rSpec - pMaterials[i].MatD3D.Specular.r) > MATERIAL_FLOAT_TOLERANCE) continue;
					if (fabs (m_localData.Mesh7mtMaterials[j].material.gSpec - pMaterials[i].MatD3D.Specular.g) > MATERIAL_FLOAT_TOLERANCE) continue;
					if (fabs (m_localData.Mesh7mtMaterials[j].material.bSpec - pMaterials[i].MatD3D.Specular.b) > MATERIAL_FLOAT_TOLERANCE) continue;
					if (fabs (m_localData.Mesh7mtMaterials[j].material.rEm - pMaterials[i].MatD3D.Emissive.r) > MATERIAL_FLOAT_TOLERANCE) continue;
					if (fabs (m_localData.Mesh7mtMaterials[j].material.gEm - pMaterials[i].MatD3D.Emissive.g) > MATERIAL_FLOAT_TOLERANCE) continue;
					if (fabs (m_localData.Mesh7mtMaterials[j].material.bEm - pMaterials[i].MatD3D.Emissive.b) > MATERIAL_FLOAT_TOLERANCE) continue;
					if (fabs (m_localData.Mesh7mtMaterials[j].material.specPower - pMaterials[i].MatD3D.Power) > MATERIAL_FLOAT_TOLERANCE) continue;

					// materialy su zhodne
					char szBuf[MAX_PATH] = "materials\\models\\";
					strcat (szBuf, m_localData.Mesh7mtMaterials[j].sz7mtMaterialName);
					// 7mt material loading
					pMeshContainer->p7MTmaterials[i] = g_pMaterialManager->LoadMaterial (szBuf);
					break;
				}
			// #######################################################
			// naèítanie textúr
			if ((pMaterials[i].pTextureFilename != NULL) && (pMaterials[i].pTextureFilename[0] != 0))
			{
				char szTag[16];
				ezxml_t	pTextureTag = NULL;
				DWORD dwTextureIdx = 0xFFFFFFFF;

				pMeshContainer->pMaterials[i].pTextureFilename = new char [strlen (pMaterials[i].pTextureFilename) + 1];
				strcpy (pMeshContainer->pMaterials[i].pTextureFilename, pMaterials[i].pTextureFilename);

				if (FindTextureIndexTagByName (m_localData.xmlTextures, pMaterials[i].pTextureFilename, dwTextureIdx))
				{
					sprintf (szTag, "texture%u", dwTextureIdx);
					pTextureTag = g_pXML->Child (m_localData.xmlTextures, szTag);
				}

				for (j=0; j < pMeshContainer->dwNumCoords; j++)		// pre jednotlive koordinaty
				{
					char szBuf[MAX_PATH] = "textures\\models\\";
					if (pTextureTag == NULL)		// pouzit texturu z x-suboru
					{
						strcat (szBuf, pMaterials[i].pTextureFilename);
						pMeshContainer->pTextures[ i * pMeshContainer->dwNumCoords * pMeshContainer->dwNumPaintings + j*pMeshContainer->dwNumPaintings + m_localData.dwUseThisPainting] = g_TextureLoader.CreateTexture (szBuf);
					}
					else
					{
						// ziskanie nazvu textury z xml suboru
						ezxml_t	pCoordsTag, pPaintingTag;
						sprintf (szTag, "coords%u", j);
						if (pCoordsTag = g_pXML->Child (pTextureTag, szTag))
						{
							sprintf (szTag, "painting%u", m_localData.dwUseThisPainting);
							if (pPaintingTag = g_pXML->Child (pCoordsTag, szTag))
								if (pPaintingTag->txt)
								{
									strcat (szBuf, pPaintingTag->txt);
									pMeshContainer->pTextures[ i * pMeshContainer->dwNumCoords * pMeshContainer->dwNumPaintings + j*pMeshContainer->dwNumPaintings + m_localData.dwUseThisPainting] = g_TextureLoader.CreateTexture (szBuf);
								}
						}
					}
				}
			}
		}
	}
	else	// nastavenie defaultneho materialu - Diffuse = 0.8, Specular = Emissive = 0.0, Ambient = 1.0
	{
		pMeshContainer->pMaterials[0].pTextureFilename = NULL;
		pMeshContainer->pMaterials[0].MatD3D.Ambient = D3DXCOLOR (1.0f, 1.0f, 1.0f, 1.0f);
		pMeshContainer->pMaterials[0].MatD3D.Diffuse = D3DXCOLOR (0.8f, 0.8f, 0.8f, 1.0f);
		pMeshContainer->pMaterials[0].MatD3D.Emissive = D3DXCOLOR (0.0f, 0.0f, 0.0f, 1.0f);
		pMeshContainer->pMaterials[0].MatD3D.Specular = pMeshContainer->pMaterials[0].MatD3D.Emissive;
		pMeshContainer->pMaterials[0].MatD3D.Power = 0.0f;
	}

/*
		// alokovanie pamäte pre materiály, textúry
		pMeshContainer->pMaterials = new D3DXMATERIAL[pMeshContainer->NumMaterials];
		pMeshContainer->pTextures = new LPDIRECT3DTEXTURE9[pMeshContainer->NumMaterials];
		if ((pMeshContainer->pMaterials == NULL) || (pMeshContainer->pTextures == NULL))
			{hr = E_OUTOFMEMORY; goto e_Exit;}
	
		//inicializácia textúr a materiálov
		memset(pMeshContainer->pTextures, 0, sizeof(LPDIRECT3DTEXTURE9) * pMeshContainer->NumMaterials);
		memset(pMeshContainer->pMaterials, 0, sizeof(D3DXMATERIAL) * pMeshContainer->NumMaterials);
	
		//ak sú dostupné materiály, tak sa kopírujú
		if (NumMaterials > 0)
		{
			for (UINT iMaterial = 0; iMaterial < NumMaterials; iMaterial++)
			{
				pMeshContainer->pMaterials[iMaterial].MatD3D = pMaterials[iMaterial].MatD3D;
				pMeshContainer->pMaterials[iMaterial].MatD3D.Ambient = D3DXCOLOR (1.0f, 1.0f, 1.0f, 1.0f);
				D3DCOLORVALUE &colorSpec = pMeshContainer->pMaterials[iMaterial].MatD3D.Specular;
				if ((colorSpec.r == 0) && (colorSpec.g == 0) && (colorSpec.b == 0))
					pMeshContainer->pMaterials[iMaterial].MatD3D.Power = 0.0f;
				if (pMaterials[iMaterial].pTextureFilename != NULL)
				{
					wsprintf (szBuf, "textures\\models\\%s", pMaterials[iMaterial].pTextureFilename);
					pMeshContainer->pTextures[iMaterial] = g_TextureLoader.CreateTexture (szBuf);
				}
			}
		}
		else		// ak nie je definovany žiaden materiál, potom sa nastavý defaultný
		{
			//Diffuse = Specular = 0.8, Ambient = 1.0
			pMeshContainer->pMaterials[0].pTextureFilename = NULL;
			pMeshContainer->pMaterials[0].MatD3D.Ambient = D3DXCOLOR (1.0f, 1.0f, 1.0f, 1.0f);
			pMeshContainer->pMaterials[0].MatD3D.Diffuse = D3DXCOLOR (0.8f, 0.8f, 0.8f, 1.0f);
			pMeshContainer->pMaterials[0].MatD3D.Emissive = D3DXCOLOR (0.0f, 0.0f, 0.0f, 1.0f);
			pMeshContainer->pMaterials[0].MatD3D.Specular = pMeshContainer->pMaterials[0].MatD3D.Diffuse;
			pMeshContainer->pMaterials[0].MatD3D.Power = 5.0f;
		}
*/
	

	//////////////////////////////////////////////////////////////////////////
	// nacitanie skin infa
	if (m_localData.bLoadSkinInfo && (pSkinInfo != NULL))
	{
		DWORD	dwNumBones;
		pMeshContainer->pSkinInfo = pSkinInfo;
		pSkinInfo->AddRef();
		// alokovanie pamate pre skin-info matice
		dwNumBones = pSkinInfo->GetNumBones();
		if (dwNumBones > 0)
		{
			pMeshContainer->pBoneInverseMatrices = new D3DXMATRIX[dwNumBones];
			pMeshContainer->ppBoneTransformMatrices = new D3DXMATRIX*[dwNumBones];
			if ((pMeshContainer->pBoneInverseMatrices == NULL) || \
						(pMeshContainer->ppBoneTransformMatrices == NULL))
				{hr = E_OUTOFMEMORY; goto e_Exit;}
			// nacitanie bone-offset matic
			for (DWORD iBone=0; iBone < dwNumBones; iBone++)
				pMeshContainer->pBoneInverseMatrices[iBone] = *(pSkinInfo->GetBoneOffsetMatrix(iBone));

			memset (pMeshContainer->ppBoneTransformMatrices, 0, sizeof(LPD3DXMATRIX) * dwNumBones);
		}

		//////////////////////////////////////////////////////////////////////////
		// upravy pre shader skinning
		pMeshContainer->NumPaletteEntries = min(MAX_SKIN_BONES, pMeshContainer->pSkinInfo->GetNumBones());

		if (FAILED (pMeshContainer->pSkinInfo->ConvertToIndexedBlendedMesh (
												pMesh,
												D3DXMESH_MANAGED | D3DXMESHOPT_VERTEXCACHE,
												pMeshContainer->NumPaletteEntries,
												pAdjacency,
												NULL, NULL, NULL,
												&pMeshContainer->NumInfl,
												&pMeshContainer->NumAttributeGroups,
												&pMeshContainer->pBoneCombinationBuf,
												&pTempMesh)))
			goto e_Exit;

		pMesh->Release ();
		pMesh = pTempMesh;
		pTempMesh = NULL;
	}

	//////////////////////////////////////////////////////////////////////////
	// optimalizacia
#ifdef MAKE_MESH_OPTIMIZATION
	if (pAdjacency)
	{
//		pMesh->GenerateAdjacency ()	 // ???
		pMesh->OptimizeInplace ( \
			D3DXMESHOPT_COMPACT | D3DXMESHOPT_ATTRSORT | D3DXMESHOPT_VERTEXCACHE, \
			pAdjacency, NULL, NULL, NULL);
	}
#endif

	//////////////////////////////////////////////////////////////////////////
	pMeshContainer->MeshData.pMesh = pMesh;
	pMeshContainer->MeshData.Type = D3DXMESHTYPE_MESH;

	*ppNewMeshContainer = pMeshContainer;
	return S_OK;

e_Exit:
	pMesh->Release ();
	SAFE_DELETE (pMeshContainer)
	return hr;
}
Beispiel #6
0
//-----------------------------------------------------------------------------
// Creates a new mesh container.
//-----------------------------------------------------------------------------
HRESULT AllocateHierarchy::CreateMeshContainer( THIS_ LPCSTR Name, CONST D3DXMESHDATA *pMeshData, CONST D3DXMATERIAL *pMaterials, CONST D3DXEFFECTINSTANCE *pEffectInstances, DWORD NumMaterials, CONST DWORD *pAdjacency, LPD3DXSKININFO pSkinInfo, LPD3DXMESHCONTAINER *ppNewMeshContainer )
{
	// Create the new mesh container and zero its memory.
	MeshContainer *meshContainer = new MeshContainer;
	ZeroMemory( meshContainer, sizeof( MeshContainer ) );

	// Copy the mesh's name.
	if( Name == NULL )
	{
		// There is no name, so create a unique name.
		static unsigned long nameCount = 0;
		char newName[32];
		sprintf( newName, "unknown_mesh_%d", nameCount );
		nameCount++;

		meshContainer->Name = new char[strlen( newName ) + 1];
		strcpy( meshContainer->Name, newName );
	}
	else
	{
		meshContainer->Name = new char[strlen( Name ) + 1];
		strcpy( meshContainer->Name, Name );
	}

	// Check if the mesh has any materials.
	if( ( meshContainer->NumMaterials = NumMaterials ) > 0 )
	{
		// Allocate some memory for the mesh's materials, and their names (i.e. texture names).
		meshContainer->materials = new Material*[meshContainer->NumMaterials];
		meshContainer->materialNames = new char*[meshContainer->NumMaterials];

		// Store all the material (texture) names.
		for( unsigned long m = 0; m < NumMaterials; m++ )
		{
			if( pMaterials[m].pTextureFilename )
			{
				meshContainer->materialNames[m] = new char[strlen( pMaterials[m].pTextureFilename ) + 1];
				memcpy( meshContainer->materialNames[m], pMaterials[m].pTextureFilename, ( strlen( pMaterials[m].pTextureFilename ) + 1 ) * sizeof( char ) );
			}
			else
				meshContainer->materialNames[m] = NULL;

			meshContainer->materials[m] = NULL;
		}
	}

	// Store the mesh's adjacency information.
	meshContainer->pAdjacency = new DWORD[pMeshData->pMesh->GetNumFaces() * 3];
	memcpy( meshContainer->pAdjacency, pAdjacency, sizeof( DWORD ) * pMeshData->pMesh->GetNumFaces() * 3 );

	// Store the mesh data.
	meshContainer->MeshData.pMesh = meshContainer->originalMesh = pMeshData->pMesh;
	meshContainer->MeshData.Type = D3DXMESHTYPE_MESH;
	pMeshData->pMesh->AddRef();
	pMeshData->pMesh->AddRef();

	// Check if this mesh is a skinned mesh.
	if( pSkinInfo != NULL )
	{
		// Store the skin information and the mesh data.
		meshContainer->pSkinInfo = pSkinInfo;
		pSkinInfo->AddRef();

		// Clone the original mesh to create the skinned mesh.
		meshContainer->originalMesh->CloneMeshFVF( D3DXMESH_MANAGED, meshContainer->originalMesh->GetFVF(), Engine::GetInstance()->GetDevice(), &meshContainer->MeshData.pMesh );

		// Store the attribute table.
		meshContainer->MeshData.pMesh->GetAttributeTable( NULL, &meshContainer->totalAttributeGroups );
		meshContainer->attributeTable = new D3DXATTRIBUTERANGE[meshContainer->totalAttributeGroups];
		meshContainer->MeshData.pMesh->GetAttributeTable( meshContainer->attributeTable, NULL );
	}

	*ppNewMeshContainer = meshContainer;

	return S_OK;
}
Beispiel #7
0
HRESULT BoneHierarchyLoader::CreateMeshContainer(LPCSTR Name,
        CONST D3DXMESHDATA *pMeshData,
        CONST D3DXMATERIAL *pMaterials,
        CONST D3DXEFFECTINSTANCE *pEffectInstances,
        DWORD NumMaterials,
        CONST DWORD *pAdjacency,
        LPD3DXSKININFO pSkinInfo,
        LPD3DXMESHCONTAINER *ppNewMeshContainer) {
    //Create new Bone Mesh
    BoneMesh *boneMesh = new BoneMesh;
    memset(boneMesh, 0, sizeof(BoneMesh));

    //Get mesh data
    boneMesh->OriginalMesh = pMeshData->pMesh;
    boneMesh->MeshData.pMesh = pMeshData->pMesh;
    boneMesh->MeshData.Type = pMeshData->Type;
    pMeshData->pMesh->AddRef();     //Add Reference so that the mesh isnt deallocated
    IDirect3DDevice9 *g_pDevice = NULL;
    pMeshData->pMesh->GetDevice(&g_pDevice);    //Get g_pDevice ptr from mesh

    //Copy materials and load textures (just like with a static mesh)
    for (int i=0; i<(int)NumMaterials; i++) {
        D3DXMATERIAL mtrl;
        memcpy(&mtrl, &pMaterials[i], sizeof(D3DXMATERIAL));
        boneMesh->materials.push_back(mtrl.MatD3D);
        IDirect3DTexture9* newTexture = NULL;

        if (mtrl.pTextureFilename != NULL) {
            char textureFname[200];
            strcpy(textureFname, "resources/meshes/");
            strcat(textureFname, mtrl.pTextureFilename);

            //Load texture
            D3DXCreateTextureFromFile(g_pDevice, textureFname, &newTexture);
        }

        boneMesh->textures.push_back(newTexture);
    }

    if (pSkinInfo != NULL) {
        //Get Skin Info
        boneMesh->pSkinInfo = pSkinInfo;
        pSkinInfo->AddRef();    //Add reference so that the SkinInfo isnt deallocated

        //Clone mesh and store in boneMesh->MeshData.pMesh
        pMeshData->pMesh->CloneMeshFVF(D3DXMESH_MANAGED, pMeshData->pMesh->GetFVF(),
                                       g_pDevice, &boneMesh->MeshData.pMesh);

        //Get Attribute Table
        boneMesh->MeshData.pMesh->GetAttributeTable(NULL, &boneMesh->NumAttributeGroups);
        boneMesh->attributeTable = new D3DXATTRIBUTERANGE[boneMesh->NumAttributeGroups];
        boneMesh->MeshData.pMesh->GetAttributeTable(boneMesh->attributeTable, NULL);

        //Create bone offset and current matrices
        int NumBones = pSkinInfo->GetNumBones();
        boneMesh->boneOffsetMatrices = new D3DXMATRIX[NumBones];
        boneMesh->currentBoneMatrices = new D3DXMATRIX[NumBones];

        //Get bone offset matrices
        for (int i=0; i < NumBones; i++)
            boneMesh->boneOffsetMatrices[i] = *(boneMesh->pSkinInfo->GetBoneOffsetMatrix(i));
    }

    //Set ppNewMeshContainer to the newly created boneMesh container
    *ppNewMeshContainer = boneMesh;

    return S_OK;
}
//====================================================================================
// メッシュコンテナの作成(XFileの各パーツの集合)ようはスキンメッシュモデルをここで作る
//====================================================================================
HRESULT CInheritanceHierarchy::CreateMeshContainer(LPCSTR Name, CONST D3DXMESHDATA* pMeshData,
													CONST D3DXMATERIAL* pMaterials, CONST D3DXEFFECTINSTANCE* pEffectInstances,
													DWORD NumMaterials, CONST DWORD *pAdjacency, LPD3DXSKININFO pSkinInfo, 
													LPD3DXMESHCONTAINER *ppMeshContainer )
{
	//========================================================================
	// コンテナ作成に当たって必要な変数を用意
	//========================================================================
	MYMESHCONTAINER *pMeshContainer = NULL;
	int iFacesAmount;
	DWORD iMaterial;
	LPDIRECT3DDEVICE9 pDevice = NULL;
	LPD3DXMESH pMesh = NULL;
	*ppMeshContainer = NULL;
	DWORD dwBoneNum=0;

	//========================================================================
	// コンテナを動的確保して値を入れていく作業へ
	//========================================================================
	pMesh = pMeshData->pMesh;
	pMeshContainer = new MYMESHCONTAINER;

	//メモリ不足のときは終了
	if (pMeshContainer == NULL)
	{
		return E_OUTOFMEMORY;
	}

	//作成に成功したら中身を0で初期化しておく
	ZeroMemory(pMeshContainer, sizeof(MYMESHCONTAINER));

	//メッシュコンテナとしてXFileでつけられてる名前を拾う
	pMeshContainer->Name=new TCHAR[lstrlen(Name) + 1];	// \0分の+1

	//名前がなかったらおかしいので終了
	if (!pMeshContainer->Name)
	{
		return E_FAIL;
	}

	//名前があるならそれにする
	strcpy(pMeshContainer->Name,Name);

	// デバイスゲット
	pMesh->GetDevice(&pDevice);

	// 面の数ゲット
	iFacesAmount = pMesh->GetNumFaces();

	pMeshContainer->MeshData.pMesh = pMesh;
	pMeshContainer->MeshData.Type = D3DXMESHTYPE_MESH;

	//通常メッシュの場合はこれが必要。スキンの場合、これをするとメモリリークになる。
	if (pSkinInfo == NULL)
	{
		pMesh->AddRef();
	}

	//メッシュのマテリアル設定
	pMeshContainer->NumMaterials = max(1, NumMaterials);
	pMeshContainer->pMaterials = new D3DXMATERIAL[pMeshContainer->NumMaterials];
	pMeshContainer->ppTextures = new LPDIRECT3DTEXTURE9[pMeshContainer->NumMaterials];
	pMeshContainer->pAdjacency = new DWORD[iFacesAmount * NUM_POLYGON_CREATE_TRIANGLE];

	//隣接性情報またはマテリアルがなければ終了
	if( pMeshContainer->pAdjacency == NULL
	||	pMeshContainer->pMaterials == NULL )
	{
		return E_FAIL;
	}

	//情報をメッシュコンテナに流し込む
	memcpy(pMeshContainer->pAdjacency, pAdjacency, sizeof(DWORD) * iFacesAmount * NUM_POLYGON_CREATE_TRIANGLE);
	memset(pMeshContainer->ppTextures, 0, sizeof(LPDIRECT3DTEXTURE9) * pMeshContainer->NumMaterials);

	//========================================================================
	//該当メッシュがスキン情報を持っている場合
	//========================================================================
	if (pSkinInfo != NULL)
	{
		pMeshContainer->pSkinInfo = pSkinInfo;
		pSkinInfo->AddRef();
		dwBoneNum = pSkinInfo->GetNumBones();
		pMeshContainer->pBoneOffsetMatrices = new D3DXMATRIX[dwBoneNum];
		for (DWORD i = 0; i < dwBoneNum; i++)
		{
			memcpy(&pMeshContainer->pBoneOffsetMatrices[i], pMeshContainer->pSkinInfo->GetBoneOffsetMatrix(i), sizeof(D3DMATRIX));
		}

		// インデックスつきのものに変換   シェーダー使わないやつとは別なので注意
		if (FAILED(pMeshContainer->pSkinInfo->ConvertToIndexedBlendedMesh(pMesh,
			NULL,
			dwBoneNum,
			pMeshContainer->pAdjacency,
			NULL,
			NULL,
			NULL,
			&pMeshContainer->dwWeight,
			&pMeshContainer->dwBoneNum,
			&pMeshContainer->pBoneBuffer,
			&pMeshContainer->MeshData.pMesh)))
		{
			return E_FAIL;
		}

		// コンバート
		ConvertMesh(&pMeshContainer->MeshData.pMesh);

		D3DVERTEXELEMENT9 elements[] =
		{
			// 頂点ストリーム(パイプライン)番号, オフセット(頂点の型の先頭からのバイト数), データ型, DEFAULTでOK, 使用用途, 使用用途が同じものを複数使うときに仕分ける番号
			{ 0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0 },
			{ 0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_BLENDWEIGHT, 0 },
			{ 0, 24, D3DDECLTYPE_UBYTE4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_BLENDINDICES, 0 },
			{ 0, 28, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0 },
			{ 0, 40, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0 },
			{ 0, 48, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0 },
			D3DDECL_END()																					// 定義終了 絶対必要
		};
		pMeshContainer->pSkinInfo->SetDeclaration(elements);
	}

	//========================================================================
	// モデルのマテリアル情報
	//========================================================================
	if (NumMaterials > 0)
	{
		memcpy(pMeshContainer->pMaterials, pMaterials, sizeof(D3DXMATERIAL) * NumMaterials);

		for (iMaterial = 0; iMaterial < NumMaterials; iMaterial++)
		{
			// マテリアルのディフーズ色を強制的に変更
			pMeshContainer->pMaterials[iMaterial].MatD3D.Diffuse = DEFAULT_POLYGON_COLOR;

			if (pMeshContainer->pMaterials[iMaterial].pTextureFilename != NULL)
			{
				TCHAR strTexturePath[MAX_PATH];
				strcpy( strTexturePath,TEX_FOLDER_PATH);
				strcat_s( strTexturePath, sizeof( char ) * MAX_LENGTH_FILE_PATH, pMeshContainer->pMaterials[iMaterial].pTextureFilename );
				if (FAILED(D3DXCreateTextureFromFile(pDevice, strTexturePath,
					&pMeshContainer->ppTextures[iMaterial])))
				{
					pMeshContainer->ppTextures[iMaterial] = NULL;
					pMeshContainer->pMaterials[iMaterial].pTextureFilename = NULL;
				}
			}
		}
	}
	else
	{
		pMeshContainer->pMaterials[0].pTextureFilename = NULL;
		memset(&pMeshContainer->pMaterials[0].MatD3D, 0, sizeof(D3DMATERIAL9));
		pMeshContainer->pMaterials[0].MatD3D.Diffuse.r = COLOR_OF_NOT_EXIST_MATERIAL.r;
		pMeshContainer->pMaterials[0].MatD3D.Diffuse.g = COLOR_OF_NOT_EXIST_MATERIAL.g;
		pMeshContainer->pMaterials[0].MatD3D.Diffuse.b = COLOR_OF_NOT_EXIST_MATERIAL.b;
		pMeshContainer->pMaterials[0].MatD3D.Specular = pMeshContainer->pMaterials[0].MatD3D.Diffuse;
	}

	//ローカルに生成したメッシュコンテナーを呼び出し側にコピーする (コピーじゃないけど・・・)
	*ppMeshContainer = pMeshContainer;

	//参照カウンタを増やしたので減らす
	SAFE_RELEASE(pDevice);
	return S_OK;
}
/**
 * \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;
}
//======================================================================
// <<<メッシュ コンテナ オブジェクトの割り当て要求の実装>>>
//	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;
}
Beispiel #11
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;
}
HRESULT BoneHierarchyLoader::CreateMeshContainer( LPCSTR Name,
												  CONST D3DXMESHDATA *pMeshData,
												  CONST D3DXMATERIAL *pMaterials,
												  CONST D3DXEFFECTINSTANCE *pEffectInstances,
												  DWORD NumMaterials,
												  CONST DWORD *pAdjacency,
												  LPD3DXSKININFO pSkinInfo,
												  LPD3DXMESHCONTAINER *ppNewMeshContainer )
{
	BoneMesh* boneMesh = new BoneMesh();

	// 메시 데이터를 얻는다.
	// 소프트웨어 스키닝을 위해서는 메시의 원본 형태의 데이터를 보관해두어야한다.
	boneMesh->_originalMesh = pMeshData->pMesh;
	boneMesh->MeshData.pMesh = pMeshData->pMesh;
	boneMesh->MeshData.Type = pMeshData->Type;

	// 메시의 메모리가 해제되지 않도록 참조값을 증가시킨다
	pMeshData->pMesh->AddRef();

	LPDIRECT3DDEVICE9 device = nullptr;
	pMeshData->pMesh->GetDevice( &device );

	// materials, texture
	for (int i = 0; i < NumMaterials; i++)
	{
		D3DXMATERIAL mtrl;
		memcpy(&mtrl, &pMaterials[i], sizeof(D3DXMATERIAL));
		boneMesh->_materials.push_back(mtrl.MatD3D);

		/*IDirect3DTexture9* newTexture = nullptr;

		if (mtrl.pTextureFilename != nullptr)
		{
			char texFileName[200] = "";
			strcat(texFileName, mtrl.pTextureFilename);

			D3DXCreateTextureFromFile(device, texFileName, &newTexture);
		}

		boneMesh->_textures.push_back(newTexture);*/
	}

	if (pSkinInfo != nullptr)
	{
		boneMesh->pSkinInfo = pSkinInfo;

		pSkinInfo->AddRef();

		pMeshData->pMesh->CloneMeshFVF( D3DXMESH_MANAGED,
										pMeshData->pMesh->GetFVF(),
										device,
										&boneMesh->MeshData.pMesh );

		boneMesh->MeshData.pMesh->GetAttributeTable( nullptr, &boneMesh->_numAttributeGroups );
		boneMesh->_attributeTable = new D3DXATTRIBUTERANGE[ boneMesh->_numAttributeGroups ];
		boneMesh->MeshData.pMesh->GetAttributeTable( boneMesh->_attributeTable, nullptr );

		int numBones = pSkinInfo->GetNumBones();
		boneMesh->_boneOffsetMatrices = new D3DXMATRIX[ numBones ];
		boneMesh->_currentBoneMatrices = new D3DXMATRIX[ numBones ];

		for (int i = 0; i < numBones; i++)
		{
			boneMesh->_boneOffsetMatrices[ i ] = *(boneMesh->pSkinInfo->GetBoneOffsetMatrix( i ));
		}
	}

	*ppNewMeshContainer = boneMesh;

	return S_OK;
}
Beispiel #13
0
//メッシュコンテナの生成
HRESULT Dx_Hierarchy::CreateMeshContainer(
	LPCTSTR Name,
	CONST D3DXMESHDATA *pMeshData,
	CONST D3DXMATERIAL *pMaterials,
	CONST D3DXEFFECTINSTANCE *pEffectInstances,
	DWORD NumMaterials, 
	CONST DWORD *pAdjacency,
	LPD3DXSKININFO pSkinInfo, 
	LPD3DXMESHCONTAINER *ppMeshContainer )
{
	HRESULT hr = S_OK;
	//生成用オブジェクトの宣言
	DxMeshContainer *pMeshContainer = NULL;
	//生成したオブジェクトの登録先を初期化
	*ppMeshContainer = NULL;

	int iFacesAmount;
	unsigned iMaterial;
	LPDIRECT3DDEVICE9 pDevice = NULL;
	LPD3DXMESH pMesh = NULL;

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

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

	//DWORD					dwBoneAmt=0;

	//メッシュデータの持つメッシュポインタを取得
	pMesh = pMeshData->pMesh;

	//オブジェクトの生成
	pMeshContainer = new DxMeshContainer;
	//変数がNULLだった場合
    if (pMeshContainer == NULL)
	{
		//エラーの意味 : Direct3D が呼び出しを完了するための十分なメモリを割り当てることができませんでした。
		return E_OUTOFMEMORY;
	}
	//
	ZeroMemory(pMeshContainer, sizeof(DxMeshContainer));

	//メッシュコンテナ名の領域確保
	pMeshContainer->Name=new TCHAR[lstrlen(Name) + 1];
	//領域が確保されなかった場合
    if (!pMeshContainer->Name)
	{
		//エラーの意味 : Direct3D サブシステム内で原因不明のエラーが発生しました。
		return E_FAIL;
	}
	//名前をコピーする
	strcpy(pMeshContainer->Name,Name);

	//メッシュに関連付けられているデバイスを取得
	if(FAILED(pMesh->GetDevice(&pDevice)))
	{
		/*hr = E_FAIL;
		SAFE_RELEASE( pDevice );
		if( pMeshContainer ) DestroyMeshContainer( pMeshContainer );
		return hr;*/
	}

	//メッシュに含まれる面の数を取得
	iFacesAmount = pMesh->GetNumFaces();

    // 当該メッシュが法線を持たない場合は法線を追加する
    if (!(pMesh->GetFVF() & D3DFVF_NORMAL)) {
		//メッシュデータの種類を「メッシュ」に変更
        pMeshContainer->MeshData.Type = D3DXMESHTYPE_MESH;
		//FVFコードを使ってメッシュのコピーを生成
        hr = pMesh->CloneMeshFVF( pMesh->GetOptions(), 
                                    pMesh->GetFVF() | D3DFVF_NORMAL, 
                                    pDevice, &pMeshContainer->MeshData.pMesh );
		//処理が失敗した場合
        if (FAILED(hr))
		{
			//エラーの意味 : Direct3D サブシステム内で原因不明のエラーが発生しました。
			return E_FAIL;
		}

        pMesh = pMeshContainer->MeshData.pMesh;
		//pMeshに含まれる各頂点の法線を計算して出力
        D3DXComputeNormals( pMesh, NULL );

    } else{
		//メッシュコンテナ内のメッシュデータにメッシュポインタを設定
        pMeshContainer->MeshData.pMesh = pMesh;
		//メッシュデータの種類を「メッシュ」に設定
        pMeshContainer->MeshData.Type = D3DXMESHTYPE_MESH;
		//???
        pMesh->AddRef();
    }

	//メッシュのマテリアル設定
	//マテリアル数を設定
    pMeshContainer->NumMaterials	= max(1, NumMaterials);
	//マテリアルの数だけマテリアルの領域を確保
    pMeshContainer->pMaterials		= new D3DXMATERIAL[pMeshContainer->NumMaterials];
	//マテリアルの数だけテクスチャの領域確保
    pMeshContainer->ppTextures		= new LPDIRECT3DTEXTURE9[pMeshContainer->NumMaterials];
	//面の数だけ領域を確保
    pMeshContainer->pAdjacency		= new DWORD[iFacesAmount*3];

	//それぞれの領域確保に失敗した場合
    if ((pMeshContainer->pAdjacency == NULL) || (pMeshContainer->pMaterials == NULL))
	{
		//エラーの意味 : Direct3D が呼び出しを完了するための十分なメモリを割り当てることができませんでした。
		return E_OUTOFMEMORY;
	}

	//配列に0を設定
    memset(pMeshContainer->ppTextures, 0, sizeof(LPDIRECT3DTEXTURE9) * pMeshContainer->NumMaterials);
	//配列にpAbjacencyを設定
    memcpy(pMeshContainer->pAdjacency, pAdjacency, sizeof(DWORD) * iFacesAmount*3);

	//マテリアルが存在する時
    if (NumMaterials > 0)
	{
		//
		memcpy(pMeshContainer->pMaterials, pMaterials, sizeof(D3DXMATERIAL) * NumMaterials);

		//
        for (iMaterial = 0; iMaterial < NumMaterials; iMaterial++)
		{
			//テクスチャのファイル名が存在する場合
            if( pMeshContainer->pMaterials[iMaterial].pTextureFilename != NULL)
			{
				//ファイルまでの相対パスを設定
				char path[256] ="res/x/";
				//ファイル名を取得
				LPSTR fName	= pMeshContainer->pMaterials[iMaterial].pTextureFilename;

				//テクスチャ情報の生成
				pMeshContainer->ppTextures[iMaterial] = 
					this->t_manager->LoadTextureFromFile(fName,path);
				//テクスチャ名の破棄
                pMeshContainer->pMaterials[iMaterial].pTextureFilename = NULL;
            }
        }
    }
	else
	{
		//テクスチャ名の破棄
        pMeshContainer->pMaterials[0].pTextureFilename = NULL;
		//マテリアルに0を設定
        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(pSkinInfo!=NULL)
	{
		//メッシュコンテナ内のスキニング情報を設定
		pMeshContainer->pSkinInfo = pSkinInfo;
		//???
		pSkinInfo->AddRef();

		//スキニング情報からボーンを生成
		this->CreateBone(pMeshContainer,pDevice);
	}

	//ローカルに生成したメッシュコンテナを呼び出し側にコピーする
	*ppMeshContainer = pMeshContainer;

	//処理が無事に終了
    return hr;
}
Beispiel #14
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;
}