//==================================================================================== // フレームの削除(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; }
//フレーム削除 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; }
//----------------------------------------------------------------------------- // 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; }
/* ================== 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; }
/** * \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; }
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; }
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; }