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

📄 skinmesh.cpp

📁 骨骼动画 此程序演示了如何在你的游戏中使用骨骼动画技术。
💻 CPP
📖 第 1 页 / 共 2 页
字号:
}


VOID CSkinMesh::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);
    }
}

//-----------------------------------------------------------------------------
// Name: DrawMeshContainer()
// Desc: 渲染层次中的网格模型
//-----------------------------------------------------------------------------
VOID CSkinMesh::DrawMeshContainer( LPD3DXMESHCONTAINER pMeshContainerBase, LPD3DXFRAME pFrameBase )
{
    D3DXMESHCONTAINER_EX *pMeshContainer = (D3DXMESHCONTAINER_EX*)pMeshContainerBase;
    D3DXFRAME_EX *pFrame = (D3DXFRAME_EX*)pFrameBase;
    UINT iMaterial;
    UINT NumBlend;
    UINT iAttrib;
    DWORD AttribIdPrev;
    LPD3DXBONECOMBINATION pBoneComb;

    UINT iMatrixIndex;
    UINT iPaletteEntry;
    D3DXMATRIXA16 matTemp;

    // first check for skinning
    if (pMeshContainer->pSkinInfo != NULL)
    {
        if (m_SkinningMethod == D3DNONINDEXED)
        {
            AttribIdPrev = UNUSED32; 
            pBoneComb = reinterpret_cast<LPD3DXBONECOMBINATION>(pMeshContainer->pBoneCombinationBuf->GetBufferPointer());

            // Draw using default vtx processing of the device (typically HW)
            for (iAttrib = 0; iAttrib < pMeshContainer->NumAttributeGroups; iAttrib++)
            {
                NumBlend = 0;
                for (DWORD i = 0; i < pMeshContainer->NumInfl; ++i)
                {
                    if (pBoneComb[iAttrib].BoneId[i] != UINT_MAX)
                    {
                        NumBlend = i;
                    }
                }

                if (m_d3dCaps.MaxVertexBlendMatrices >= NumBlend + 1)
                {
                    // first calculate the world matrices for the current set of blend weights and get the accurate count of the number of blends
                    for (DWORD i = 0; i < pMeshContainer->NumInfl; ++i)
                    {
                        iMatrixIndex = pBoneComb[iAttrib].BoneId[i];
                        if (iMatrixIndex != UINT_MAX)
                        {
                            D3DXMatrixMultiply( &matTemp, &pMeshContainer->pBoneOffsetMatrices[iMatrixIndex], pMeshContainer->ppBoneMatrixPtrs[iMatrixIndex] );
                            m_pID3dDevice->SetTransform( D3DTS_WORLDMATRIX( i ), &matTemp );
                        }
                    }

                    m_pID3dDevice->SetRenderState(D3DRS_VERTEXBLEND, NumBlend);

                    // lookup the material used for this subset of faces
                    if ((AttribIdPrev != pBoneComb[iAttrib].AttribId) || (AttribIdPrev == UNUSED32))
                    {
                        m_pID3dDevice->SetMaterial( &pMeshContainer->pMaterials[pBoneComb[iAttrib].AttribId].MatD3D );
                        m_pID3dDevice->SetTexture( 0, pMeshContainer->ppTextures[pBoneComb[iAttrib].AttribId] );
                        AttribIdPrev = pBoneComb[iAttrib].AttribId;
                    }

                    // draw the subset now that the correct material and matrices are loaded
                    pMeshContainer->MeshData.pMesh->DrawSubset(iAttrib);
                }
            }

            // If necessary, draw parts that HW could not handle using SW
            if (pMeshContainer->iAttributeSW < pMeshContainer->NumAttributeGroups)
            {
                AttribIdPrev = UNUSED32; 
                m_pID3dDevice->SetSoftwareVertexProcessing(TRUE);
                for (iAttrib = pMeshContainer->iAttributeSW; iAttrib < pMeshContainer->NumAttributeGroups; iAttrib++)
                {
                    NumBlend = 0;
                    for (DWORD i = 0; i < pMeshContainer->NumInfl; ++i)
                    {
                        if (pBoneComb[iAttrib].BoneId[i] != UINT_MAX)
                        {
                            NumBlend = i;
                        }
                    }

                    if (m_d3dCaps.MaxVertexBlendMatrices < NumBlend + 1)
                    {
                        // first calculate the world matrices for the current set of blend weights and get the accurate count of the number of blends
                        for (DWORD i = 0; i < pMeshContainer->NumInfl; ++i)
                        {
                            iMatrixIndex = pBoneComb[iAttrib].BoneId[i];
                            if (iMatrixIndex != UINT_MAX)
                            {
                                D3DXMatrixMultiply( &matTemp, &pMeshContainer->pBoneOffsetMatrices[iMatrixIndex], pMeshContainer->ppBoneMatrixPtrs[iMatrixIndex] );
                                m_pID3dDevice->SetTransform( D3DTS_WORLDMATRIX( i ), &matTemp );
                            }
                        }

                        m_pID3dDevice->SetRenderState(D3DRS_VERTEXBLEND, NumBlend);

                        // lookup the material used for this subset of faces
                        if ((AttribIdPrev != pBoneComb[iAttrib].AttribId) || (AttribIdPrev == UNUSED32))
                        {
                            m_pID3dDevice->SetMaterial( &pMeshContainer->pMaterials[pBoneComb[iAttrib].AttribId].MatD3D );
                            m_pID3dDevice->SetTexture( 0, pMeshContainer->ppTextures[pBoneComb[iAttrib].AttribId] );
                            AttribIdPrev = pBoneComb[iAttrib].AttribId;
                        }

                        // draw the subset now that the correct material and matrices are loaded
                        pMeshContainer->MeshData.pMesh->DrawSubset(iAttrib);
                    }
                }
                m_pID3dDevice->SetSoftwareVertexProcessing(FALSE);
            }

            m_pID3dDevice->SetRenderState(D3DRS_VERTEXBLEND, 0);
        }
        else if (m_SkinningMethod == D3DINDEXED)
        {
            // if hw doesn't support indexed vertex processing, switch to software vertex processing
            if (pMeshContainer->UseSoftwareVP)
            {
                m_pID3dDevice->SetSoftwareVertexProcessing(TRUE);
            }

            // set the number of vertex blend indices to be blended
            if (pMeshContainer->NumInfl == 1)
                m_pID3dDevice->SetRenderState(D3DRS_VERTEXBLEND, D3DVBF_0WEIGHTS);
            else
                m_pID3dDevice->SetRenderState(D3DRS_VERTEXBLEND, pMeshContainer->NumInfl - 1);

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




            // for each attribute group in the mesh, calculate the set of matrices in the palette and then draw the mesh subset
            pBoneComb = reinterpret_cast<LPD3DXBONECOMBINATION>(pMeshContainer->pBoneCombinationBuf->GetBufferPointer());
            for (iAttrib = 0; iAttrib < pMeshContainer->NumAttributeGroups; iAttrib++)
            {

                 // first calculate all the world matrices
                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_pID3dDevice->SetTransform( D3DTS_WORLDMATRIX( iPaletteEntry ), &matTemp );
                    }
                }
               
                // setup the material of the mesh subset - REMEMBER to use the original pre-skinning attribute id to get the correct material id
                m_pID3dDevice->SetMaterial( &pMeshContainer->pMaterials[pBoneComb[iAttrib].AttribId].MatD3D );
                m_pID3dDevice->SetTexture( 0, pMeshContainer->ppTextures[pBoneComb[iAttrib].AttribId] );

                // finally draw the subset with the current world matrix palette and material state
                pMeshContainer->MeshData.pMesh->DrawSubset( iAttrib );
            }

            // reset blending state
            m_pID3dDevice->SetRenderState(D3DRS_INDEXEDVERTEXBLENDENABLE, FALSE);
            m_pID3dDevice->SetRenderState(D3DRS_VERTEXBLEND, 0);

            // remember to reset back to hw vertex processing if software was required
            if (pMeshContainer->UseSoftwareVP)
            {
                m_pID3dDevice->SetSoftwareVertexProcessing(FALSE);
            }
        }
        else if (m_SkinningMethod == SOFTWARE)
        {
            D3DXMATRIX  Identity;
            DWORD       cBones  = pMeshContainer->pSkinInfo->GetNumBones();
            DWORD       iBone;
            PBYTE       pbVerticesSrc;
            PBYTE       pbVerticesDest;

            // set up bone transforms
            for (iBone = 0; iBone < cBones; ++iBone)
            {
                D3DXMatrixMultiply
                (
                    &m_pBoneMatrices[iBone],                 // output
                    &pMeshContainer->pBoneOffsetMatrices[iBone], 
                    pMeshContainer->ppBoneMatrixPtrs[iBone]
                );
            }

            // set world transform
            D3DXMatrixIdentity(&Identity);
            m_pID3dDevice->SetTransform(D3DTS_WORLD, &Identity);

            pMeshContainer->pOrigMesh->LockVertexBuffer(D3DLOCK_READONLY, (LPVOID*)&pbVerticesSrc);
            pMeshContainer->MeshData.pMesh->LockVertexBuffer(0, (LPVOID*)&pbVerticesDest);

            // generate skinned mesh
            pMeshContainer->pSkinInfo->UpdateSkinnedMesh(m_pBoneMatrices, NULL, pbVerticesSrc, pbVerticesDest);

            pMeshContainer->pOrigMesh->UnlockVertexBuffer();
            pMeshContainer->MeshData.pMesh->UnlockVertexBuffer();

            for (iAttrib = 0; iAttrib < pMeshContainer->NumAttributeGroups; iAttrib++)
            {
                m_pID3dDevice->SetMaterial(&(pMeshContainer->pMaterials[pMeshContainer->pAttributeTable[iAttrib].AttribId].MatD3D));
                m_pID3dDevice->SetTexture(0, pMeshContainer->ppTextures[pMeshContainer->pAttributeTable[iAttrib].AttribId]);
                pMeshContainer->MeshData.pMesh->DrawSubset(pMeshContainer->pAttributeTable[iAttrib].AttribId);
            }
        }
        else // bug out as unsupported mode
        {
            return;
        }
    }
    else  // standard mesh, just draw it after setting material properties
    {
        m_pID3dDevice->SetTransform(D3DTS_WORLD, &pFrame->CombinedTransformationMatrix);

        for (iMaterial = 0; iMaterial < pMeshContainer->NumMaterials; iMaterial++)
        {
            m_pID3dDevice->SetMaterial( &pMeshContainer->pMaterials[iMaterial].MatD3D );
            m_pID3dDevice->SetTexture( 0, pMeshContainer->ppTextures[iMaterial] );
            pMeshContainer->MeshData.pMesh->DrawSubset(iMaterial);
        }
    }
}


VOID CSkinMesh::UpdateFrameMatrices( LPD3DXFRAME pFrameBase, LPD3DXMATRIX pParentMatrix )
{
    D3DXFRAME_EX *pFrame = (D3DXFRAME_EX*)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::SetAnim(BOOL bAnim)
	{
		m_bMoving=bAnim;
		if(!m_bMoving && m_pIAnimController)
		{	
#if ((D3D_SDK_VERSION&0xFF)== 31)		
		m_pIAnimController->SetTime(0);	
#else	
		m_pIAnimController->ResetTime();
#endif
		}
	}

BOOL CSkinMesh::SetAnimationName( char *strAnimName )
{
	if(!m_bMoving || !m_pIAnimController  ) 
		return FALSE;
	DWORD nAnimSet;
	char strTempName[256];
	nAnimSet = m_pIAnimController->GetNumAnimationSets();
	LPD3DXANIMATIONSET pAnimSet;
	
	for(DWORD i=0;i<nAnimSet;i++)
	{	
		m_pIAnimController->GetAnimationSet( i, &pAnimSet );
		strcpy_s( strTempName, _tcslen(pAnimSet->GetName())+1, pAnimSet->GetName() );
		if(strcmp(strAnimName,strTempName)==0) 
		{
			m_pIAnimController->SetTrackAnimationSet( 0, pAnimSet );
		 
			return TRUE;			
		}
	}

	SAFE_RELEASE( pAnimSet );
	return FALSE;	
};

//-----------------------------------------
//Name:Intersect
//Desc:使用索引和顶点缓冲区,求Mesh和射线交点
//2006/6/27 JohnsonFeng
//Use: IntersectIndexBuffer
//-----------------------------------------
BOOL CSkinMesh::InterSect( D3DVECTOR *pRayOrig,
		 D3DVECTOR *pRayDir,D3DVECTOR* pVRet)
{
	return S_OK;
}

HRESULT CSkinMesh::CalculateBondingBox( LPD3DXFRAME pFrameParent, D3DXVECTOR3 *pVmin, D3DXVECTOR3 *pVmax )		// 计算模型的包围盒,通过参数返回包围盒数据
{
	static LPVOID pV; 
	static LPD3DXMESH pMesh;
	static LPD3DXMATRIX pMat;
	static D3DXVECTOR3 vMin,vMax; 
	static D3DXVECTOR3 vTransFormed;

	if( pFrameParent->pMeshContainer )
	{
		pMesh = pFrameParent->pMeshContainer->MeshData.pMesh;    
		pMat = &( ((D3DXFRAME_EX*)pFrameParent)->CombinedTransformationMatrix );

		pMesh->LockVertexBuffer( 0,&pV );	// 锁定顶点缓冲区
		D3DXComputeBoundingBox( (LPD3DXVECTOR3)pV, pMesh->GetNumVertices(), pMesh->GetNumBytesPerVertex(), &vMin, &vMax );	// 创建包围盒
		
		vTransFormed.x = pMat->_11*vMin.x + pMat->_21*vMin.y + pMat->_31*vMin.z + pMat->_41;
		vTransFormed.y = pMat->_12*vMin.x + pMat->_22*vMin.y + pMat->_32*vMin.z + pMat->_42;
		vTransFormed.z = pMat->_13*vMin.x + pMat->_23*vMin.y + pMat->_33*vMin.z + pMat->_43;

		if(vTransFormed.x<pVmin->x) pVmin->x = vTransFormed.x;
		if(vTransFormed.y<pVmin->y) pVmin->y = vTransFormed.y;
		if(vTransFormed.z<pVmin->z) pVmin->z = vTransFormed.z;

		vTransFormed.x=pMat->_11*vMax.x+pMat->_21*vMax.y+pMat->_31*vMax.z+pMat->_41;
		vTransFormed.y=pMat->_12*vMax.x+pMat->_22*vMax.y+pMat->_32*vMax.z+pMat->_42;
		vTransFormed.z=pMat->_13*vMax.x+pMat->_23*vMax.y+pMat->_33*vMax.z+pMat->_43;

		if(vTransFormed.x>pVmax->x) pVmax->x = vTransFormed.x;
		if(vTransFormed.y>pVmax->y) pVmax->y = vTransFormed.y;
		if(vTransFormed.z>pVmax->z) pVmax->z = vTransFormed.z;

		pMesh->UnlockVertexBuffer(); 
	}
	//else return S_OK;
	
	if( pFrameParent->pFrameSibling )
		CalculateBondingBox(pFrameParent->pFrameSibling,pVmin,pVmax);
	
	if( pFrameParent->pFrameFirstChild )
		CalculateBondingBox( pFrameParent->pFrameFirstChild, pVmin, pVmax );
	return S_OK;

}

⌨️ 快捷键说明

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