骨骼动画

来源:互联网 发布:量化交易编程r语言 编辑:程序博客网 时间:2024/04/30 05:22
  

class CSkinMesh_Test;

struct D3DXFRAME_DERIVED: public D3DXFRAME
{
    D3DXMATRIXA16        CombinedTransformationMatrix;
};

struct D3DXMESHCONTAINER_DERIVED: public D3DXMESHCONTAINER
{
    LPDIRECT3DTEXTURE9*  ppTextures;       // array of textures, entries are NULL if no texture specified   
                               
    // SkinMesh info            
    LPD3DXMESH           pOrigMesh;
    LPD3DXATTRIBUTERANGE pAttributeTable;
    DWORD                NumAttributeGroups;
    DWORD                NumInfl;
    LPD3DXBUFFER         pBoneCombinationBuf;
    D3DXMATRIX**         ppBoneMatrixPtrs;
    D3DXMATRIX*          pBoneOffsetMatrices;
    DWORD                NumPaletteEntries;
    bool                 UseSoftwareVP;
    DWORD                iAttributeSW;     // used to denote the split between SW and HW if necessary for non-indexed skinning
};

class CAllocateHierarchy: public ID3DXAllocateHierarchy
{
public:
    STDMETHOD(CreateFrame)(THIS_ LPCTSTR Name, LPD3DXFRAME *ppNewFrame);//创建骨骼对象
    STDMETHOD(CreateMeshContainer)(THIS_ LPCSTR Name, CONST D3DXMESHDATA *pMeshData, CONST D3DXMATERIAL *pMaterials, CONST D3DXEFFECTINSTANCE *pEffectInstances,
           DWORD NumMaterials, CONST DWORD *pAdjacency, LPD3DXSKININFO pSkinInfo, LPD3DXMESHCONTAINER *ppNewMeshContainer);//创建Mesh数据对象

    STDMETHOD(DestroyFrame)(THIS_ LPD3DXFRAME pFrameToFree);
    STDMETHOD(DestroyMeshContainer)(THIS_ LPD3DXMESHCONTAINER pMeshContainerBase);
    CAllocateHierarchy(CSkinMesh_Test *pSkinMesh) :m_pSkinMesh(pSkinMesh) {}

public:
 CSkinMesh_Test*  m_pSkinMesh;
};

class CSkinMesh_Test
{
public:
 CSkinMesh_Test(void);
 virtual ~CSkinMesh_Test(void);

public:
 HRESULT D3DCreate( LPDIRECT3DDEVICE9 pd3dDevice );
 void Render( LPDIRECT3DDEVICE9 pd3dDevice );
 void SetMatrix( LPDIRECT3DDEVICE9 pd3dDevice );

public:
 HRESULT GenerateSkinnedMesh(D3DXMESHCONTAINER_DERIVED *pMeshContainer);
 HRESULT SetupBoneMatrixPointers(LPD3DXFRAME pFrame);
 HRESULT SetupBoneMatrixPointersOnMesh( LPD3DXMESHCONTAINER pMeshContainerBase );
 VOID UpdateFrameMatrices(LPD3DXFRAME pFrameBase, LPD3DXMATRIX pParentMatrix);
 VOID DrawFrame(LPD3DXFRAME pFrame);
 VOID DrawMeshContainer(LPD3DXMESHCONTAINER pMeshContainerBase, LPD3DXFRAME pFrameBase);
private:
 D3DCAPS9      m_d3dCaps;
 D3DXVECTOR3                 m_vObjectCenter;
 FLOAT                       m_fObjectRadius;

 LPDIRECT3DDEVICE9   m_pd3dDevice;
 UINT      m_NumBoneMatricesMax;
 D3DXMATRIXA16*    m_pBoneMatrices;

 FLOAT      m_fElapsedTime;
 BOOL      m_bMoving;
 LPD3DXFRAME     m_pFrameRoot;
 LPD3DXANIMATIONCONTROLLER m_pAnimController;
};

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

HRESULT AllocateName( LPCTSTR Name, LPTSTR *pNewName )
{
    UINT cbLength;
 
    if (Name != NULL)
    {
        cbLength = lstrlen(Name) + 1;
        *pNewName = new TCHAR[cbLength];
        if (*pNewName == NULL)
            return E_OUTOFMEMORY;
        memcpy(*pNewName, Name, cbLength*sizeof(TCHAR));
    }
    else
    {
        *pNewName = NULL;
    }
 
    return S_OK;
}

HRESULT CAllocateHierarchy::CreateFrame(LPCTSTR Name, LPD3DXFRAME *ppNewFrame )
{
    D3DXFRAME_DERIVED *pFrame;
 
    *ppNewFrame = NULL;
 
    pFrame = new D3DXFRAME_DERIVED;
    if (pFrame == NULL)
        return E_OUTOFMEMORY;
 
    if( FAILED ( AllocateName( Name, &pFrame->Name ) ) )
 {
  SAFE_DELETE(pFrame);
        return S_OK;
 }
    D3DXMatrixIdentity(&pFrame->TransformationMatrix);
    D3DXMatrixIdentity(&pFrame->CombinedTransformationMatrix);
 
    pFrame->pMeshContainer = NULL;
    pFrame->pFrameSibling = NULL;
    pFrame->pFrameFirstChild = NULL;
 
    *ppNewFrame = pFrame;
    pFrame = NULL;

    SAFE_DELETE(pFrame);
    return S_OK;
}

LRESULT CAllocateHierarchy::CreateMeshContainer( LPCTSTR Name, CONST D3DXMESHDATA *pMeshData, CONST D3DXMATERIAL *pMaterials, CONST D3DXEFFECTINSTANCE *pEffectInstances,
            DWORD NumMaterials, CONST DWORD *pAdjacency, LPD3DXSKININFO pSkinInfo, LPD3DXMESHCONTAINER *ppNewMeshContainer)
{
    D3DXMESHCONTAINER_DERIVED *pMeshContainer = NULL;
    UINT NumFaces;
    UINT iMaterial;
    UINT iBone, cBones;
    LPDIRECT3DDEVICE9 pd3dDevice = NULL;
 
    LPD3DXMESH pMesh = NULL;
 
    *ppNewMeshContainer = NULL;
 
    if (pMeshData->Type != D3DXMESHTYPE_MESH)//Mesh数据类型,是否正确
 {
  if ( pMeshContainer != NULL )
   DestroyMeshContainer(pMeshContainer);

        return E_FAIL;
    }
 
    pMesh = pMeshData->pMesh;
 
    if (pMesh->GetFVF() == 0)//mesh的顶点格式,是否为空
    {
  if ( pMeshContainer != NULL )
   DestroyMeshContainer(pMeshContainer);

        return E_FAIL;
    }
 
    pMeshContainer = new D3DXMESHCONTAINER_DERIVED;
    if (pMeshContainer == NULL)
    {
        SAFE_RELEASE(pd3dDevice);
  if ( pMeshContainer != NULL )
   DestroyMeshContainer(pMeshContainer);

        return E_OUTOFMEMORY;
    }
    memset(pMeshContainer, 0, sizeof(D3DXMESHCONTAINER_DERIVED));
 
    if( FAILED( AllocateName(Name, &pMeshContainer->Name) ) )//拷贝名字
 {
        SAFE_RELEASE(pd3dDevice);
  if ( pMeshContainer != NULL )
   DestroyMeshContainer(pMeshContainer);

        return E_FAIL;      
 }

    pMesh->GetDevice(&pd3dDevice);//获取设备指针
    NumFaces = pMesh->GetNumFaces();//获取模型面数
 
    if (!(pMesh->GetFVF() & D3DFVF_NORMAL))
    {
        pMeshContainer->MeshData.Type = D3DXMESHTYPE_MESH;
  
        if( FAILED( pMesh->CloneMeshFVF( pMesh->GetOptions(), pMesh->GetFVF() | D3DFVF_NORMAL, pd3dDevice, &pMeshContainer->MeshData.pMesh ) ) )
  {
   SAFE_RELEASE(pd3dDevice);
   if ( pMeshContainer != NULL )
    DestroyMeshContainer(pMeshContainer);

   return E_FAIL;
  }

        pMesh = pMeshContainer->MeshData.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[NumFaces*3];
    if ((pMeshContainer->pAdjacency == NULL) || (pMeshContainer->pMaterials == NULL))
    {
  SAFE_RELEASE(pd3dDevice);
  if ( pMeshContainer != NULL )
   DestroyMeshContainer(pMeshContainer);

        return E_OUTOFMEMORY;
    }
 
    memcpy(pMeshContainer->pAdjacency, pAdjacency, sizeof(DWORD) * NumFaces*3);
    memset(pMeshContainer->ppTextures, 0, sizeof(LPDIRECT3DTEXTURE9) * pMeshContainer->NumMaterials);
 
    if (NumMaterials > 0)           
    {
        memcpy(pMeshContainer->pMaterials, pMaterials, sizeof(D3DXMATERIAL) * NumMaterials);
  
        for (iMaterial = 0; iMaterial < NumMaterials; iMaterial++)
        {
            if (pMeshContainer->pMaterials[iMaterial].pTextureFilename != NULL)
            {     
    std::string strTextureFilename = "Dwarf\\";
    strTextureFilename += pMeshContainer->pMaterials[iMaterial].pTextureFilename;

    if( FAILED( D3DXCreateTextureFromFile( pd3dDevice, strTextureFilename.c_str(), &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 = 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();
  
        pMeshContainer->pOrigMesh = pMesh;
        pMesh->AddRef();
  
        cBones = pSkinInfo->GetNumBones();
        pMeshContainer->pBoneOffsetMatrices = new D3DXMATRIX[cBones];
        if (pMeshContainer->pBoneOffsetMatrices == NULL)
        {
            SAFE_RELEASE(pd3dDevice);
   if ( pMeshContainer != NULL )
    DestroyMeshContainer(pMeshContainer);

   return E_OUTOFMEMORY;
        }
  
        for (iBone = 0; iBone < cBones; iBone++)
        {
            pMeshContainer->pBoneOffsetMatrices[iBone] = *(pMeshContainer->pSkinInfo->GetBoneOffsetMatrix(iBone));
        }
  
        if( FAILED( m_pSkinMesh->GenerateSkinnedMesh(pMeshContainer) ) )
  {
   SAFE_RELEASE(pd3dDevice);
   if ( pMeshContainer != NULL )
    DestroyMeshContainer(pMeshContainer);

   return E_FAIL;
  }
    }
 
    *ppNewMeshContainer = pMeshContainer;
    pMeshContainer = NULL;

 return S_OK;
}

HRESULT CAllocateHierarchy::DestroyFrame(LPD3DXFRAME pFrameToFree)
{
    SAFE_DELETE_ARRAY( pFrameToFree->Name );
    SAFE_DELETE( pFrameToFree );
    return S_OK;
}

HRESULT CAllocateHierarchy::DestroyMeshContainer(LPD3DXMESHCONTAINER pMeshContainerBase)
{
    UINT iMaterial;
    D3DXMESHCONTAINER_DERIVED *pMeshContainer = (D3DXMESHCONTAINER_DERIVED*)pMeshContainerBase;
 
    SAFE_DELETE_ARRAY( pMeshContainer->Name );
    SAFE_DELETE_ARRAY( pMeshContainer->pAdjacency );
    SAFE_DELETE_ARRAY( pMeshContainer->pMaterials );
    SAFE_DELETE_ARRAY( pMeshContainer->pBoneOffsetMatrices );
 
    // release all the allocated textures
    if (pMeshContainer->ppTextures != NULL)
    {
        for (iMaterial = 0; iMaterial < pMeshContainer->NumMaterials; iMaterial++)
        {
            SAFE_RELEASE( pMeshContainer->ppTextures[iMaterial] );
        }
    }
 
    SAFE_DELETE_ARRAY( pMeshContainer->ppTextures );
    SAFE_DELETE_ARRAY( pMeshContainer->ppBoneMatrixPtrs );
    SAFE_RELEASE( pMeshContainer->pBoneCombinationBuf );
    SAFE_RELEASE( pMeshContainer->MeshData.pMesh );
    SAFE_RELEASE( pMeshContainer->pSkinInfo );
    SAFE_RELEASE( pMeshContainer->pOrigMesh );
    SAFE_DELETE( pMeshContainer );
    return S_OK;
}

CSkinMesh_Test::CSkinMesh_Test(void)
{
 m_fElapsedTime   =  0.0f;
 m_bMoving=TRUE;
    m_pAnimController = NULL;
    m_pFrameRoot = NULL;
    m_pBoneMatrices = NULL;
    m_NumBoneMatricesMax = 0;
}

CSkinMesh_Test::~CSkinMesh_Test(void)
{
 CAllocateHierarchy Alloc(this);
 D3DXFrameDestroy(m_pFrameRoot, &Alloc);
 
    SAFE_RELEASE(m_pAnimController);
}

HRESULT CSkinMesh_Test::D3DCreate( LPDIRECT3DDEVICE9 pd3dDevice )
{
 m_pd3dDevice = pd3dDevice;
 m_pd3dDevice->GetDeviceCaps( &m_d3dCaps );

 CAllocateHierarchy Alloc(this);
 
    if( FAILED( D3DXLoadMeshHierarchyFromX( "Dwarf\\zhashi.X", D3DXMESH_MANAGED, m_pd3dDevice, &Alloc, NULL, &m_pFrameRoot, &m_pAnimController) ) )//从X文件加载骨骼动画信息
  return E_FAIL;
  
    if( FAILED( SetupBoneMatrixPointers(m_pFrameRoot) ) )
  return E_FAIL;
 
 //计算层次框架的包围球
 //返回的是中心点 m_vObjectCenter
 //和半径
    if( FAILED( D3DXFrameCalculateBoundingSphere(m_pFrameRoot, &m_vObjectCenter, &m_fObjectRadius) ) )
   return E_FAIL;

 SetMatrix(pd3dDevice);
 return S_OK;
}

HRESULT CSkinMesh_Test::SetupBoneMatrixPointers(LPD3DXFRAME pFrame)
{
    HRESULT hr;

 //判断层次框架下的网格
    if (pFrame->pMeshContainer != NULL)
    { //左序遍历
        hr = SetupBoneMatrixPointersOnMesh(pFrame->pMeshContainer);
        if (FAILED(hr))
            return hr;
    }

     //做递归把找出所有 兄弟节点框架下的网格
    if (pFrame->pFrameSibling != NULL)
    {
        hr = SetupBoneMatrixPointers(pFrame->pFrameSibling);
        if (FAILED(hr))
            return hr;
    }

 //做递归把找出所有 儿子节点框架下的网格
    if (pFrame->pFrameFirstChild != NULL)
    {
        hr = SetupBoneMatrixPointers(pFrame->pFrameFirstChild);
        if (FAILED(hr))
            return hr;
    }

    return S_OK;
}

HRESULT CSkinMesh_Test::SetupBoneMatrixPointersOnMesh(LPD3DXMESHCONTAINER pMeshContainerBase)
{
    UINT iBone, cBones;
    D3DXFRAME_DERIVED *pFrame;

    D3DXMESHCONTAINER_DERIVED *pMeshContainer = (D3DXMESHCONTAINER_DERIVED*)pMeshContainerBase;

    // if there is a skinmesh, then setup the bone matrices
 //蒙皮动画,则设置骨骼的变换矩阵
    if (pMeshContainer->pSkinInfo != NULL)
    {
        cBones = pMeshContainer->pSkinInfo->GetNumBones();

        pMeshContainer->ppBoneMatrixPtrs = new D3DXMATRIX*[cBones]; //创建骨骼

        if (pMeshContainer->ppBoneMatrixPtrs == NULL)
            return E_OUTOFMEMORY;

        for (iBone = 0; iBone < cBones; iBone++)
        {
   //找到根框架的子框架
            pFrame = (D3DXFRAME_DERIVED*)D3DXFrameFind(m_pFrameRoot,
    pMeshContainer->pSkinInfo->GetBoneName(iBone));

            if (pFrame == NULL)
                return E_FAIL;
   //初始化矩阵
            pMeshContainer->ppBoneMatrixPtrs[iBone] = &pFrame->CombinedTransformationMatrix;
        }
    }

    return S_OK;
}

void CSkinMesh_Test::Render( LPDIRECT3DDEVICE9 pd3dDevice )
{
 m_pd3dDevice->SetRenderState(D3DRS_LIGHTING, true);
 m_pd3dDevice->SetRenderState( D3DRS_AMBIENT, D3DCOLOR_XRGB( 255,255,255 ) );//设置环境光颜色值

 if(m_pAnimController)
 {
  if (m_bMoving)
   m_pAnimController->AdvanceTime(0.02f,NULL);
  else
   m_pAnimController->ResetTime();
 }

 D3DXMATRIXA16 matWorld;
 D3DXMatrixTranslation( &matWorld, 0.0f, 0.0f, 0.0f );

 UpdateFrameMatrices(m_pFrameRoot, &matWorld);
 
 DrawFrame(m_pFrameRoot);

VOID CSkinMesh_Test::UpdateFrameMatrices(LPD3DXFRAME pFrameBase, LPD3DXMATRIX pParentMatrix)
{
    D3DXFRAME_DERIVED *pFrame = (D3DXFRAME_DERIVED*)pFrameBase;

    if (pParentMatrix != NULL)
        D3DXMatrixMultiply(&pFrame->CombinedTransformationMatrix, &pFrame->TransformationMatrix, pParentMatrix);
    else
        pFrame->CombinedTransformationMatrix = pFrame->TransformationMatrix;

    if (pFrame->pFrameSibling != NULL)
    {
        UpdateFrameMatrices(pFrame->pFrameSibling, pParentMatrix);
    }

    if (pFrame->pFrameFirstChild != NULL)
    {
        UpdateFrameMatrices(pFrame->pFrameFirstChild, &pFrame->CombinedTransformationMatrix);
    }
}

VOID CSkinMesh_Test::DrawFrame(LPD3DXFRAME pFrame)
{
    LPD3DXMESHCONTAINER pMeshContainer;
 
    pMeshContainer = pFrame->pMeshContainer;
    while (pMeshContainer != NULL)
    {
        DrawMeshContainer(pMeshContainer, pFrame);
        pMeshContainer = pMeshContainer->pNextMeshContainer;
    }
 
    if (pFrame->pFrameSibling != NULL)
    {
        DrawFrame(pFrame->pFrameSibling);
    }
 
    if (pFrame->pFrameFirstChild != NULL)
    {
        DrawFrame(pFrame->pFrameFirstChild);
    }
}

VOID CSkinMesh_Test::DrawMeshContainer(LPD3DXMESHCONTAINER pMeshContainerBase, LPD3DXFRAME pFrameBase)
{
    D3DXMESHCONTAINER_DERIVED *pMeshContainer = (D3DXMESHCONTAINER_DERIVED*)pMeshContainerBase;
    D3DXFRAME_DERIVED *pFrame = (D3DXFRAME_DERIVED*)pFrameBase;
    UINT iAttrib;
    LPD3DXBONECOMBINATION pBoneComb;

    UINT iMatrixIndex;
    UINT iPaletteEntry;
    D3DXMATRIXA16 matTemp;

    if (pMeshContainer->pSkinInfo != NULL)
    {
        if (pMeshContainer->UseSoftwareVP)
        {
            m_pd3dDevice->SetSoftwareVertexProcessing(TRUE);
        }

        if (pMeshContainer->NumInfl == 1)
            m_pd3dDevice->SetRenderState(D3DRS_VERTEXBLEND, D3DVBF_0WEIGHTS);
        else
            m_pd3dDevice->SetRenderState(D3DRS_VERTEXBLEND, pMeshContainer->NumInfl - 1);

        if (pMeshContainer->NumInfl)
            m_pd3dDevice->SetRenderState(D3DRS_INDEXEDVERTEXBLENDENABLE, TRUE);

        pBoneComb = reinterpret_cast<LPD3DXBONECOMBINATION>(pMeshContainer->pBoneCombinationBuf->GetBufferPointer());
        for (iAttrib = 0; iAttrib < pMeshContainer->NumAttributeGroups; iAttrib++)
        {
            for (iPaletteEntry = 0; iPaletteEntry < pMeshContainer->NumPaletteEntries; ++iPaletteEntry)
            {
                iMatrixIndex = pBoneComb[iAttrib].BoneId[iPaletteEntry];
                if (iMatrixIndex != UINT_MAX)
                {
                    D3DXMatrixMultiply( &matTemp, &pMeshContainer->pBoneOffsetMatrices[iMatrixIndex], pMeshContainer->ppBoneMatrixPtrs[iMatrixIndex] );
                    m_pd3dDevice->SetTransform( D3DTS_WORLDMATRIX( iPaletteEntry ), &matTemp );
                }
            }
           
   pMeshContainer->pMaterials[pBoneComb[iAttrib].AttribId].MatD3D.Ambient.a = 1.0f;
   pMeshContainer->pMaterials[pBoneComb[iAttrib].AttribId].MatD3D.Ambient.b = 1.0f;
   pMeshContainer->pMaterials[pBoneComb[iAttrib].AttribId].MatD3D.Ambient.g = 1.0f;
   pMeshContainer->pMaterials[pBoneComb[iAttrib].AttribId].MatD3D.Ambient.r = 1.0f;

            m_pd3dDevice->SetMaterial( &pMeshContainer->pMaterials[pBoneComb[iAttrib].AttribId].MatD3D );
            m_pd3dDevice->SetTexture( 0, pMeshContainer->ppTextures[pBoneComb[iAttrib].AttribId] );

            pMeshContainer->MeshData.pMesh->DrawSubset( iAttrib );
        }

        m_pd3dDevice->SetRenderState(D3DRS_INDEXEDVERTEXBLENDENABLE, FALSE);
        m_pd3dDevice->SetRenderState(D3DRS_VERTEXBLEND, 0);

        if (pMeshContainer->UseSoftwareVP)
        {
            m_pd3dDevice->SetSoftwareVertexProcessing(FALSE);
        }
    }
}

void CSkinMesh_Test::SetMatrix( LPDIRECT3DDEVICE9 pd3dDevice )
{
 D3DXMATRIX matView, matProj;
 D3DXMatrixLookAtLH(&matView,&D3DXVECTOR3(0,30,80),&D3DXVECTOR3(0,30,0), &D3DXVECTOR3(0,1,0)); //视图变换矩阵,摄像机位置,焦点位置,向上方向
 D3DXMatrixPerspectiveFovLH(&matProj,D3DX_PI/4,1.0f,1.0f,1000.0f); //PI/4的视角,4/3的长宽比,近平面1.0,远屏幕1000;
 
 pd3dDevice->SetTransform(D3DTS_VIEW,&matView);
 pd3dDevice->SetTransform(D3DTS_PROJECTION,&matProj);
}

HRESULT CSkinMesh_Test::GenerateSkinnedMesh(D3DXMESHCONTAINER_DERIVED *pMeshContainer)
{
    HRESULT hr = S_OK;

    if (pMeshContainer->pSkinInfo == NULL)
        return hr;

    SAFE_RELEASE( pMeshContainer->MeshData.pMesh );
    SAFE_RELEASE( pMeshContainer->pBoneCombinationBuf );

    DWORD NumMaxFaceInfl;
    DWORD Flags = D3DXMESHOPT_VERTEXCACHE;

    LPDIRECT3DINDEXBUFFER9 pIB;
    hr = pMeshContainer->pOrigMesh->GetIndexBuffer(&pIB);
    if (FAILED(hr))
        return hr;

    hr = pMeshContainer->pSkinInfo->GetMaxFaceInfluences(pIB, pMeshContainer->pOrigMesh->GetNumFaces(), &NumMaxFaceInfl);
    pIB->Release();
    if (FAILED(hr))
   return hr;

    NumMaxFaceInfl = min(NumMaxFaceInfl, 12);

    if (m_d3dCaps.MaxVertexBlendMatrixIndex + 1 < NumMaxFaceInfl)
    {
        pMeshContainer->NumPaletteEntries = min(256, pMeshContainer->pSkinInfo->GetNumBones());
        pMeshContainer->UseSoftwareVP = true;
        Flags |= D3DXMESH_SYSTEMMEM;
    }
    else
    {
        pMeshContainer->NumPaletteEntries = min( ( m_d3dCaps.MaxVertexBlendMatrixIndex + 1 ) / 2,
                                                 pMeshContainer->pSkinInfo->GetNumBones() );
        pMeshContainer->UseSoftwareVP = false;
        Flags |= D3DXMESH_MANAGED;
    }

    hr = pMeshContainer->pSkinInfo->ConvertToIndexedBlendedMesh
                                            (
                                            pMeshContainer->pOrigMesh,
                                            Flags,
                                            pMeshContainer->NumPaletteEntries,
                                            pMeshContainer->pAdjacency,
                                            NULL, NULL, NULL,
                                            &pMeshContainer->NumInfl,
                                            &pMeshContainer->NumAttributeGroups,
                                            &pMeshContainer->pBoneCombinationBuf,
                                            &pMeshContainer->MeshData.pMesh);         
   


    return hr;
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

typedef struct _D3DXFRAME//框架信息(对应于骨骼)
{
    LPSTR                   Name;
    D3DXMATRIX              TransformationMatrix; //本骨骼的转换矩阵

    LPD3DXMESHCONTAINER     pMeshContainer;       //本骨骼所对应Mesh数据

    struct _D3DXFRAME       *pFrameSibling;       //兄弟骨骼
    struct _D3DXFRAME       *pFrameFirstChild;    //子骨骼
} D3DXFRAME, *LPD3DXFRAME;
typedef struct _D3DXMESHCONTAINER
{
    LPSTR                   Name;       //容器名
    D3DXMESHDATA            MeshData;   //Mesh数据,可创建SkinMesh取代这个Mesh
    LPD3DXMATERIAL          pMaterials; //材质数组
    LPD3DXEFFECTINSTANCE    pEffects;  
    DWORD                   NumMaterials;//材质数
    DWORD*                  pAdjacency;  //邻接三角形数组
    LPD3DXSKININFO          pSkinInfo;   //蒙皮信息,其中含.x中的各个skinweight蒙皮顶点索引及各骨骼偏移矩阵等。
    struct _D3DXMESHCONTAINER *pNextMeshContainer;
} D3DXMESHCONTAINER, *LPD3DXMESHCONTAINER;


HRESULT WINAPI D3DXLoadMeshHierarchyFromX
(
        LPCSTR Filename,                 //.x文件名
        DWORD MeshOptions,               //Mesh选项,一般选D3DXMESH_MANAGED
        LPDIRECT3DDEVICE9 pD3DDevice,    //指向D3D设备Device
        LPD3DXALLOCATEHIERARCHY pAlloc,  //自定义数据容器
        LPD3DXLOADUSERDATA pUserDataLoader,  //一般选NULL
        LPD3DXFRAME *ppFrameHierarchy,       //返回根Frame指针,指向代表整个骨架的Frame层次结构
        LPD3DXANIMATIONCONTROLLER *ppAnimController //返回相应的动画控制器
);
HRESULT WINAPI D3DXFrameCalculateBoundingSphere//求有骨骼模型的包围球
(
    CONST D3DXFRAME *pFrameRoot,      
    LPD3DXVECTOR3 pObjectCenter, 
    FLOAT *pObjectRadius         
);
LPD3DXFRAME WINAPI D3DXFrameFind//找到根框架的子框架
(
    CONST D3DXFRAME *pFrameRoot,
    LPCSTR Name
);

原创粉丝点击