topical media & game development

talk show tell print

hush-src-multi-GamePlayer-Character.cpp / cpp



  //------------------------------------------------------------------------------
  // File: Character.cpp
  //
  // Desc: DirectShow sample code - MultiVMR9 GamePlayer
  //
  // Copyright (c) Microsoft Corporation.  All rights reserved.
  //------------------------------------------------------------------------------
  
  define STRICT
  include <stdafx.h>
  include <Character.h>
  include <d3dx9anim.h>
  include <d3dx9mesh.h>
  include <d3dutil.h>
  include <dxutil.h>
  include <resource.h>
  
  //#include scene/scene.h"
  include <vip.h>
  
  int once = 0;
  /* walking back
  float xrot = -0.5;
  float yrot = 0.0;
  float zrot = 0.0;
  */
  
  extern vip* VP;
  
  float xrot = -0.5; // from flat
  float yrot = 0.0; // 1 under, 0.5 sideways
  float zrot = 1.0; // 0.5 towards wall
  
  int strange_machine = 1;
  
  const TCHAR g_achMeshFile[] = TEXT("res\\tiny.x");
  //const TCHAR g_achMeshFile[] = TEXT(<tiny.x>);
  const TCHAR g_achSkinFile[] = TEXT("Tiny_skin.bmp");
  
  // world matrix (combined projection and view)
  D3DXMATRIX g_matCharacterWorld(
               0.850856720f,  0.17622593f,   0.49494526f,  0.00000000f,
               0.031906456f,  0.92298937f,  -0.38349065f,  0.00000000f,
              -0.524415970f,  0.34209663f,   0.77970898f,  0.00000000f,
            //-230.000000000f, 20.00000000f,   0.00000000f,  1.00000000f
                     -230.000000000f, -210.00000000f,   0.00000000f,  1.00000000f
              );
  
  extern D3DXMATRIX g_matWorld;
  
  
******************Public*Routine*of*Private*Class***********************\ CCharacter constructor \*************************************************************************

  
  CCharacter::CCharacter()
      : m_bInitialized( FALSE )
      , m_pFrameRoot( NULL )
      , m_pAnimController( NULL )
      , m_pDevice( NULL )
      , m_pBoneMatrices( NULL )
      , m_fObjectRadius( 0.f )
      , m_NumBoneMatricesMax( 0 )
          , m_bAlreadyFailed( FALSE )
  {
      ZeroMemory( &m_vObjectCenter, sizeof(m_vObjectCenter));
  }
  
  
******************Public*Routine*of*Private*Class***********************\ ~CCharacter destructor \*************************************************************************

  
  CCharacter::~CCharacter()
  {
      CAllocateHierarchy Alloc(m_pDevice);
  
      D3DXFrameDestroy(m_pFrameRoot, &Alloc);
      RELEASE( m_pAnimController );
      RELEASE( m_pDevice );
  
      if( m_pBoneMatrices )
      {
          delete[] m_pBoneMatrices;
          m_pBoneMatrices = NULL;
      }
  }
  
  
******************Public*Routine*of*Private*Class***********************\ Initialize Loads "walking figure" from 'tiny.x' file as a skinned mesh \*************************************************************************

  
  HRESULT CCharacter::Initialize( IDirect3DDevice9 *pDevice )
  {
      HRESULT hr = S_OK;
  
      CString strMessage;
      TCHAR achMeshPath[MAX_PATH];
      CAllocateHierarchy Alloc( pDevice );
  
      if( !pDevice )
      {
          return E_POINTER;
      }
  
      m_pDevice = pDevice;
      m_pDevice->AddRef();
  
      if( m_bInitialized )
      {
          return VFW_E_WRONG_STATE;
      }
      
      try
      {
          hr = FindMediaFile( achMeshPath,
                              sizeof( TCHAR)*MAX_PATH,
                              (TCHAR*)g_achSkinFile,
                              MAKEINTRESOURCE(IDB_BITMAP_SKIN),
                              RT_BITMAP);
          if( FAILED(hr))
          {
                          if( !m_bAlreadyFailed )
                          {
                                  strMessage.Format(_T("Cannot find file '\%s''. Make sure you have valid installation of DirectX SDK"), g_achSkinFile);
                                  AfxMessageBox( strMessage );
                                  m_bAlreadyFailed = TRUE;
                          }
              return hr;
          }
  
          hr = FindMediaFile( achMeshPath,
                              sizeof( TCHAR)*MAX_PATH,
                              (TCHAR*)g_achMeshFile,
                              MAKEINTRESOURCE(1),/* dummy */
                              RT_RCDATA);
          if( FAILED(hr))
          {
                          if( !m_bAlreadyFailed )
                          {
                                  strMessage.Format(_T("Cannot find file '\%s''. Make sure you have valid installation of DirectX SDK"), g_achMeshFile);
                                  AfxMessageBox( strMessage );
                                  m_bAlreadyFailed = TRUE;
                          }
              return hr;
          }
  
  ifdef UNICODE
          hr = D3DXLoadMeshHierarchyFromXW(        achMeshPath, 
                                                                                          D3DXMESH_MANAGED, 
                                                                                          pDevice, 
                                                                                          (LPD3DXALLOCATEHIERARCHY)(&Alloc), 
                                                                                          NULL, 
                                                                                          (LPD3DXFRAME*)(&m_pFrameRoot), 
                                                                                          (LPD3DXANIMATIONCONTROLLER*)(&m_pAnimController));
  else
          
          hr = D3DXLoadMeshHierarchyFromXA(        (LPCSTR)achMeshPath,
                  //        "..\\models\\tiny.x",
                                                                                          D3DXMESH_MANAGED, 
                                                                                          pDevice, 
                                                                                          (LPD3DXALLOCATEHIERARCHY)(&Alloc), 
                                                                                          NULL, 
                                                                                          (LPD3DXFRAME*)(&m_pFrameRoot), 
                                                                                          (LPD3DXANIMATIONCONTROLLER*)(&m_pAnimController));
  
          
  
  endif
          if (FAILED(hr))
          {
              throw hr;
          }
  
          hr = SetupBoneMatrixPointers_(m_pFrameRoot);
          if (FAILED(hr))
          {
              throw hr;
          }
  
          hr = D3DXFrameCalculateBoundingSphere(m_pFrameRoot, &m_vObjectCenter, &m_fObjectRadius);
          if (FAILED(hr))
          {
              throw hr;
          }
  
          m_bInitialized = TRUE;
      }
  
      catch( HRESULT hr1 )
      {
          hr = hr1;
      }
  
      return hr;
  }
  
  
******************Public*Routine*of*Private*Class***********************\ RestoreDeviceObjects restores device objects for "walking figure" \*************************************************************************

  
  HRESULT CCharacter::RestoreDeviceObjects( IDirect3DDevice9* pDevice)
  {
      HRESULT hr = S_OK;
  
      if( !pDevice )
      {
          return E_POINTER;
      }
      try
      {
          // Setup render state
  
          CHECK_HR(
              hr = pDevice->SetSamplerState(0, D3DSAMP_ADDRESSU ,D3DTADDRESS_WRAP),
              DbgMsg("CHall::RestoreDeviceObjects failed to set D3DSAMP_ADDRESSU/D3DTADDRESS_WRAP, hr = 0x%08x", hr));
  
          CHECK_HR(
              hr = pDevice->SetSamplerState(0, D3DSAMP_ADDRESSV ,D3DTADDRESS_WRAP),
              DbgMsg("CHall::RestoreDeviceObjects failed to set D3DSAMP_ADDRESSV/D3DTADDRESS_WRAP, hr = 0x%08x", hr));
  
          CHECK_HR(
              hr = pDevice->SetRenderState( D3DRS_ZENABLE, TRUE ), 
              DbgMsg("CCharacter::RestoreDeviceObjects: failed to set render state D3DRS_ZENABLE/TRUE, hr = 0x%08x", hr));
  
          CHECK_HR(
              hr = pDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_CCW ),
              DbgMsg("CCharacter::RestoreDeviceObjects: failed to set render state D3DRS_CULLMODE/D3DCULL_CCW, hr = 0x%08x", hr));
  
          CHECK_HR(
              hr = pDevice->SetRenderState( D3DRS_AMBIENT, 0x55555555 ),
              DbgMsg("CCharacter::RestoreDeviceObjects: failed to set render state D3DRS_AMBIENT/0x33333333, hr = 0x%08x", hr));
  
                    //CHECK_HR(
                      // hr = pDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
                          if (!scene::ds("movie:blend")) hr = pDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
              //DbgMsg("CHall::RestoreDeviceObjects failed to set D3DRS_ALPHABLENDENABLE/TRUE, hr = 0x%08x", hr));
  
          CHECK_HR(
              hr = pDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA),
              DbgMsg("CHall::RestoreDeviceObjects failed to set D3DRS_SRCBLEND/D3DBLEND_SRCALPHA, hr = 0x%08x", hr));
  
          CHECK_HR(
              hr = pDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA),
              DbgMsg("CHall::RestoreDeviceObjects failed to set D3DRS_DESTBLEND/D3DBLEND_INVSRCALPHA, hr = 0x%08x", hr));
  
          CHECK_HR(
              hr = pDevice->SetRenderState( D3DRS_DITHERENABLE, TRUE ),
              DbgMsg("CHall::RestoreDeviceObjects failed to set D3DRS_DITHERENABLE/TRUE, hr = 0x%08x", hr));
  
          CHECK_HR(
              hr = pDevice->SetRenderState( D3DRS_AMBIENT, 0xFFFFFFFF ),
              DbgMsg("CHall::RestoreDeviceObjects failed to set D3DRS_AMBIENT/0xFFFFFFFF, hr = 0x%08x", hr));
  
          CHECK_HR(
              hr = pDevice->SetRenderState(D3DRS_LIGHTING, FALSE),
              DbgMsg("CHall::RestoreDeviceObjects failed to set D3DRS_LIGHTING/FALSE, hr = 0x%08x", hr));
  
          CHECK_HR(
              hr = pDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE),
              DbgMsg("CHall::RestoreDeviceObjects failed to set D3DRS_CULLMODE/D3DCULL_NONE, hr = 0x%08x", hr));
  
          CHECK_HR(
              hr = pDevice->SetSamplerState(0, D3DSAMP_ADDRESSU ,D3DTADDRESS_WRAP),
              DbgMsg("CHall::RestoreDeviceObjects failed to set D3DSAMP_ADDRESSU/D3DTADDRESS_WRAP, hr = 0x%08x", hr));
  
          CHECK_HR(
              hr = pDevice->SetSamplerState(0, D3DSAMP_ADDRESSV ,D3DTADDRESS_WRAP),
              DbgMsg("CHall::RestoreDeviceObjects failed to set D3DSAMP_ADDRESSV/D3DTADDRESS_WRAP, hr = 0x%08x", hr));
  
          CHECK_HR(
              hr = pDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1),
              DbgMsg("CHall::RestoreDeviceObjects failed to set D3DTSS_ALPHAOP/D3DTOP_SELECTARG1, hr = 0x%08x", hr));
  
          CHECK_HR(
              hr = pDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE),
              DbgMsg("CHall::RestoreDeviceObjects failed to set D3DTSS_ALPHAARG1/D3DTA_DIFFUSE, hr = 0x%08x", hr));
                  if (1) { //XX
          hr = pDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE);
      hr = pDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
      hr = pDevice->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_TEXTURE);
      hr = pDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
                  }
          }// try
      catch(HRESULT hr1)
      {
          hr = hr1;
      }
      return hr;
  }
  
  
******************Public*Routine*of*Private*Class***********************\ Compose restores device objects for "walking figure" \*************************************************************************

  
  HRESULT CCharacter::Compose(DWORD t)
  {
      HRESULT hr = S_OK;
      static DWORD dwLastTick = 0L;
  
      DOUBLE fElapsedTime;
  
      if( 0L == dwLastTick )
      {
          fElapsedTime = 0.f;
      }
      else
      {
                  fElapsedTime = ((DOUBLE)(t - dwLastTick)/1000.f) * (scene::ds("walk:speed") / 100.0);
      }
      dwLastTick = t;
  
      if (m_pAnimController != NULL)
          m_pAnimController->AdvanceTime(fElapsedTime, NULL);
  
          if (once == 0) {
  //        float xrot = -0.5;
  //        float yrot = 0.0;
  //        float zrot = 1.0;
  
   D3DXMATRIX mat, matx, maty, matz;
   D3DXMatrixIdentity(&mat);
   D3DXMatrixIdentity(&matx);
   D3DXMatrixIdentity(&matx);
   D3DXMatrixIdentity(&matz);
   D3DXMatrixRotationX(&matx, xrot*3.14);
   //D3DXMatrixIdentity(&mat);
   D3DXMatrixRotationY(&maty, yrot*3.14);
   //D3DXMatrixIdentity(&mat);
   D3DXMatrixRotationZ(&matz, zrot*3.14);
      D3DXMatrixMultiply(&mat,&maty,&matz);
   D3DXMatrixMultiply(&mat,&mat,&matx);
      once++;
   D3DXMatrixMultiply(&g_matCharacterWorld,&mat,&g_matCharacterWorld);
      }
  
      UpdateFrameMatrices_(m_pFrameRoot, &g_matCharacterWorld);
  
      return hr;
  }
  
  
******************Public*Routine*of*Private*Class***********************\ Render \*************************************************************************

  
  HRESULT CCharacter::Render(IDirect3DDevice9* pDevice)
  {
      HRESULT hr = S_OK;
  
      if( !pDevice )
      {
          return E_POINTER;
      }
      try
      {
          CHECK_HR(
              hr = RestoreDeviceObjects( pDevice ),
              DbgMsg("CCharacter::Render: failed in RestoreDeviceObjects, hr = 0x%08x", hr));
  
          CHECK_HR(
              hr = DrawFrame_(pDevice, m_pFrameRoot ),
              DbgMsg("CCharacter::Render: failed in DrawFrame_, hr = 0x%08x", hr));
      }
      catch( HRESULT hr1 )
      {
          hr = hr1;
      }
      return hr;
  }
  
  
******************Private*Routine*of*Private*Class**********************\ DrawFrame_ Draws of frame of the frame hierarchy \*************************************************************************

  
  HRESULT CCharacter::DrawFrame_(IDirect3DDevice9* pDevice, LPD3DXFRAME pFrame)
  {
      HRESULT hr = S_OK;
      LPD3DXMESHCONTAINER pMeshContainer;
  
      pMeshContainer = pFrame->pMeshContainer;
      while (pMeshContainer != NULL)
      {
          DrawMeshContainer_(pDevice, pMeshContainer, pFrame);
  
          pMeshContainer = pMeshContainer->pNextMeshContainer;
      }
  
      if (pFrame->pFrameSibling != NULL)
      {
          DrawFrame_(pDevice, pFrame->pFrameSibling);
      }
  
      if (pFrame->pFrameFirstChild != NULL)
      {
          DrawFrame_(pDevice, pFrame->pFrameFirstChild);
      }
      return S_OK;
  }
  
  
******************Private*Routine*of*Private*Class**********************\ DrawMeshContainer_ \*************************************************************************

  
  HRESULT CCharacter::DrawMeshContainer_( IDirect3DDevice9* pDevice,
                                          LPD3DXMESHCONTAINER pMeshContainerBase, 
                                          LPD3DXFRAME pFrameBase)
  {
      D3DXMESHCONTAINER_DERIVED *pMeshContainer = (D3DXMESHCONTAINER_DERIVED*)pMeshContainerBase;
      D3DXFRAME_DERIVED *pFrame = (D3DXFRAME_DERIVED*)pFrameBase;
      UINT iMaterial;
      UINT NumBlend;
      UINT iAttrib;
      DWORD AttribIdPrev;
      LPD3DXBONECOMBINATION pBoneComb;
  
      UINT iMatrixIndex;
      D3DXMATRIXA16 matTemp;
  
      // first check for skinning
      if (pMeshContainer->pSkinInfo != NULL)
      {
          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++)
          {
              DWORD i;
              NumBlend = 0;
              for (i = 0; i < pMeshContainer->NumInfl; ++i)
              {
                  if (pBoneComb[iAttrib].BoneId[i] != UINT_MAX)
                  {
                      NumBlend = i;
                  }
              }
  
              // first calculate the world matrices for the current set of blend weights and get the accurate count of the number of blends
              for (i = 0; i < pMeshContainer->NumInfl; ++i)
              {
                  iMatrixIndex = pBoneComb[iAttrib].BoneId[i];
                  if (iMatrixIndex != UINT_MAX)
                  {
                      pDevice->SetTransform(D3DTS_WORLDMATRIX(i), pMeshContainer->ppBoneMatrixPtrs[iMatrixIndex]);
                      pDevice->MultiplyTransform(D3DTS_WORLDMATRIX(i), &pMeshContainer->pBoneOffsetMatrices[iMatrixIndex]);
                  }
              }
  
              pDevice->SetRenderState(D3DRS_VERTEXBLEND, NumBlend);
  
              // lookup the material used for this subset of faces
              if ((AttribIdPrev != pBoneComb[iAttrib].AttribId) || (AttribIdPrev == UNUSED32))
              {
                  pDevice->SetMaterial( &pMeshContainer->pMaterials[pBoneComb[iAttrib].AttribId].MatD3D );
                  //pDevice->SetTexture( 0, pMeshContainer->ppTextures[pBoneComb[iAttrib].AttribId] );
                                  //pDevice->SetTexture( 0, GM->get_capture(GM->project()));
                                  //pDevice->SetTexture( 0, VP->get_capture(VP->get_active()));
                                  pDevice->SetTexture( 0, scene::tx(scene::cm("character")));
  
                  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; 
              pDevice->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;
                      }
                  }
  
                  // first calculate the world matrices for the current set of blend weights and get the accurate count of the number of blends
                  for (int i = 0; i < pMeshContainer->NumInfl; ++i)
                  {
                      iMatrixIndex = pBoneComb[iAttrib].BoneId[i];
                      if (iMatrixIndex != UINT_MAX)
                      {
                          pDevice->SetTransform(D3DTS_WORLDMATRIX(i), pMeshContainer->ppBoneMatrixPtrs[iMatrixIndex]);
                          pDevice->MultiplyTransform(D3DTS_WORLDMATRIX(i), &pMeshContainer->pBoneOffsetMatrices[iMatrixIndex]);
                      }
                  }
  
                  pDevice->SetRenderState(D3DRS_VERTEXBLEND, NumBlend);
  
                  // lookup the material used for this subset of faces
                  if ((AttribIdPrev != pBoneComb[iAttrib].AttribId) || (AttribIdPrev == UNUSED32))
                  {
                      pDevice->SetMaterial( &pMeshContainer->pMaterials[pBoneComb[iAttrib].AttribId].MatD3D );
                      //pDevice->SetTexture( 0, pMeshContainer->ppTextures[pBoneComb[iAttrib].AttribId] );
                                          //pDevice->SetTexture( 0, GM->get_capture(GM->project()));
                                      //pDevice->SetTexture( 0, VP->get_capture(VP->get_active()));
                                          pDevice->SetTexture( 0, scene::tx(scene::cm("character")));
  
                      AttribIdPrev = pBoneComb[iAttrib].AttribId;
                  }
  
                  // draw the subset now that the correct material and matrices are loaded
                  pMeshContainer->MeshData.pMesh->DrawSubset(iAttrib);
              }
              pDevice->SetSoftwareVertexProcessing(FALSE);
          }
  
              pDevice->SetRenderState(D3DRS_VERTEXBLEND, 0);
      }
      else  // standard mesh, just draw it after setting material properties
      {
          pDevice->SetTransform(D3DTS_WORLD, &pFrame->CombinedTransformationMatrix);
  
          for (iMaterial = 0; iMaterial < pMeshContainer->NumMaterials; iMaterial++)
          {
              pDevice->SetMaterial( &pMeshContainer->pMaterials[iMaterial].MatD3D );
              //pDevice->SetTexture( 0, pMeshContainer->ppTextures[iMaterial] );
              //pDevice->SetTexture( 0, GM->get_capture(GM->project()));
                          //pDevice->SetTexture( 0, VP->get_capture(VP->get_active()));
                          pDevice->SetTexture( 0, scene::tx(scene::cm("character")));
  
                          pMeshContainer->MeshData.pMesh->DrawSubset(iMaterial);
          }
      }
      return S_OK;
  }
  
  
******************Private*Routine*of*Private*Class**********************\ UpdateFrameMatrices_ \*************************************************************************

  
  HRESULT CCharacter::UpdateFrameMatrices_(LPD3DXFRAME pFrameBase, D3DXMATRIX* pM)
  {
      D3DXFRAME_DERIVED *pFrame = (D3DXFRAME_DERIVED*)pFrameBase;
  
      if (pM != NULL)
          D3DXMatrixMultiply(&pFrame->CombinedTransformationMatrix, &pFrame->TransformationMatrix, pM);
      else
          pFrame->CombinedTransformationMatrix = pFrame->TransformationMatrix;
  
      if (pFrame->pFrameSibling != NULL)
      {
          UpdateFrameMatrices_(pFrame->pFrameSibling, pM);
      }
  
      if (pFrame->pFrameFirstChild != NULL)
      {
          UpdateFrameMatrices_(pFrame->pFrameFirstChild, &pFrame->CombinedTransformationMatrix);
      }
  
      return S_OK;
  }
  
  
******************Private*Routine*of*Private*Class***********************\ SetupBoneMatrixPointers_ Called to setup the pointers for a given bone to its transformation matrix ( see SkinnedMesh sample of Direct3D of this SDK ) \*************************************************************************

  
  HRESULT CCharacter::SetupBoneMatrixPointers_( LPD3DXFRAME pFrame)
  {
      HRESULT hr = S_OK;
  
      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;
  }
  
  
******************Private*Routine*of*Private*Class***********************\ SetupBoneMatrixPointersOnMesh_ Called to setup the pointers for a given bone to its transformation matrix ( see SkinnedMesh sample of Direct3D of this SDK ) \*************************************************************************

  
  HRESULT CCharacter::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;
  }
  
  
////////////////////////// CAllocateHierarchy
/////////////////////


//----------------------------------------------------------------------------- // Name: AllocateName() // Desc: Allocates memory for a string to hold the name of a frame or mesh //----------------------------------------------------------------------------- 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; } //----------------------------------------------------------------------------- // CAllocateHierarchy // Constructor //----------------------------------------------------------------------------- CAllocateHierarchy::CAllocateHierarchy(IDirect3DDevice9* pDevice) : m_pDevice( NULL ) { if( pDevice ) { m_pDevice = pDevice; m_pDevice->AddRef(); } } //----------------------------------------------------------------------------- // ~CAllocateHierarchy // Destructor //----------------------------------------------------------------------------- CAllocateHierarchy::~CAllocateHierarchy() { RELEASE( m_pDevice ); } //----------------------------------------------------------------------------- // Name: CAllocateHierarchy::CreateFrame() // Desc: //----------------------------------------------------------------------------- HRESULT CAllocateHierarchy::CreateFrame(LPCTSTR Name, LPD3DXFRAME *ppNewFrame) { HRESULT hr = S_OK; D3DXFRAME_DERIVED *pFrame = NULL; *ppNewFrame = NULL; try { pFrame = new D3DXFRAME_DERIVED; if (pFrame == NULL) throw E_OUTOFMEMORY; hr = AllocateName(Name, &pFrame->Name); if (FAILED(hr)) { delete pFrame; throw hr; } // initialize other data members of the frame D3DXMatrixIdentity(&pFrame->TransformationMatrix); D3DXMatrixIdentity(&pFrame->CombinedTransformationMatrix); pFrame->pMeshContainer = NULL; pFrame->pFrameSibling = NULL; pFrame->pFrameFirstChild = NULL; *ppNewFrame = pFrame; pFrame = NULL; } catch( HRESULT hr1 ) { if( pFrame ) { delete pFrame; hr = hr1; } } return hr; } //----------------------------------------------------------------------------- // Name: CAllocateHierarchy::CreateMeshContainer() // Desc: //----------------------------------------------------------------------------- HRESULT CAllocateHierarchy::CreateMeshContainer( LPCTSTR Name, CONST D3DXMESHDATA *pMeshData, CONST D3DXMATERIAL *pMaterials, CONST D3DXEFFECTINSTANCE *pEffectInstances, DWORD NumMaterials, CONST DWORD *pAdjacency, LPD3DXSKININFO pSkinInfo, LPD3DXMESHCONTAINER *ppNewMeshContainer) { HRESULT hr = S_OK; D3DXMESHCONTAINER_DERIVED *pMeshContainer = NULL; UINT NumFaces; UINT iMaterial; UINT iBone, cBones; LPDIRECT3DDEVICE9 pd3dDevice = NULL; LPD3DXMESH pMesh = NULL; *ppNewMeshContainer = NULL; try { // this sample does not handle patch meshes, so fail when one is found if (pMeshData->Type != D3DXMESHTYPE_MESH) throw E_FAIL; // 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) throw E_FAIL; // allocate the overloaded structure to return as a D3DXMESHCONTAINER pMeshContainer = new D3DXMESHCONTAINER_DERIVED; if (pMeshContainer == NULL) throw E_OUTOFMEMORY; 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)) throw hr; 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)) throw 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)) throw E_OUTOFMEMORY; 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 strTexturePath[MAX_PATH] = _T(""); DXUtil_FindMediaFileCb( strTexturePath, sizeof(strTexturePath), pMeshContainer->pMaterials[iMaterial].pTextureFilename ); if( FAILED( D3DXCreateTextureFromFile( pd3dDevice, strTexturePath, &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) throw E_OUTOFMEMORY; // 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 = GenerateSkinnedMesh_(pMeshContainer); if (FAILED(hr)) throw hr; } *ppNewMeshContainer = pMeshContainer; pMeshContainer = NULL; }// try catch( HRESULT hr1 ) { DestroyMeshContainer(pMeshContainer); hr = hr1; } RELEASE(pd3dDevice); return hr; } //----------------------------------------------------------------------------- // Name: CAllocateHierarchy::DestroyFrame() // Desc: //----------------------------------------------------------------------------- HRESULT CAllocateHierarchy::DestroyFrame(LPD3DXFRAME pFrameToFree) { if( pFrameToFree->Name ) { delete[] pFrameToFree->Name; pFrameToFree->Name = NULL; } if( pFrameToFree ) { delete pFrameToFree; pFrameToFree = NULL; } return S_OK; } //----------------------------------------------------------------------------- // Name: CAllocateHierarchy::DestroyMeshContainer() // Desc: //----------------------------------------------------------------------------- HRESULT CAllocateHierarchy::DestroyMeshContainer(LPD3DXMESHCONTAINER pMeshContainerBase) { UINT iMaterial; D3DXMESHCONTAINER_DERIVED *pMeshContainer = (D3DXMESHCONTAINER_DERIVED*)pMeshContainerBase; if( pMeshContainer->Name ) { delete[] pMeshContainer->Name; pMeshContainer->Name = NULL; } if( pMeshContainer->pAdjacency ) { delete[] pMeshContainer->pAdjacency; pMeshContainer->pAdjacency = NULL; } if( pMeshContainer->pMaterials ) { delete[] pMeshContainer->pMaterials; pMeshContainer->pMaterials = NULL; } if( pMeshContainer->pBoneOffsetMatrices ) { delete[] pMeshContainer->pBoneOffsetMatrices; pMeshContainer->pBoneOffsetMatrices = NULL; } // release all the allocated textures if (pMeshContainer->ppTextures != NULL) { for (iMaterial = 0; iMaterial < pMeshContainer->NumMaterials; iMaterial++) { RELEASE( pMeshContainer->ppTextures[iMaterial] ); } delete[] pMeshContainer->ppTextures; pMeshContainer->ppTextures = NULL; } if( pMeshContainer->ppBoneMatrixPtrs ) { delete[] pMeshContainer->ppBoneMatrixPtrs; pMeshContainer->ppBoneMatrixPtrs = NULL; } RELEASE( pMeshContainer->pBoneCombinationBuf ); RELEASE( pMeshContainer->MeshData.pMesh ); RELEASE( pMeshContainer->pSkinInfo ); RELEASE( pMeshContainer->pOrigMesh ); if( pMeshContainer ) { delete pMeshContainer; pMeshContainer = NULL; } return S_OK; } //----------------------------------------------------------------------------- // Name: CAllocateHierarchy::GenerateSkinnedMesh_() // Desc: //----------------------------------------------------------------------------- HRESULT CAllocateHierarchy::GenerateSkinnedMesh_(D3DXMESHCONTAINER_DERIVED *pMeshContainer) { HRESULT hr = S_OK; if( !pMeshContainer ) { return E_POINTER; } if (pMeshContainer->pSkinInfo == NULL) return hr; try { RELEASE( pMeshContainer->MeshData.pMesh ); RELEASE( pMeshContainer->pBoneCombinationBuf ); CHECK_HR( hr = pMeshContainer->pSkinInfo->ConvertToBlendedMesh ( pMeshContainer->pOrigMesh, D3DXMESH_MANAGED|D3DXMESHOPT_VERTEXCACHE, pMeshContainer->pAdjacency, NULL, NULL, NULL, &pMeshContainer->NumInfl, &pMeshContainer->NumAttributeGroups, &pMeshContainer->pBoneCombinationBuf, &pMeshContainer->MeshData.pMesh ), DbgMsg("CAllocateHierarchy::GenerateSkinnedMesh_: failed in ConvertToBlendedMesh, hr = 0x%08x", hr)); LPD3DXBONECOMBINATION rgBoneCombinations = reinterpret_cast<LPD3DXBONECOMBINATION>( pMeshContainer->pBoneCombinationBuf->GetBufferPointer()); // if there is both HW and SW, add the Software Processing flag if (pMeshContainer->iAttributeSW < pMeshContainer->NumAttributeGroups) { LPD3DXMESH pMeshTmp; CHECK_HR( hr = pMeshContainer->MeshData.pMesh->CloneMeshFVF( D3DXMESH_SOFTWAREPROCESSING | pMeshContainer->MeshData.pMesh->GetOptions(), pMeshContainer->MeshData.pMesh->GetFVF(), m_pDevice, &pMeshTmp), DbgMsg("CAllocateHierarchy::GenerateSkinnedMesh_: failed in CloneMeshFVF, hr = 0x%08x", hr)); pMeshContainer->MeshData.pMesh->Release(); pMeshContainer->MeshData.pMesh = pMeshTmp; pMeshTmp = NULL; } }// try catch( HRESULT hr1 ) { hr = hr1; } return hr; }


(C) Æliens 20/2/2008

You may not copy or print any of this material without explicit permission of the author or the publisher. In case of other copyright issues, contact the author.