home *** CD-ROM | disk | FTP | other *** search
/ Visual Basic Game Programming for Teens / VBGPFT.cdr / DirectX8 / dx8a_sdk.exe / samples / multimedia / direct3d / skinnedmesh / mdraw.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2000-09-22  |  17.4 KB  |  535 lines

  1. //-----------------------------------------------------------------------------
  2. // File: mdraw.cpp
  3. //
  4. // Copyright (c) 1999-2000 Microsoft Corporation. All rights reserved.
  5. //-----------------------------------------------------------------------------
  6.  
  7. #include <d3d8.h>
  8. #include <d3dx8.h>
  9. #include "D3DApp.h"
  10. #include "D3DFont.h"
  11. #include "D3DUtil.h"
  12. #include "DXUtil.h"
  13. #include "SkinnedMesh.h"
  14.  
  15.  
  16. HRESULT CMyD3DApplication::DrawMeshContainer(SMeshContainer *pmcMesh)
  17. {
  18.     UINT ipattr;
  19.     HRESULT hr = S_OK;
  20.     LPD3DXBONECOMBINATION pBoneComb;
  21.     LPDIRECT3DDEVICE8 m_pDevice = m_pd3dDevice;
  22.  
  23.     if (pmcMesh->m_pSkinMesh)
  24.     {
  25.         D3DCAPS8    caps;
  26.  
  27.         m_pDevice->GetDeviceCaps(&caps);
  28.  
  29.         if (m_method != pmcMesh->m_Method)
  30.         {
  31.             GenerateMesh(pmcMesh);
  32.         }
  33.  
  34.         if (m_method == D3DNONINDEXED)
  35.         {
  36.             if (caps.MaxVertexBlendMatrices >= pmcMesh->m_maxFaceInfl || (pmcMesh->pMeshSW == NULL && pmcMesh->pMeshHW == NULL))
  37.             {
  38.                 m_pDevice->SetRenderState(D3DRS_VERTEXBLEND, pmcMesh->m_maxFaceInfl - 1);
  39.                 pBoneComb = reinterpret_cast<LPD3DXBONECOMBINATION>(pmcMesh->m_pBoneCombinationBuf->GetBufferPointer());
  40.                 for (ipattr = 0; ipattr < pmcMesh->cpattr; ipattr++)
  41.                 {
  42.                     for (DWORD i = 0; i < pmcMesh->m_maxFaceInfl; ++i)
  43.                     {
  44.                         DWORD matid = pBoneComb[ipattr].BoneId[i];
  45.                         if (matid != UINT_MAX && (ipattr == 0 || matid != pBoneComb[ipattr - 1].BoneId[i]))
  46.                         {
  47.                             m_pDevice->SetTransform(D3DTS_WORLDMATRIX(i), pmcMesh->m_pBoneMatrix[matid]);
  48.                             m_pDevice->MultiplyTransform(D3DTS_WORLDMATRIX(i), &pmcMesh->m_pBoneOffsetMat[matid]);
  49.                         }
  50.                     }
  51.  
  52.                     if (ipattr == 0 || (pBoneComb[ipattr].AttribId != pBoneComb[ipattr - 1].AttribId))
  53.                     {
  54.                         m_pDevice->SetMaterial(&(pmcMesh->rgMaterials[pBoneComb[ipattr].AttribId]));
  55.                         m_pDevice->SetTexture(0, pmcMesh->pTextures[pBoneComb[ipattr].AttribId]);
  56.                     }
  57.  
  58.                     hr = pmcMesh->pMesh->DrawSubset( ipattr );
  59.                     if(FAILED(hr))
  60.                         return hr;
  61.                 }
  62.                 m_pDevice->SetRenderState(D3DRS_VERTEXBLEND, 0);
  63.             }
  64.             else
  65.             {
  66.                 if (pmcMesh->pMeshHW != NULL)
  67.                 {
  68.                     m_pDevice->SetRenderState(D3DRS_VERTEXBLEND, 1);        // Two matrix blending
  69.                     pBoneComb = reinterpret_cast<LPD3DXBONECOMBINATION>(pmcMesh->m_pBoneCombinationBuf->GetBufferPointer());
  70.                     for (ipattr = 0; ipattr < pmcMesh->iAttrSplit; ipattr++)
  71.                     {
  72.                         for (DWORD i = 0; i < 2; ++i)       
  73.                         {
  74.                             DWORD matid = pBoneComb[ipattr].BoneId[i];
  75.                             if (matid != UINT_MAX && (ipattr == 0 || matid != pBoneComb[ipattr - 1].BoneId[i]))
  76.                             {
  77.                                 m_pDevice->SetTransform(D3DTS_WORLDMATRIX(i), pmcMesh->m_pBoneMatrix[matid]);
  78.                                 m_pDevice->MultiplyTransform(D3DTS_WORLDMATRIX(i), &pmcMesh->m_pBoneOffsetMat[matid]);
  79.                             }
  80.                         }
  81.  
  82.                         if (ipattr == 0 || (pBoneComb[ipattr].AttribId != pBoneComb[ipattr - 1].AttribId))
  83.                         {
  84.                             m_pDevice->SetMaterial(&(pmcMesh->rgMaterials[pBoneComb[ipattr].AttribId]));
  85.                             m_pDevice->SetTexture(0, pmcMesh->pTextures[pBoneComb[ipattr].AttribId]);
  86.                         }
  87.  
  88.                         hr = pmcMesh->pMeshHW->DrawSubset( ipattr );
  89.                         if(FAILED(hr))
  90.                             return hr;
  91.                     }
  92.                     m_pDevice->SetRenderState(D3DRS_VERTEXBLEND, 0);
  93.                 }
  94.  
  95.                 if (pmcMesh->pMeshSW != NULL)
  96.                 {
  97.                     m_pDevice->SetRenderState(D3DRS_SOFTWAREVERTEXPROCESSING, TRUE);
  98.                     m_pDevice->SetRenderState(D3DRS_VERTEXBLEND, pmcMesh->m_maxFaceInfl - 1);
  99.                     pBoneComb = reinterpret_cast<LPD3DXBONECOMBINATION>(pmcMesh->m_pBoneCombinationBuf->GetBufferPointer());
  100.                     for (ipattr = pmcMesh->iAttrSplit; ipattr < pmcMesh->cpattr; ipattr++)
  101.                     {
  102.                         for (DWORD i = 0; i < pmcMesh->m_maxFaceInfl; ++i)
  103.                         {
  104.                             DWORD matid = pBoneComb[ipattr].BoneId[i];
  105.                             if (matid != UINT_MAX && (ipattr == pmcMesh->iAttrSplit || matid != pBoneComb[ipattr - 1].BoneId[i]))
  106.                             {
  107.                                 m_pDevice->SetTransform(D3DTS_WORLDMATRIX(i), pmcMesh->m_pBoneMatrix[matid]);
  108.                                 m_pDevice->MultiplyTransform(D3DTS_WORLDMATRIX(i), &pmcMesh->m_pBoneOffsetMat[matid]);
  109.                             }
  110.                         }
  111.  
  112.                         if (ipattr == pmcMesh->iAttrSplit || (pBoneComb[ipattr].AttribId != pBoneComb[ipattr - 1].AttribId))
  113.                         {
  114.                             m_pDevice->SetMaterial(&(pmcMesh->rgMaterials[pBoneComb[ipattr].AttribId]));
  115.                             m_pDevice->SetTexture(0, pmcMesh->pTextures[pBoneComb[ipattr].AttribId]);
  116.                         }
  117.  
  118.                         hr = pmcMesh->pMeshSW->DrawSubset( ipattr );
  119.                         if(FAILED(hr))
  120.                             return hr;
  121.                     }
  122.                     m_pDevice->SetRenderState(D3DRS_VERTEXBLEND, 0);
  123.                     m_pDevice->SetRenderState(D3DRS_SOFTWAREVERTEXPROCESSING, FALSE);
  124.                 }
  125.             }
  126.         }
  127.         else if (m_method == D3DINDEXED)
  128.         {
  129.             if (caps.MaxVertexBlendMatrixIndex < pmcMesh->m_pSkinMesh->GetNumBones())
  130.             {
  131.                 m_pDevice->SetRenderState(D3DRS_SOFTWAREVERTEXPROCESSING, TRUE);
  132.             }
  133.  
  134.             m_pDevice->SetRenderState(D3DRS_VERTEXBLEND, pmcMesh->m_maxFaceInfl - 1);
  135.             if (pmcMesh->m_maxFaceInfl - 1)
  136.                 m_pDevice->SetRenderState(D3DRS_INDEXEDVERTEXBLENDENABLE, TRUE);
  137.             pBoneComb = reinterpret_cast<LPD3DXBONECOMBINATION>(pmcMesh->m_pBoneCombinationBuf->GetBufferPointer());
  138.             for (ipattr = 0; ipattr < pmcMesh->cpattr; ipattr++)
  139.             {
  140.                 for (DWORD i = 0; i < 255/*paletteSize*/; ++i)
  141.                 {
  142.                     DWORD matid = pBoneComb[ipattr].BoneId[i];
  143.                     if (matid != UINT_MAX)
  144.                     {
  145.                         m_pDevice->SetTransform(D3DTS_WORLDMATRIX(i), pmcMesh->m_pBoneMatrix[matid]);
  146.                         m_pDevice->MultiplyTransform(D3DTS_WORLDMATRIX(i), &pmcMesh->m_pBoneOffsetMat[matid]);
  147.                     }
  148.                 }
  149.                 
  150.                 m_pDevice->SetMaterial(&(pmcMesh->rgMaterials[pBoneComb[ipattr].AttribId]));
  151.                 m_pDevice->SetTexture(0, pmcMesh->pTextures[pBoneComb[ipattr].AttribId]);
  152.  
  153.                 hr = pmcMesh->pMesh->DrawSubset( ipattr );
  154.                 if(FAILED(hr))
  155.                     return hr;
  156.             }
  157.             m_pDevice->SetRenderState(D3DRS_INDEXEDVERTEXBLENDENABLE, FALSE);
  158.             m_pDevice->SetRenderState(D3DRS_VERTEXBLEND, 0);
  159.  
  160.             if (caps.MaxVertexBlendMatrixIndex < pmcMesh->m_pSkinMesh->GetNumBones())
  161.             {
  162.                 m_pDevice->SetRenderState(D3DRS_SOFTWAREVERTEXPROCESSING, FALSE);
  163.             }
  164.         }
  165.         else if (m_method == SOFTWARE)
  166.         {
  167.             D3DXMATRIX  Identity;
  168.  
  169.             DWORD       cBones  = pmcMesh->m_pSkinMesh->GetNumBones();
  170.  
  171.             // set up bone transforms
  172.  
  173.             D3DXMATRIX* rgBoneMatrices  = NULL;
  174.             
  175.             rgBoneMatrices  = new D3DXMATRIX[cBones];
  176.  
  177.             if (rgBoneMatrices == NULL)
  178.             {
  179.                 hr = E_OUTOFMEMORY;
  180.  
  181.                 goto e_ExitSOFTWARE;
  182.             }
  183.  
  184.             {
  185.             for (DWORD iBone = 0; iBone < cBones; ++iBone)
  186.             {
  187.                 D3DXMatrixMultiply
  188.                 (
  189.                     &rgBoneMatrices[iBone],                 // output
  190.                     &pmcMesh->m_pBoneOffsetMat[iBone], 
  191.                     pmcMesh->m_pBoneMatrix[iBone]
  192.                 );
  193.             }
  194.             }
  195.  
  196.             // set world transform
  197.             D3DXMatrixIdentity(&Identity);
  198.  
  199.             hr = m_pDevice->SetTransform(D3DTS_WORLD, &Identity);
  200.  
  201.             if (FAILED(hr))
  202.                 goto e_ExitSOFTWARE;
  203.  
  204.  
  205.             // generate skinned mesh
  206.             hr = pmcMesh->m_pSkinMesh->UpdateSkinnedMesh(rgBoneMatrices, pmcMesh->pMesh);
  207.  
  208.             if (FAILED(hr))
  209.                 goto e_ExitSOFTWARE;
  210.  
  211.  
  212.             for (ipattr = 0; ipattr < pmcMesh->cpattr; ipattr++)
  213.             {
  214.                 m_pDevice->SetMaterial(&(pmcMesh->rgMaterials[ipattr]));
  215.                 m_pDevice->SetTexture(0, pmcMesh->pTextures[ipattr]);
  216.  
  217.                 hr  = pmcMesh->pMesh->DrawSubset(ipattr);
  218.  
  219.                 if (FAILED(hr))
  220.                     goto e_ExitSOFTWARE;
  221.             }
  222.  
  223. e_ExitSOFTWARE:
  224.  
  225.             delete[] rgBoneMatrices;
  226.  
  227.             return hr;
  228.         }
  229.     }
  230.     else
  231.     {
  232.         for (ipattr = 0; ipattr < pmcMesh->cpattr; ipattr++)
  233.         {
  234.             m_pDevice->SetMaterial(&(pmcMesh->rgMaterials[ipattr]));
  235.             m_pDevice->SetTexture(0, pmcMesh->pTextures[ipattr]);
  236.             hr = pmcMesh->pMesh->DrawSubset( ipattr );
  237.             if(FAILED(hr))
  238.                 return hr;
  239.         }
  240.     }
  241.  
  242.     return S_OK;
  243.  
  244.  
  245. }
  246.  
  247.  
  248.  
  249.  
  250. HRESULT CMyD3DApplication::UpdateFrames(SFrame *pframeCur, D3DXMATRIX &matCur)
  251. {
  252.     HRESULT hr = S_OK;
  253.     pframeCur->matCombined = matCur;
  254.     D3DXMatrixMultiply(&pframeCur->matCombined, &pframeCur->matRot, &matCur);
  255.     D3DXMatrixMultiply(&pframeCur->matCombined, &pframeCur->matCombined, &pframeCur->matTrans );
  256.     SFrame *pframeChild = pframeCur->pframeFirstChild;
  257.     while (pframeChild != NULL)
  258.     {
  259.         hr = UpdateFrames(pframeChild, pframeCur->matCombined);
  260.         if (FAILED(hr))
  261.             return hr;
  262.  
  263.         pframeChild = pframeChild->pframeSibling;
  264.     }
  265.     return S_OK;
  266. }
  267.  
  268.  
  269.  
  270.  
  271. HRESULT CMyD3DApplication::DrawFrames(SFrame *pframeCur, UINT &cTriangles)
  272. {
  273.     HRESULT hr = S_OK;
  274.     SMeshContainer *pmcMesh;
  275.     SFrame *pframeChild;
  276.     LPDIRECT3DDEVICE8 m_pDevice = m_pd3dDevice;
  277.  
  278.     if (pframeCur->pmcMesh != NULL)
  279.     {
  280.         hr = m_pDevice->SetTransform(D3DTS_WORLD, &pframeCur->matCombined);
  281.         if(FAILED(hr))
  282.             return hr;
  283.     }
  284.  
  285.     pmcMesh = pframeCur->pmcMesh;
  286.     while (pmcMesh != NULL)
  287.     {
  288.         hr = DrawMeshContainer(pmcMesh);
  289.         if (FAILED(hr))
  290.             return hr;
  291.  
  292.         cTriangles += pmcMesh->pMesh->GetNumFaces();
  293.  
  294.         pmcMesh = pmcMesh->pmcNext;
  295.     }
  296.  
  297.     pframeChild = pframeCur->pframeFirstChild;
  298.     while (pframeChild != NULL)
  299.     {
  300.         hr = DrawFrames(pframeChild, cTriangles);
  301.         if (FAILED(hr))
  302.             return hr;
  303.  
  304.         pframeChild = pframeChild->pframeSibling;
  305.     }
  306.  
  307.     return S_OK;
  308. }
  309.  
  310.  
  311.  
  312.  
  313. void SFrame::SetTime(float fGlobalTime)
  314. {
  315.     UINT iKey;
  316.     UINT dwp2;
  317.     UINT dwp3;
  318.     D3DXMATRIX matResult;
  319.     D3DXMATRIX matTemp;
  320.     float fTime1;
  321.     float fTime2;
  322.     float fLerpValue;
  323.     D3DXVECTOR3 vScale;
  324.     D3DXVECTOR3 vPos;
  325.     D3DXQUATERNION quat;
  326.     BOOL bAnimate = false;
  327.     float fTime;
  328.  
  329.     if (m_pMatrixKeys )
  330.     {
  331.         fTime = (float)fmod(fGlobalTime, m_pMatrixKeys[m_cMatrixKeys-1].dwTime);
  332.  
  333.         for (iKey = 0 ;iKey < m_cMatrixKeys ; iKey++)
  334.         {
  335.             if ((float)m_pMatrixKeys[iKey].dwTime > fTime)
  336.             {
  337.                 dwp3 = iKey;
  338.  
  339.                 if (iKey > 0)
  340.                 {
  341.                     dwp2= iKey - 1;
  342.                 }
  343.                 else  // when iKey == 0, then dwp2 == 0
  344.                 {
  345.                     dwp2 = iKey;
  346.                 }
  347.  
  348.                 break;
  349.             }
  350.         }
  351.         fTime1 = (float)m_pMatrixKeys[dwp2].dwTime;
  352.         fTime2 = (float)m_pMatrixKeys[dwp3].dwTime;
  353.  
  354.         if ((fTime2 - fTime1) ==0)
  355.             fLerpValue = 0;
  356.         else
  357.             fLerpValue =  (fTime - fTime1)  / (fTime2 - fTime1);
  358.  
  359.         if (fLerpValue > 0.5)
  360.         {
  361.             iKey = dwp3;
  362.         }
  363.         else
  364.         {
  365.             iKey = dwp2;
  366.         }
  367.  
  368.         pframeToAnimate->matRot = m_pMatrixKeys[iKey].mat;
  369.     }
  370.     else
  371.     {
  372.         D3DXMatrixIdentity(&matResult);
  373.  
  374.         if (m_pScaleKeys)
  375.         {
  376.             dwp2 = dwp3 = 0;
  377.  
  378.             fTime = (float)fmod(fGlobalTime, m_pScaleKeys[m_cScaleKeys-1].dwTime);
  379.  
  380.             for (iKey = 0 ;iKey < m_cScaleKeys ; iKey++)
  381.             {
  382.                 if ((float)m_pScaleKeys[iKey].dwTime > fTime)
  383.                 {
  384.                     dwp3 = iKey;
  385.  
  386.                     if (iKey > 0)
  387.                     {
  388.                         dwp2= iKey - 1;
  389.                     }
  390.                     else  // when iKey == 0, then dwp2 == 0
  391.                     {
  392.                         dwp2 = iKey;
  393.                     }
  394.  
  395.                     break;
  396.                 }
  397.             }
  398.             fTime1 = (float)m_pScaleKeys[dwp2].dwTime;
  399.             fTime2 = (float)m_pScaleKeys[dwp3].dwTime;
  400.  
  401.             if ((fTime2 - fTime1) ==0)
  402.                 fLerpValue = 0;
  403.             else
  404.                 fLerpValue =  (fTime - fTime1)  / (fTime2 - fTime1);
  405.  
  406.             D3DXVec3Lerp(&vScale,
  407.                     &m_pScaleKeys[dwp2].vScale,
  408.                     &m_pScaleKeys[dwp3].vScale,
  409.                     fLerpValue);
  410.  
  411.  
  412.             D3DXMatrixScaling(&matTemp, vScale.x, vScale.y, vScale.z);
  413.  
  414.             D3DXMatrixMultiply(&matResult, &matResult, &matTemp);
  415.  
  416.             bAnimate = true;
  417.         }
  418.  
  419.         //check rot keys
  420.         if (m_pRotateKeys )
  421.         {
  422.             dwp2 = dwp3 = 0;
  423.  
  424.             fTime = (float)fmod(fGlobalTime, m_pRotateKeys[m_cRotateKeys-1].dwTime);
  425.  
  426.             for (iKey = 0 ;iKey < m_cRotateKeys ; iKey++)
  427.             {
  428.                 if ((float)m_pRotateKeys[iKey].dwTime > fTime)
  429.                 {
  430.                     dwp3 = iKey;
  431.  
  432.                     if (iKey > 0)
  433.                     {
  434.                         dwp2= iKey - 1;
  435.                     }
  436.                     else  // when iKey == 0, then dwp2 == 0
  437.                     {
  438.                         dwp2 = iKey;
  439.                     }
  440.  
  441.                     break;
  442.                 }
  443.             }
  444.             fTime1 = (float)m_pRotateKeys[dwp2].dwTime;
  445.             fTime2 = (float)m_pRotateKeys[dwp3].dwTime;
  446.  
  447.             if ((fTime2 - fTime1) ==0)
  448.                 fLerpValue = 0;
  449.             else
  450.                 fLerpValue =  (fTime - fTime1)  / (fTime2 - fTime1);
  451.  
  452.             //s=0;
  453.             D3DXQUATERNION q1,q2;
  454.             q1.x =-m_pRotateKeys[dwp2].quatRotate.x;
  455.             q1.y =-m_pRotateKeys[dwp2].quatRotate.y;
  456.             q1.z =-m_pRotateKeys[dwp2].quatRotate.z;
  457.             q1.w =m_pRotateKeys[dwp2].quatRotate.w;
  458.  
  459.             q2.x =-m_pRotateKeys[dwp3].quatRotate.x;
  460.             q2.y =-m_pRotateKeys[dwp3].quatRotate.y;
  461.             q2.z =-m_pRotateKeys[dwp3].quatRotate.z;
  462.             q2.w =m_pRotateKeys[dwp3].quatRotate.w;
  463.  
  464.             D3DXQuaternionSlerp(&quat,
  465.                                 &q1,
  466.                                 &q2,
  467.                                 fLerpValue);
  468.  
  469.             D3DXMatrixRotationQuaternion(&matTemp, &quat);
  470.  
  471.             D3DXMatrixMultiply(&matResult, &matResult, &matTemp);
  472.             bAnimate = true;
  473.         }
  474.  
  475.         if (m_pPositionKeys)
  476.         {
  477.             dwp2=dwp3=0;
  478.  
  479.             fTime = (float)fmod(fGlobalTime, m_pPositionKeys[m_cRotateKeys-1].dwTime);
  480.  
  481.             for (iKey = 0 ;iKey < m_cPositionKeys ; iKey++)
  482.             {
  483.                 if ((float)m_pPositionKeys[iKey].dwTime > fTime)
  484.                 {
  485.                     dwp3 = iKey;
  486.  
  487.                     if (iKey > 0)
  488.                     {
  489.                         dwp2= iKey - 1;
  490.                     }
  491.                     else  // when iKey == 0, then dwp2 == 0
  492.                     {
  493.                         dwp2 = iKey;
  494.                     }
  495.  
  496.                     break;
  497.                 }
  498.             }
  499.             fTime1 = (float)m_pPositionKeys[dwp2].dwTime;
  500.             fTime2 = (float)m_pPositionKeys[dwp3].dwTime;
  501.  
  502.             if ((fTime2 - fTime1) ==0)
  503.                 fLerpValue = 0;
  504.             else
  505.                 fLerpValue =  (fTime - fTime1)  / (fTime2 - fTime1);
  506.  
  507.  
  508.             D3DXVec3Lerp((D3DXVECTOR3*)&vPos,
  509.                     &m_pPositionKeys[dwp2].vPos,
  510.                     &m_pPositionKeys[dwp3].vPos,
  511.                     fLerpValue);
  512.  
  513.             D3DXMatrixTranslation(&matTemp, vPos.x, vPos.y, vPos.z);
  514.  
  515.             D3DXMatrixMultiply(&matResult, &matResult, &matTemp);
  516.             bAnimate = true;
  517.         }
  518.         else
  519.         {
  520.             D3DXMatrixTranslation(&matTemp, pframeToAnimate->matRotOrig._41, pframeToAnimate->matRotOrig._42, pframeToAnimate->matRotOrig._43);
  521.  
  522.             D3DXMatrixMultiply(&matResult, &matResult, &matTemp);
  523.         }
  524.  
  525.         if (bAnimate)
  526.         {
  527.             pframeToAnimate->matRot = matResult;
  528.         }
  529.     }
  530. }
  531.  
  532.  
  533.  
  534.  
  535.