//------------------------------------------------------------------------------ // 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 #include #include "d3dutil.h" #include "dxutil.h" #include "resource.h" //#include scene/scene.h" #include 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( 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( 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; }