⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 skinmesh.cpp

📁 Camera的源文件只是一部分Camera的源文件只是一部分
💻 CPP
📖 第 1 页 / 共 3 页
字号:
{
	CAllocateHierarchy Alloc(this);
	D3DXFrameDestroy(m_pFrameRoot, &Alloc);
    SAFE_RELEASE(m_pAnimController);
	
}
//----------------------------------------------------------------------------
//Summ:	从.x文件加载模型
//Desc:	从.x文件加载模型
//Para:	
//	strFileName:文件名
//----------------------------------------------------------------------------
HRESULT CSkinMesh::LoadFromXFile(char *strFileName)
{
    HRESULT    hr;
	CAllocateHierarchy Alloc(this);
	
    hr = D3DXLoadMeshHierarchyFromX(strFileName, D3DXMESH_MANAGED, m_pd3dDevice, &Alloc, NULL, &m_pFrameRoot, &m_pAnimController);
    if (FAILED(hr))
        return hr;
	
    hr = SetupBoneMatrixPointers(m_pFrameRoot);
    if (FAILED(hr))
        return hr;
	 
	 if(m_pFrameRoot)	
	 {
		 D3DXMATRIX matIdentity;
		 D3DXMatrixIdentity(&matIdentity); 
//	     if(m_pAnimController )
//		 {	
//			m_pAnimController->ResetTime(); 
//			LPD3DXANIMATIONSET aSet;
//			m_pAnimController->GetAnimationSet(0,&aSet);
//			m_pAnimController->RegisterAnimationSet(aSet);  
//		 }
		 UpdateFrameMatrices(m_pFrameRoot,&matIdentity); 	
		   
	 }
	return S_OK;
}

//-----------------------------------------------------------------------------
// Name: GenerateSkinnedMesh()
// Desc: Called either by CreateMeshContainer when loading a skin mesh, or when 
//       changing methods.  This function uses the pSkinInfo of the mesh 
//       container to generate the desired drawable mesh and bone combination 
//       table.
//-----------------------------------------------------------------------------
HRESULT CSkinMesh::GenerateSkinnedMesh(D3DXMESHCONTAINER_DERIVED *pMeshContainer)
{
    HRESULT hr = S_OK;

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

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

    // if non-indexed skinning mode selected, use ConvertToBlendedMesh to generate drawable mesh
	//如果不使用索引的蒙皮动画,就把网格转换成可绘制的网格
    if (m_SkinningMethod == D3DNONINDEXED)
    {

        hr = pMeshContainer->pSkinInfo->ConvertToBlendedMesh
                                   (
                                       pMeshContainer->pOrigMesh,
                                       D3DXMESH_MANAGED|D3DXMESHOPT_VERTEXCACHE, 
                                       pMeshContainer->pAdjacency, 
                                       NULL, NULL, NULL, 
                                       &pMeshContainer->NumInfl,
                                       &pMeshContainer->NumAttributeGroups, 
                                       &pMeshContainer->pBoneCombinationBuf, 
                                       &pMeshContainer->MeshData.pMesh
                                   );
        if (FAILED(hr))
            goto e_Exit;
		
		//如果设备只支持2个顶点混和,ConverteToBlendMesh不能近似地转换所有的网格。这时需要把网格转换成两部分,
		//只使用2个矩阵部分和其他部分。前者使用设备的顶点处理,其他部分使用软件方式处理
		LPD3DXBONECOMBINATION rgBoneCombinations  = reinterpret_cast<LPD3DXBONECOMBINATION>(pMeshContainer->pBoneCombinationBuf->GetBufferPointer());

        // look for any set of bone combinations that do not fit the caps
        for (pMeshContainer->iAttributeSW = 0; pMeshContainer->iAttributeSW < pMeshContainer->NumAttributeGroups; pMeshContainer->iAttributeSW++)
        {
            DWORD cInfl   = 0;

            for (DWORD iInfl = 0; iInfl < pMeshContainer->NumInfl; iInfl++)
            {
                if (rgBoneCombinations[pMeshContainer->iAttributeSW].BoneId[iInfl] != UINT_MAX)
                {
                    ++cInfl;
                }
            }

            if (cInfl > m_d3dCaps.MaxVertexBlendMatrices)
            {
                break;
            }
        }

        // if there is both HW and SW, add the Software Processing flag
        if (pMeshContainer->iAttributeSW < pMeshContainer->NumAttributeGroups)
        {
            LPD3DXMESH pMeshTmp;

            hr = pMeshContainer->MeshData.pMesh->CloneMeshFVF(D3DXMESH_SOFTWAREPROCESSING|pMeshContainer->MeshData.pMesh->GetOptions(), 
                                                pMeshContainer->MeshData.pMesh->GetFVF(),
                                                m_pd3dDevice, &pMeshTmp);
            if (FAILED(hr))
            {
                goto e_Exit;
            }

            pMeshContainer->MeshData.pMesh->Release();
            pMeshContainer->MeshData.pMesh = pMeshTmp;
            pMeshTmp = NULL;
        }
    }
    // if indexed skinning mode selected, use ConvertToIndexedsBlendedMesh to generate drawable mesh
    else if (m_SkinningMethod == D3DINDEXED)	//索引缓冲区模式的
    {
        DWORD NumMaxFaceInfl;
        DWORD Flags = D3DXMESHOPT_VERTEXCACHE;

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

        hr = pMeshContainer->pSkinInfo->GetMaxFaceInfluences(pIB, pMeshContainer->pOrigMesh->GetNumFaces(), 
			&NumMaxFaceInfl);
        pIB->Release();	//?这里为什么要释放
        if (FAILED(hr))
            goto e_Exit;

        // 12 entry palette guarantees that any triangle (4 independent influences per vertex of a tri)
        // can be handled
		//12个调色板保证所有三角形都被处理
        NumMaxFaceInfl = min(NumMaxFaceInfl, 12);

        if (m_d3dCaps.MaxVertexBlendMatrixIndex + 1 < NumMaxFaceInfl)
        {	
            // HW does not support indexed vertex blending. Use SW instead
			//如果硬件不支持顶点混和,就使用软件混和
            pMeshContainer->NumPaletteEntries = min(256, pMeshContainer->pSkinInfo->GetNumBones());
            pMeshContainer->UseSoftwareVP = true;
            Flags |= D3DXMESH_SYSTEMMEM;
        }
        else
        {
            // using hardware - determine palette size from caps and number of bones
            // If normals are present in the vertex data that needs to be blended for lighting, then 
            // the number of matrices is half the number specified by MaxVertexBlendMatrixIndex.
            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);
        if (FAILED(hr))
            goto e_Exit;
    }
     // if software skinning selected, use GenerateSkinnedMesh to create a mesh that can be used with UpdateSkinnedMesh
    else if (m_SkinningMethod == SOFTWARE)
    {
        hr = pMeshContainer->pOrigMesh->CloneMeshFVF(D3DXMESH_MANAGED, pMeshContainer->pOrigMesh->GetFVF(),
                                              m_pd3dDevice, &pMeshContainer->MeshData.pMesh);
        if (FAILED(hr))
            goto e_Exit;

        hr = pMeshContainer->MeshData.pMesh->GetAttributeTable(NULL, &pMeshContainer->NumAttributeGroups);
        if (FAILED(hr))
            goto e_Exit;

        delete[] pMeshContainer->pAttributeTable;
        pMeshContainer->pAttributeTable  = new D3DXATTRIBUTERANGE[pMeshContainer->NumAttributeGroups];
        if (pMeshContainer->pAttributeTable == NULL)
        {
            hr = E_OUTOFMEMORY;
            goto e_Exit;
        }

        hr = pMeshContainer->MeshData.pMesh->GetAttributeTable(pMeshContainer->pAttributeTable, NULL);
        if (FAILED(hr))
            goto e_Exit;

        // allocate a buffer for bone matrices, but only if another mesh has not allocated one of the same size or larger
        if (m_NumBoneMatricesMax < pMeshContainer->pSkinInfo->GetNumBones())
        {
            m_NumBoneMatricesMax = pMeshContainer->pSkinInfo->GetNumBones();

            // Allocate space for blend matrices
            delete []m_pBoneMatrices; 
            m_pBoneMatrices  = new D3DXMATRIXA16[m_NumBoneMatricesMax];
            if (m_pBoneMatrices == NULL)
            {
                hr = E_OUTOFMEMORY;
                goto e_Exit;
            }
        }
    }
    else  // invalid m_SkinningMethod value
    {        
        // return failure due to invalid skinning method value
        hr = E_INVALIDARG;
        goto e_Exit;
    }

e_Exit:
    return hr;
}

//Summ:设置MeshContainer链表每个节点的矩阵指针
//Desc:设置每个MeshContainer节点的矩阵指针,每个MeshContainer都有相对应的若干个变换矩阵
//		这里每个Frame包含一个MeshContainer的链表,而影响这个MeshContainer的矩阵并非
//		一个,所以,尽管已经有了变换矩阵,但并非唯一影响这个MeshContainer的矩阵
//Para:
//		pMeshContainerBase	pMeshContainerBase链表的结构的首节点
HRESULT CSkinMesh::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;
}
//Summ:设置MeshContainer每个节点的矩阵指针
//Desc:设置MeshContainer的矩阵指针,每个MeshContainer都有相对应的若干个变换矩阵
//		这里每个Frame包含一个MeshContainer的链表,而影响这个MeshContainer的矩阵并非
//		一个,所以,尽管已经有了变换矩阵,但并非唯一影响这个MeshContainer的矩阵
//Para:
//		pMeshContainerBase	pMeshContainerBase链表的结构的首节点
HRESULT CSkinMesh::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;
}

//Summ:渲染
//Desc:渲染这个蒙皮动画
//Para:
//	fElapsedAppTime:上一帧到当前帧的时间间隔,用于更新时间轴
//	vPos:			蒙皮的位置,也就是根节点的位置
//	angle:			角度
//	scale:			比例
VOID CSkinMesh::Render(float fTimeFromLastFrame,D3DXVECTOR3 vPos,float angle,float scale)
{
	
   if( 0.00f == fTimeFromLastFrame )    
	   return;
	m_fElapsedTime = fTimeFromLastFrame;
	
	// Setup world matrix
    D3DXMATRIXA16 matWorld,matWorld2;

	D3DXMatrixRotationY(&matWorld2,angle);
	D3DXMatrixScaling(&matWorld,scale,scale,scale);

	D3DXMatrixMultiply(&matWorld,&matWorld,&matWorld2);

   D3DXMatrixTranslation( &matWorld2, vPos.x, vPos.y,vPos.z );

	D3DXMatrixMultiply(&matWorld,&matWorld,&matWorld2);
	
	if(m_pAnimController)
	{

#if ((D3D_SDK_VERSION & 0xFF) == 31)
		if (m_bMoving)
			m_pAnimController->SetTime(m_pAnimController->GetTime()+m_fElapsedTime );
		else
			m_pAnimController->SetTime(0);
			
#else 
		if (m_bMoving)
			m_pAnimController->AdvanceTime(m_fElapsedTime,NULL); 
		else
			m_pAnimController->ResetTime();
#endif

	}
	
    UpdateFrameMatrices(m_pFrameRoot, &matWorld);

	//TODO:动态更新方盒,如果使用动态方盒,那么这里得到是方盒的世界坐标
	//	m_vMin=vPos;
	//	m_vMax=vPos;
	//	CalculateBondingBox(m_pFrameRoot,&m_vMin,&m_vMax);
	DrawFrame(m_pFrameRoot);
}

VOID CSkinMesh::Render(float fTime, D3DXMATRIXA16 * matWorld )
{
	m_fElapsedTime = fTime;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -