Sign in to follow this  
Me_Neo_Diehard

what happens with my application?

Recommended Posts

I'm trying to make a program base on SkinnedMesh program in the DirectX SDK Samples. But the result is very bad. Please tell me some. Image hosted by Photobucket.com my project is just one file. + tiny.x + SkinnedMesh.fx + Tiny_skin.bmp //////////////////////////// #include <d3d9.h> #include <d3dx9.h> #include <vector> #include <windows.h> // enum for various skinning modes possible enum METHOD { D3DNONINDEXED, D3DINDEXED, SOFTWARE, D3DINDEXEDVS, D3DINDEXEDHLSLVS, NONE }; /*------ Global variables--------*/ HWND hWindow; LPDIRECT3D9 m_pD3D; LPDIRECT3DDEVICE9 m_pD3DDevice; const int Width = 1280; const int Height = 800; ID3DXEffect* g_pEffect = NULL; // D3DX effect interface IDirect3DTexture9* g_pMeshTexture = NULL; // Mesh texture DWORD g_dwBehaviorFlags; // Behavior flags of the 3D device METHOD g_SkinningMethod = D3DNONINDEXED; // Current skinning method LPD3DXFRAME g_pFrameRoot = NULL; ID3DXAnimationController* g_pAnimController = NULL; D3DXVECTOR3 g_vObjectCenter; // Center of bounding sphere of object FLOAT g_fObjectRadius; // Radius of bounding sphere of object bool g_bUseSoftwareVP; // Flag to indicate whether software vp is UINT g_NumBoneMatricesMax = 0; // required due to lack of hardwar D3DXMATRIXA16* g_pBoneMatrices = NULL; D3DXMATRIXA16 g_matView; // View matrix D3DXMATRIXA16 g_matProj; // Projection matrix D3DXMATRIXA16 g_matProjT; IDirect3DVertexShader9* g_pIndexedVertexShader[4]; D3DSURFACE_DESC m_d3dsdBackBuffer; // Surface desc of the backbuffer char Text[1024]; float g_MeshRadius = 334.0f; #ifndef SAFE_RELEASE #define SAFE_RELEASE(p) { if(p) { (p)->Release(); (p)=NULL; } } #endif #ifndef SAFE_DELETE #define SAFE_DELETE(p) { if(p) { delete (p); (p)=NULL; } } #endif #ifndef SAFE_DELETE_ARRAY #define SAFE_DELETE_ARRAY(p) { if(p) { delete[] (p); (p)=NULL; } } #endif //-------------------------------------------------------------------------------------- // Name: struct D3DXMESHCONTAINER_DERIVED // Desc: Structure derived from D3DXMESHCONTAINER so we can add some app-specific // info that will be stored with each mesh //-------------------------------------------------------------------------------------- struct D3DXMESHCONTAINER_DERIVED: public D3DXMESHCONTAINER { LPDIRECT3DTEXTURE9* ppTextures; // array of textures, entries are NULL if no texture specified // SkinMesh info LPD3DXMESH pOrigMesh; LPD3DXATTRIBUTERANGE pAttributeTable; DWORD NumAttributeGroups; DWORD NumInfl; LPD3DXBUFFER pBoneCombinationBuf; D3DXMATRIX** ppBoneMatrixPtrs; D3DXMATRIX* pBoneOffsetMatrices; DWORD NumPaletteEntries; bool UseSoftwareVP; DWORD iAttributeSW; // used to denote the split between SW and HW if necessary for non-indexed skinning }; class CAllocateHierarchy: public ID3DXAllocateHierarchy { public: STDMETHOD(CreateFrame)(THIS_ LPCSTR Name, LPD3DXFRAME *ppNewFrame); STDMETHOD(CreateMeshContainer)(THIS_ LPCSTR Name, CONST D3DXMESHDATA *pMeshData, CONST D3DXMATERIAL *pMaterials, CONST D3DXEFFECTINSTANCE *pEffectInstances, DWORD NumMaterials, CONST DWORD *pAdjacency, LPD3DXSKININFO pSkinInfo, LPD3DXMESHCONTAINER *ppNewMeshContainer); STDMETHOD(DestroyFrame)(THIS_ LPD3DXFRAME pFrameToFree); STDMETHOD(DestroyMeshContainer)(THIS_ LPD3DXMESHCONTAINER pMeshContainerBase); CAllocateHierarchy() {} }; ///////////////////////// HRESULT SetupBoneMatrixPointers( LPD3DXFRAME pFrame ); HRESULT SetupBoneMatrixPointersOnMesh( LPD3DXMESHCONTAINER pMeshContainer ); HRESULT GenerateSkinnedMesh( IDirect3DDevice9 *pd3dDevice, D3DXMESHCONTAINER_DERIVED *pMeshContainer ); ///////////////// //-------------------------------------------------------------------------------------- // Name: struct D3DXFRAME_DERIVED // Desc: Structure derived from D3DXFRAME so we can add some app-specific // info that will be stored with each frame //-------------------------------------------------------------------------------------- struct D3DXFRAME_DERIVED: public D3DXFRAME { D3DXMATRIXA16 CombinedTransformationMatrix; }; /*------Prototypes--------*/ LRESULT CALLBACK WndProc(HWND hWindow, UINT iMessage, WPARAM wParam, LPARAM lParam); HRESULT SetupDirect3D(void); HRESULT KillDirect3D(void); void Frame(float timeDelta); bool Setup(void); bool Setup() { HRESULT hr = 0; DWORD dwShaderFlags = D3DXFX_NOT_CLONEABLE; #ifdef DEBUG_VS dwShaderFlags |= D3DXSHADER_FORCE_VS_SOFTWARE_NOOPT; #endif #ifdef DEBUG_PS dwShaderFlags |= D3DXSHADER_FORCE_PS_SOFTWARE_NOOPT; #endif hr=D3DXCreateEffectFromFile( m_pD3DDevice, "SkinnedMesh.fx", NULL, NULL, dwShaderFlags, NULL, &g_pEffect, NULL ); if(FAILED(hr)) { ::MessageBox(0, "OptimizeInplace() - FAILED", 0, 0); return false; } // // Load the mesh // ID3DXBuffer* adjBuffer = 0; ID3DXBuffer* mtrlBuffer = 0; DWORD numMtrls = 0; CAllocateHierarchy Alloc; hr=D3DXLoadMeshHierarchyFromX( "tiny.x", D3DXMESH_MANAGED, m_pD3DDevice, &Alloc, NULL, &g_pFrameRoot, &g_pAnimController ); if(FAILED(hr)) { ::MessageBox(0, "OptimizeInplace() - FAILED", 0, 0); return false; } hr=SetupBoneMatrixPointers( g_pFrameRoot ); if(FAILED(hr)) { ::MessageBox(0, "OptimizeInplace() - FAILED", 0, 0); return false; } hr=D3DXFrameCalculateBoundingSphere( g_pFrameRoot, &g_vObjectCenter, &g_fObjectRadius ); if(FAILED(hr)) { ::MessageBox(0, "OptimizeInplace() - FAILED", 0, 0); return false; } // Store render target surface desc LPDIRECT3DSURFACE9 pBackBuffer = NULL; m_pD3DDevice->GetBackBuffer( 0, 0, D3DBACKBUFFER_TYPE_MONO, &pBackBuffer ); pBackBuffer->GetDesc( &m_d3dsdBackBuffer ); pBackBuffer->Release(); // Obtain the behavior flags D3DDEVICE_CREATION_PARAMETERS cp; m_pD3DDevice->GetCreationParameters( &cp ); g_dwBehaviorFlags = cp.BehaviorFlags; D3DXVECTOR3 vEye( 0, 0, -2*g_fObjectRadius ); D3DXVECTOR3 vAt( 0, 0, 0 ); D3DXVECTOR3 vUp( 0, 1, 0 ); D3DXMatrixLookAtLH( &g_matView, &vEye, &vAt, &vUp); m_pD3DDevice->SetTransform( D3DTS_VIEW, &g_matView ); return true; } HRESULT SetupDirect3D(void) { /* Create the Direct3D Object */ if (NULL == (m_pD3D = Direct3DCreate9 (D3D_SDK_VERSION ))) { return E_FAIL; } /* Get current display mode so we can know what bitdepth we are */ D3DDISPLAYMODE d3ddm; if( FAILED (m_pD3D->GetAdapterDisplayMode (D3DADAPTER_DEFAULT, &d3ddm))) { return E_FAIL; } /* Fill in the present parameters */ D3DPRESENT_PARAMETERS d3dpp; ZeroMemory (&d3dpp, sizeof(d3dpp)); d3dpp.BackBufferWidth = Width; d3dpp.BackBufferHeight = Height; d3dpp.BackBufferFormat = D3DFMT_X8R8G8B8; d3dpp.BackBufferCount = 1; d3dpp.MultiSampleType = D3DMULTISAMPLE_NONE; d3dpp.MultiSampleQuality = 0; d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; d3dpp.hDeviceWindow = hWindow; d3dpp.Windowed = false; d3dpp.EnableAutoDepthStencil = true; d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8; d3dpp.Flags = 0; d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT; d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; /*--------------------------------------------------------*/ /* Create the device */ if (FAILED(m_pD3D->CreateDevice (D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWindow, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &m_pD3DDevice ))) { return E_FAIL; } return D3D_OK; } HRESULT KillDirect3D ( void) { /* If any of the Direct3D objects exist, release them */ if ( NULL != m_pD3D) { m_pD3D->Release (); m_pD3D=0; } if (NULL != m_pD3DDevice) { m_pD3DDevice->Release (); m_pD3DDevice=0; } SAFE_RELEASE( g_pEffect ); CAllocateHierarchy Alloc; D3DXFrameDestroy( g_pFrameRoot, &Alloc ); SAFE_RELEASE( g_pAnimController ); return D3D_OK; } //-------------------------------------------------------------------------------------- // Called to render a mesh in the hierarchy //-------------------------------------------------------------------------------------- void DrawMeshContainer( IDirect3DDevice9 *pd3dDevice, LPD3DXMESHCONTAINER pMeshContainerBase, LPD3DXFRAME pFrameBase ) { HRESULT hr; D3DXMESHCONTAINER_DERIVED *pMeshContainer = (D3DXMESHCONTAINER_DERIVED*)pMeshContainerBase; D3DXFRAME_DERIVED *pFrame = (D3DXFRAME_DERIVED*)pFrameBase; UINT iMaterial; UINT NumBlend; UINT iAttrib; DWORD AttribIdPrev; LPD3DXBONECOMBINATION pBoneComb; UINT iMatrixIndex; UINT iPaletteEntry; D3DXMATRIXA16 matTemp; D3DCAPS9 d3dCaps; pd3dDevice->GetDeviceCaps( &d3dCaps ); // first check for skinning if (pMeshContainer->pSkinInfo != NULL) { if( g_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( 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] ); pd3dDevice->SetTransform( D3DTS_WORLDMATRIX( i ), &matTemp ) ; } } pd3dDevice->SetRenderState(D3DRS_VERTEXBLEND, NumBlend) ; // lookup the material used for this subset of faces if ((AttribIdPrev != pBoneComb[iAttrib].AttribId) || (AttribIdPrev == UNUSED32)) { pd3dDevice->SetMaterial( &pMeshContainer->pMaterials[pBoneComb[iAttrib].AttribId].MatD3D ) ; pd3dDevice->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; pd3dDevice->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 (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] ); pd3dDevice->SetTransform( D3DTS_WORLDMATRIX( i ), &matTemp ) ; } } pd3dDevice->SetRenderState(D3DRS_VERTEXBLEND, NumBlend); // lookup the material used for this subset of faces if ((AttribIdPrev != pBoneComb[iAttrib].AttribId) || (AttribIdPrev == UNUSED32)) { pd3dDevice->SetMaterial( &pMeshContainer->pMaterials[pBoneComb[iAttrib].AttribId].MatD3D ); pd3dDevice->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) ; } } pd3dDevice->SetSoftwareVertexProcessing( FALSE ) ; } pd3dDevice->SetRenderState( D3DRS_VERTEXBLEND, 0) ; } else if (g_SkinningMethod == D3DINDEXED) { // if hw doesn't support indexed vertex processing, switch to software vertex processing if (pMeshContainer->UseSoftwareVP) { // If hw or pure hw vertex processing is forced, we can't render the // mesh, so just exit out. Typical applications should create // a device with appropriate vertex processing capability for this // skinning method. if( g_dwBehaviorFlags & D3DCREATE_HARDWARE_VERTEXPROCESSING ) return; pd3dDevice->SetSoftwareVertexProcessing(TRUE) ; } // set the number of vertex blend indices to be blended if (pMeshContainer->NumInfl == 1) { pd3dDevice->SetRenderState(D3DRS_VERTEXBLEND, D3DVBF_0WEIGHTS) ; } else { pd3dDevice->SetRenderState(D3DRS_VERTEXBLEND, pMeshContainer->NumInfl - 1) ; } if (pMeshContainer->NumInfl) pd3dDevice->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] ); pd3dDevice->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 pd3dDevice->SetMaterial( &pMeshContainer->pMaterials[pBoneComb[iAttrib].AttribId].MatD3D ) ; pd3dDevice->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 pd3dDevice->SetRenderState(D3DRS_INDEXEDVERTEXBLENDENABLE, FALSE) ; pd3dDevice->SetRenderState(D3DRS_VERTEXBLEND, 0) ; // remember to reset back to hw vertex processing if software was required if (pMeshContainer->UseSoftwareVP) { pd3dDevice->SetSoftwareVertexProcessing(FALSE) ; } } else if (g_SkinningMethod == D3DINDEXEDVS) { // Use COLOR instead of UBYTE4 since Geforce3 does not support it // vConst.w should be 3, but due to COLOR/UBYTE4 issue, mul by 255 and add epsilon D3DXVECTOR4 vConst( 1.0f, 0.0f, 0.0f, 765.01f ); if (pMeshContainer->UseSoftwareVP) { // If hw or pure hw vertex processing is forced, we can't render the // mesh, so just exit out. Typical applications should create // a device with appropriate vertex processing capability for this // skinning method. if( g_dwBehaviorFlags & D3DCREATE_HARDWARE_VERTEXPROCESSING ) return; pd3dDevice->SetSoftwareVertexProcessing(TRUE) ; } pd3dDevice->SetVertexShader( g_pIndexedVertexShader[pMeshContainer->NumInfl - 1] ) ; 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]); D3DXMatrixMultiplyTranspose(&matTemp, &matTemp, &g_matView); pd3dDevice->SetVertexShaderConstantF(iPaletteEntry*3 + 9, (float*)&matTemp, 3) ; } } // Sum of all ambient and emissive contribution D3DXCOLOR color1(pMeshContainer->pMaterials[pBoneComb[iAttrib].AttribId].MatD3D.Ambient); D3DXCOLOR color2(.25, .25, .25, 1.0); D3DXCOLOR ambEmm; D3DXColorModulate(&ambEmm, &color1, &color2); ambEmm += D3DXCOLOR(pMeshContainer->pMaterials[pBoneComb[iAttrib].AttribId].MatD3D.Emissive); // set material color properties pd3dDevice->SetVertexShaderConstantF(8, (float*)&(pMeshContainer->pMaterials[pBoneComb[iAttrib].AttribId].MatD3D.Diffuse), 1) ; pd3dDevice->SetVertexShaderConstantF(7, (float*)&ambEmm, 1) ; vConst.y = pMeshContainer->pMaterials[pBoneComb[iAttrib].AttribId].MatD3D.Power; pd3dDevice->SetVertexShaderConstantF(0, (float*)&vConst, 1) ; pd3dDevice->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 ) ; } // remember to reset back to hw vertex processing if software was required if (pMeshContainer->UseSoftwareVP) { pd3dDevice->SetSoftwareVertexProcessing(FALSE) ; } pd3dDevice->SetVertexShader( NULL ) ; } else if (g_SkinningMethod == D3DINDEXEDHLSLVS) { if (pMeshContainer->UseSoftwareVP) { // If hw or pure hw vertex processing is forced, we can't render the // mesh, so just exit out. Typical applications should create // a device with appropriate vertex processing capability for this // skinning method. if( g_dwBehaviorFlags & D3DCREATE_HARDWARE_VERTEXPROCESSING ) return; pd3dDevice->SetSoftwareVertexProcessing(TRUE) ; } 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]); D3DXMatrixMultiply(&g_pBoneMatrices[iPaletteEntry], &matTemp, &g_matView); } } g_pEffect->SetMatrixArray( "mWorldMatrixArray", g_pBoneMatrices, pMeshContainer->NumPaletteEntries) ; // Sum of all ambient and emissive contribution D3DXCOLOR color1(pMeshContainer->pMaterials[pBoneComb[iAttrib].AttribId].MatD3D.Ambient); D3DXCOLOR color2(.25, .25, .25, 1.0); D3DXCOLOR ambEmm; D3DXColorModulate(&ambEmm, &color1, &color2); ambEmm += D3DXCOLOR(pMeshContainer->pMaterials[pBoneComb[iAttrib].AttribId].MatD3D.Emissive); // set material color properties g_pEffect->SetVector("MaterialDiffuse", (D3DXVECTOR4*)&(pMeshContainer->pMaterials[pBoneComb[iAttrib].AttribId].MatD3D.Diffuse)) ; g_pEffect->SetVector("MaterialAmbient", (D3DXVECTOR4*)&ambEmm) ; // setup the material of the mesh subset - REMEMBER to use the original pre-skinning attribute id to get the correct material id pd3dDevice->SetTexture( 0, pMeshContainer->ppTextures[pBoneComb[iAttrib].AttribId] ) ; // Set CurNumBones to select the correct vertex shader for the number of bones g_pEffect->SetInt( "CurNumBones", pMeshContainer->NumInfl -1) ; // Start the effect now all parameters have been updated UINT numPasses; g_pEffect->Begin( &numPasses, D3DXFX_DONOTSAVESTATE ) ; for( UINT iPass = 0; iPass < numPasses; iPass++ ) { g_pEffect->BeginPass( iPass ) ; // draw the subset with the current world matrix palette and material state pMeshContainer->MeshData.pMesh->DrawSubset( iAttrib ) ; g_pEffect->EndPass() ; } g_pEffect->End() ; pd3dDevice->SetVertexShader(NULL) ; } // remember to reset back to hw vertex processing if software was required if (pMeshContainer->UseSoftwareVP) { pd3dDevice->SetSoftwareVertexProcessing(FALSE) ; } } else if (g_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 ( &g_pBoneMatrices[iBone], // output &pMeshContainer->pBoneOffsetMatrices[iBone], pMeshContainer->ppBoneMatrixPtrs[iBone] ); } // set world transform D3DXMatrixIdentity(&Identity); pd3dDevice->SetTransform(D3DTS_WORLD, &Identity) ; pMeshContainer->pOrigMesh->LockVertexBuffer(D3DLOCK_READONLY, (LPVOID*)&pbVerticesSrc) ; pMeshContainer->MeshData.pMesh->LockVertexBuffer(0, (LPVOID*)&pbVerticesDest) ; // generate skinned mesh pMeshContainer->pSkinInfo->UpdateSkinnedMesh(g_pBoneMatrices, NULL, pbVerticesSrc, pbVerticesDest); pMeshContainer->pOrigMesh->UnlockVertexBuffer() ; pMeshContainer->MeshData.pMesh->UnlockVertexBuffer() ; for (iAttrib = 0; iAttrib < pMeshContainer->NumAttributeGroups; iAttrib++) { pd3dDevice->SetMaterial(&(pMeshContainer->pMaterials[pMeshContainer->pAttributeTable[iAttrib].AttribId].MatD3D)) ; pd3dDevice->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 { pd3dDevice->SetTransform(D3DTS_WORLD, &pFrame->CombinedTransformationMatrix); for (iMaterial = 0; iMaterial < pMeshContainer->NumMaterials; iMaterial++) { pd3dDevice->SetMaterial( &pMeshContainer->pMaterials[iMaterial].MatD3D ) ; pd3dDevice->SetTexture( 0, pMeshContainer->ppTextures[iMaterial] ) ; pMeshContainer->MeshData.pMesh->DrawSubset(iMaterial) ; } } } void DrawFrame( IDirect3DDevice9 *pd3dDevice, LPD3DXFRAME pFrame ) { LPD3DXMESHCONTAINER pMeshContainer; pMeshContainer = pFrame->pMeshContainer; while (pMeshContainer != NULL) { DrawMeshContainer( pd3dDevice, pMeshContainer, pFrame ); pMeshContainer = pMeshContainer->pNextMeshContainer; } if (pFrame->pFrameSibling != NULL) { DrawFrame( pd3dDevice, pFrame->pFrameSibling); } if (pFrame->pFrameFirstChild != NULL) { DrawFrame( pd3dDevice, pFrame->pFrameFirstChild ); } } void Frame(float timeDelta) { HRESULT hr; // Clear the backbuffer m_pD3DDevice->Clear( 0L, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER, D3DCOLOR_ARGB(0, 66, 75, 121), 1.0f, 0L ); // Setup the light D3DLIGHT9 light; D3DXVECTOR3 vecLightDirUnnormalized(0.0f, -1.0f, 1.0f); ZeroMemory( &light, sizeof(D3DLIGHT9) ); light.Type = D3DLIGHT_DIRECTIONAL; light.Diffuse.r = 1.0f; light.Diffuse.g = 1.0f; light.Diffuse.b = 1.0f; D3DXVec3Normalize( (D3DXVECTOR3*)&light.Direction, &vecLightDirUnnormalized ); light.Position.x = 0.0f; light.Position.y = -1.0f; light.Position.z = 1.0f; light.Range = 1000.0f; m_pD3DDevice->SetLight(0, &light ); m_pD3DDevice->LightEnable(0, TRUE ) ; // Set Light for vertex shader D3DXVECTOR4 vLightDir( 0.0f, 1.0f, -1.0f, 0.0f ); D3DXVec4Normalize( &vLightDir, &vLightDir ); m_pD3DDevice->SetVertexShaderConstantF(1, (float*)&vLightDir, 1); g_pEffect->SetVector( "lhtDir", &vLightDir); // Setup the projection matrix D3DXMATRIXA16 matProj; FLOAT fAspect = (FLOAT)m_d3dsdBackBuffer.Width / (FLOAT)m_d3dsdBackBuffer.Height; D3DXMatrixPerspectiveFovLH( &matProj, D3DX_PI/4, fAspect, g_fObjectRadius/64.0f, g_fObjectRadius*200.0f ); m_pD3DDevice->SetTransform( D3DTS_PROJECTION, &matProj ); g_pEffect->SetMatrix( "mViewProj", &matProj); // set the projection matrix for the vertex shader based skinning method D3DXMatrixTranspose(&matProj, &matProj); m_pD3DDevice->SetVertexShaderConstantF(2, (float*)&matProj, 4); // Begin the scene if( SUCCEEDED( m_pD3DDevice->BeginScene() ) ) { DrawFrame( m_pD3DDevice, g_pFrameRoot ); m_pD3DDevice->EndScene(); } m_pD3DDevice->Present(0, 0, 0, 0); return; } int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInst, LPSTR lpCmdLine, int nShowCmd) { /* The window class */ WNDCLASS kWndClass; /* Visual property */ kWndClass.hCursor = LoadCursor (NULL, IDC_ARROW); kWndClass.hIcon = LoadIcon (NULL, IDI_APPLICATION); kWndClass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH); /* System properties */ kWndClass.hInstance = hInstance; kWndClass.lpfnWndProc = WndProc; kWndClass.lpszClassName = "Real Time message loop"; /* Extra properties */ kWndClass.lpszMenuName = NULL; kWndClass.cbClsExtra = NULL; kWndClass.cbWndExtra = NULL; kWndClass.style = NULL; /* Try to register class */ if (!RegisterClass (&kWndClass)) { return -1; } /* Create the window */ hWindow = CreateWindow ("Real time message loop", "Real time message loop", WS_EX_TOPMOST | WS_POPUP | WS_VISIBLE, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL); ShowWindow ( hWindow, nShowCmd); SetupDirect3D(); Setup(); /* Message loop */ MSG kMessage; /* Enter the real message loop */ static float lastTime = (float)timeGetTime(); while (1) { /* Query to see if there is any message in the que */ if (PeekMessage (&kMessage, hWindow, 0, 0, PM_REMOVE)) { /* If it is the WM_QUIT message, quit the loop */ if (WM_QUIT == kMessage.message) { break; } /* Process the message normally */ else { TranslateMessage(&kMessage); DispatchMessage (&kMessage); } } /* No message, do whatever we want */ else { float currTime = (float)timeGetTime(); float timeDelta = (currTime - lastTime)*0.001f; Frame(timeDelta); lastTime = currTime; } } KillDirect3D(); return 0L; } /* The Message Handler */ LRESULT CALLBACK WndProc (HWND hWindow, UINT iMessage, WPARAM wParam, LPARAM lParam) { switch (iMessage) { /* Close window */ case WM_CLOSE: PostQuitMessage (0); break; case WM_KEYDOWN: { switch( wParam ) { // Quit if the escape key is pressed case VK_ESCAPE: { PostQuitMessage(0); break; } case VK_SPACE: { break; } default: { break; } } } default: return DefWindowProc (hWindow, iMessage, wParam, lParam); } return 0; } HRESULT SetupBoneMatrixPointers( LPD3DXFRAME pFrame ) { HRESULT hr; if (pFrame->pMeshContainer != NULL) { hr = SetupBoneMatrixPointersOnMesh(pFrame->pMeshContainer); if (FAILED(hr)) return hr; } if (pFrame->pFrameSibling != NULL) { hr = SetupBoneMatrixPointers(pFrame->pFrameSibling); if (FAILED(hr)) return hr; } if (pFrame->pFrameFirstChild != NULL) { hr = SetupBoneMatrixPointers(pFrame->pFrameFirstChild); if (FAILED(hr)) return hr; } return S_OK; } //-------------------------------------------------------------------------------------- // Called to setup the pointers for a given bone to its transformation matrix //-------------------------------------------------------------------------------------- HRESULT 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( g_pFrameRoot, pMeshContainer->pSkinInfo->GetBoneName(iBone) ); if (pFrame == NULL) return E_FAIL; pMeshContainer->ppBoneMatrixPtrs[iBone] = &pFrame->CombinedTransformationMatrix; } } return S_OK; } //-------------------------------------------------------------------------------------- // Name: AllocateName() // Desc: Allocates memory for a string to hold the name of a frame or mesh //-------------------------------------------------------------------------------------- HRESULT AllocateName( LPCSTR Name, LPSTR *pNewName ) { UINT cbLength; if( Name != NULL ) { cbLength = (UINT)strlen(Name) + 1; *pNewName = new CHAR[cbLength]; if (*pNewName == NULL) return E_OUTOFMEMORY; memcpy( *pNewName, Name, cbLength*sizeof(CHAR) ); } else { *pNewName = NULL; } return S_OK; } //-------------------------------------------------------------------------------------- // Name: CAllocateHierarchy::CreateFrame() // Desc: //-------------------------------------------------------------------------------------- HRESULT CAllocateHierarchy::CreateFrame( LPCSTR Name, LPD3DXFRAME *ppNewFrame ) { HRESULT hr = S_OK; D3DXFRAME_DERIVED *pFrame; *ppNewFrame = NULL; pFrame = new D3DXFRAME_DERIVED; if (pFrame == NULL) { hr = E_OUTOFMEMORY; goto e_Exit; } hr = AllocateName(Name, &pFrame->Name); if (FAILED(hr)) goto e_Exit; // 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; e_Exit: delete pFrame; return hr; } //-------------------------------------------------------------------------------------- // Name: CAllocateHierarchy::CreateMeshContainer() // Desc: //-------------------------------------------------------------------------------------- HRESULT CAllocateHierarchy::CreateMeshContainer( LPCSTR Name, CONST D3DXMESHDATA *pMeshData, CONST D3DXMATERIAL *pMaterials, CONST D3DXEFFECTINSTANCE *pEffectInstances, DWORD NumMaterials, CONST DWORD *pAdjacency, LPD3DXSKININFO pSkinInfo, LPD3DXMESHCONTAINER *ppNewMeshContainer) { HRESULT hr; D3DXMESHCONTAINER_DERIVED *pMeshContainer = NULL; UINT NumFaces; UINT iMaterial; UINT iBone, cBones; LPDIRECT3DDEVICE9 pd3dDevice = NULL; LPD3DXMESH pMesh = NULL; *ppNewMeshContainer = NULL; // this sample does not handle patch meshes, so fail when one is found if (pMeshData->Type != D3DXMESHTYPE_MESH) { hr = E_FAIL; goto e_Exit; } // 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) { hr = E_FAIL; goto e_Exit; } // allocate the overloaded structure to return as a D3DXMESHCONTAINER pMeshContainer = new D3DXMESHCONTAINER_DERIVED; if (pMeshContainer == NULL) { hr = E_OUTOFMEMORY; goto e_Exit; } 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)) goto e_Exit; 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)) goto e_Exit; // 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)) { hr = E_OUTOFMEMORY; goto e_Exit; } 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) { if( FAILED( D3DXCreateTextureFromFile( pd3dDevice, pMeshContainer->pMaterials[iMaterial].pTextureFilename, &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) { hr = E_OUTOFMEMORY; goto e_Exit; } // 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( pd3dDevice, pMeshContainer ); if (FAILED(hr)) goto e_Exit; } *ppNewMeshContainer = pMeshContainer; pMeshContainer = NULL; e_Exit: SAFE_RELEASE(pd3dDevice); // call Destroy function to properly clean up the memory allocated if (pMeshContainer != NULL) { DestroyMeshContainer(pMeshContainer); } return hr; } //-------------------------------------------------------------------------------------- // Name: CAllocateHierarchy::DestroyFrame() // Desc: //-------------------------------------------------------------------------------------- HRESULT CAllocateHierarchy::DestroyFrame(LPD3DXFRAME pFrameToFree) { SAFE_DELETE_ARRAY( pFrameToFree->Name ); SAFE_DELETE( pFrameToFree ); return S_OK; } //-------------------------------------------------------------------------------------- // Name: CAllocateHierarchy::DestroyMeshContainer() // Desc: //-------------------------------------------------------------------------------------- HRESULT CAllocateHierarchy::DestroyMeshContainer(LPD3DXMESHCONTAINER pMeshContainerBase) { UINT iMaterial; D3DXMESHCONTAINER_DERIVED *pMeshContainer = (D3DXMESHCONTAINER_DERIVED*)pMeshContainerBase; SAFE_DELETE_ARRAY( pMeshContainer->Name ); SAFE_DELETE_ARRAY( pMeshContainer->pAdjacency ); SAFE_DELETE_ARRAY( pMeshContainer->pMaterials ); SAFE_DELETE_ARRAY( pMeshContainer->pBoneOffsetMatrices ); // release all the allocated textures if (pMeshContainer->ppTextures != NULL) { for (iMaterial = 0; iMaterial < pMeshContainer->NumMaterials; iMaterial++) { SAFE_RELEASE( pMeshContainer->ppTextures[iMaterial] ); } } SAFE_DELETE_ARRAY( pMeshContainer->ppTextures ); SAFE_DELETE_ARRAY( pMeshContainer->ppBoneMatrixPtrs ); SAFE_RELEASE( pMeshContainer->pBoneCombinationBuf ); SAFE_RELEASE( pMeshContainer->MeshData.pMesh ); SAFE_RELEASE( pMeshContainer->pSkinInfo ); SAFE_RELEASE( pMeshContainer->pOrigMesh ); SAFE_DELETE( pMeshContainer ); return S_OK; } //-------------------------------------------------------------------------------------- // Called either by CreateMeshContainer when loading a skin mesh, or when // changing methods. This function uses the pSkinInfo of the mesh // container to generate the desired drawable mesh and bone combination // table. //-------------------------------------------------------------------------------------- HRESULT GenerateSkinnedMesh( IDirect3DDevice9 *pd3dDevice, D3DXMESHCONTAINER_DERIVED *pMeshContainer ) { HRESULT hr = S_OK; D3DCAPS9 d3dCaps; pd3dDevice->GetDeviceCaps( &d3dCaps ); if( pMeshContainer->pSkinInfo == NULL ) return hr; g_bUseSoftwareVP = false; SAFE_RELEASE( pMeshContainer->MeshData.pMesh ); SAFE_RELEASE( pMeshContainer->pBoneCombinationBuf ); // if non-indexed skinning mode selected, use ConvertToBlendedMesh to generate drawable mesh if( g_SkinningMethod == D3DNONINDEXED ) { hr = pMeshContainer->pSkinInfo->ConvertToBlendedMesh ( pMeshContainer->pOrigMesh, D3DXMESH_MANAGED|D3DXMESHOPT_VERTEXCACHE, pMeshContainer->pAdjacency, NULL, NULL, NULL, &pMeshContainer->NumInfl, &pMeshContainer->NumAttributeGroups, &pMeshContainer->pBoneCombinationBuf, &pMeshContainer->MeshData.pMesh ); if (FAILED(hr)) goto e_Exit; // If the device can only do 2 matrix blends, ConvertToBlendedMesh cannot approximate all meshes to it // Thus we split the mesh in two parts: The part that uses at most 2 matrices and the rest. The first is // drawn using the device's HW vertex processing and the rest is drawn using SW vertex processing. LPD3DXBONECOMBINATION rgBoneCombinations = reinterpret_cast<LPD3DXBONECOMBINATION>(pMeshContainer->pBoneCombinationBuf->GetBufferPointer()); // look for any set of bone combinations that do not fit the caps for (pMeshContainer->iAttributeSW = 0; pMeshContainer->iAttributeSW < pMeshContainer->NumAttributeGroups; pMeshContainer->iAttributeSW++) { DWORD cInfl = 0; for (DWORD iInfl = 0; iInfl < pMeshContainer->NumInfl; iInfl++) { if (rgBoneCombinations[pMeshContainer->iAttributeSW].BoneId[iInfl] != UINT_MAX) { ++cInfl; } } if (cInfl > d3dCaps.MaxVertexBlendMatrices) { break; } } // if there is both HW and SW, add the Software Processing flag if (pMeshContainer->iAttributeSW < pMeshContainer->NumAttributeGroups) { LPD3DXMESH pMeshTmp; hr = pMeshContainer->MeshData.pMesh->CloneMeshFVF(D3DXMESH_SOFTWAREPROCESSING|pMeshContainer->MeshData.pMesh->GetOptions(), pMeshContainer->MeshData.pMesh->GetFVF(), pd3dDevice, &pMeshTmp); if (FAILED(hr)) { goto e_Exit; } pMeshContainer->MeshData.pMesh->Release(); pMeshContainer->MeshData.pMesh = pMeshTmp; pMeshTmp = NULL; } } // if indexed skinning mode selected, use ConvertToIndexedsBlendedMesh to generate drawable mesh else if( g_SkinningMethod == D3DINDEXED ) { DWORD NumMaxFaceInfl; DWORD Flags = D3DXMESHOPT_VERTEXCACHE; LPDIRECT3DINDEXBUFFER9 pIB; hr = pMeshContainer->pOrigMesh->GetIndexBuffer(&pIB); if (FAILED(hr)) goto e_Exit; hr = pMeshContainer->pSkinInfo->GetMaxFaceInfluences(pIB, pMeshContainer->pOrigMesh->GetNumFaces(), &NumMaxFaceInfl); pIB->Release(); if (FAILED(hr)) goto e_Exit; // 12 entry palette guarantees that any triangle (4 independent influences per vertex of a tri) // can be handled NumMaxFaceInfl = min(NumMaxFaceInfl, 12); if( d3dCaps.MaxVertexBlendMatrixIndex + 1 < NumMaxFaceInfl ) { // HW does not support indexed vertex blending. Use SW instead pMeshContainer->NumPaletteEntries = min(256, pMeshContainer->pSkinInfo->GetNumBones()); pMeshContainer->UseSoftwareVP = true; g_bUseSoftwareVP = true; Flags |= D3DXMESH_SYSTEMMEM; } else { // using hardware - determine palette size from caps and number of bones // If normals are present in the vertex data that needs to be blended for lighting, then // the number of matrices is half the number specified by MaxVertexBlendMatrixIndex. pMeshContainer->NumPaletteEntries = min( ( d3dCaps.MaxVertexBlendMatrixIndex + 1 ) / 2, pMeshContainer->pSkinInfo->GetNumBones() ); pMeshContainer->UseSoftwareVP = false; Flags |= D3DXMESH_MANAGED; } hr = pMeshContainer->pSkinInfo->ConvertToIndexedBlendedMesh ( pMeshContainer->pOrigMesh, Flags, pMeshContainer->NumPaletteEntries, pMeshContainer->pAdjacency, NULL, NULL, NULL, &pMeshContainer->NumInfl, &pMeshContainer->NumAttributeGroups, &pMeshContainer->pBoneCombinationBuf, &pMeshContainer->MeshData.pMesh); if (FAILED(hr)) goto e_Exit; } // if vertex shader indexed skinning mode selected, use ConvertToIndexedsBlendedMesh to generate drawable mesh else if( ( g_SkinningMethod == D3DINDEXEDVS ) || ( g_SkinningMethod == D3DINDEXEDHLSLVS ) ) { // Get palette size // First 9 constants are used for other data. Each 4x3 matrix takes up 3 constants. // (96 - 9) /3 i.e. Maximum constant count - used constants UINT MaxMatrices = 26; pMeshContainer->NumPaletteEntries = min(MaxMatrices, pMeshContainer->pSkinInfo->GetNumBones()); DWORD Flags = D3DXMESHOPT_VERTEXCACHE; if (d3dCaps.VertexShaderVersion >= D3DVS_VERSION(1, 1)) { pMeshContainer->UseSoftwareVP = false; Flags |= D3DXMESH_MANAGED; } else { pMeshContainer->UseSoftwareVP = true; g_bUseSoftwareVP = true; Flags |= D3DXMESH_SYSTEMMEM; } SAFE_RELEASE(pMeshContainer->MeshData.pMesh); hr = pMeshContainer->pSkinInfo->ConvertToIndexedBlendedMesh ( pMeshContainer->pOrigMesh, Flags, pMeshContainer->NumPaletteEntries, pMeshContainer->pAdjacency, NULL, NULL, NULL, &pMeshContainer->NumInfl, &pMeshContainer->NumAttributeGroups, &pMeshContainer->pBoneCombinationBuf, &pMeshContainer->MeshData.pMesh); if (FAILED(hr)) goto e_Exit; // FVF has to match our declarator. Vertex shaders are not as forgiving as FF pipeline DWORD NewFVF = (pMeshContainer->MeshData.pMesh->GetFVF() & D3DFVF_POSITION_MASK) | D3DFVF_NORMAL | D3DFVF_TEX1 | D3DFVF_LASTBETA_UBYTE4; if (NewFVF != pMeshContainer->MeshData.pMesh->GetFVF()) { LPD3DXMESH pMesh; hr = pMeshContainer->MeshData.pMesh->CloneMeshFVF(pMeshContainer->MeshData.pMesh->GetOptions(), NewFVF, pd3dDevice, &pMesh); if (!FAILED(hr)) { pMeshContainer->MeshData.pMesh->Release(); pMeshContainer->MeshData.pMesh = pMesh; pMesh = NULL; } } D3DVERTEXELEMENT9 pDecl[MAX_FVF_DECL_SIZE]; LPD3DVERTEXELEMENT9 pDeclCur; hr = pMeshContainer->MeshData.pMesh->GetDeclaration(pDecl); if (FAILED(hr)) goto e_Exit; // the vertex shader is expecting to interpret the UBYTE4 as a D3DCOLOR, so update the type // NOTE: this cannot be done with CloneMesh, that would convert the UBYTE4 data to float and then to D3DCOLOR // this is more of a "cast" operation pDeclCur = pDecl; while (pDeclCur->Stream != 0xff) { if ((pDeclCur->Usage == D3DDECLUSAGE_BLENDINDICES) && (pDeclCur->UsageIndex == 0)) pDeclCur->Type = D3DDECLTYPE_D3DCOLOR; pDeclCur++; } hr = pMeshContainer->MeshData.pMesh->UpdateSemantics(pDecl); if (FAILED(hr)) goto e_Exit; // allocate a buffer for bone matrices, but only if another mesh has not allocated one of the same size or larger if( g_NumBoneMatricesMax < pMeshContainer->pSkinInfo->GetNumBones() ) { g_NumBoneMatricesMax = pMeshContainer->pSkinInfo->GetNumBones(); // Allocate space for blend matrices delete[] g_pBoneMatrices; g_pBoneMatrices = new D3DXMATRIXA16[g_NumBoneMatricesMax]; if( g_pBoneMatrices == NULL ) { hr = E_OUTOFMEMORY; goto e_Exit; } } } // if software skinning selected, use GenerateSkinnedMesh to create a mesh that can be used with UpdateSkinnedMesh else if( g_SkinningMethod == SOFTWARE ) { hr = pMeshContainer->pOrigMesh->CloneMeshFVF(D3DXMESH_MANAGED, pMeshContainer->pOrigMesh->GetFVF(), pd3dDevice, &pMeshContainer->MeshData.pMesh); if (FAILED(hr)) goto e_Exit; hr = pMeshContainer->MeshData.pMesh->GetAttributeTable(NULL, &pMeshContainer->NumAttributeGroups); if (FAILED(hr)) goto e_Exit; delete[] pMeshContainer->pAttributeTable; pMeshContainer->pAttributeTable = new D3DXATTRIBUTERANGE[pMeshContainer->NumAttributeGroups]; if (pMeshContainer->pAttributeTable == NULL) { hr = E_OUTOFMEMORY; goto e_Exit; } hr = pMeshContainer->MeshData.pMesh->GetAttributeTable(pMeshContainer->pAttributeTable, NULL); if (FAILED(hr)) goto e_Exit; // allocate a buffer for bone matrices, but only if another mesh has not allocated one of the same size or larger if (g_NumBoneMatricesMax < pMeshContainer->pSkinInfo->GetNumBones()) { g_NumBoneMatricesMax = pMeshContainer->pSkinInfo->GetNumBones(); // Allocate space for blend matrices delete[] g_pBoneMatrices; g_pBoneMatrices = new D3DXMATRIXA16[g_NumBoneMatricesMax]; if( g_pBoneMatrices == NULL ) { hr = E_OUTOFMEMORY; goto e_Exit; } } } else // invalid g_SkinningMethod value { // return failure due to invalid skinning method value hr = E_INVALIDARG; goto e_Exit; } e_Exit: return hr; } ///////////////////////////

Share this post


Link to post
Share on other sites
Quote:
Original post by PinguinDude
You should really learn to use the source tags.

And here's where you learn to use them.

@OP: Is there anything specific about your code or an algorithm that you're having trouble with?

Share this post


Link to post
Share on other sites
ifyoudontusesourcetagsyourcodeisnotreadableandnooneisabletohelpyou
ifyouwanttolearnhowtousethempleasegoherehttp://www.gamedev.net/community/forums/faq.asp

Share this post


Link to post
Share on other sites
Quote:
Original post by Me_Neo_Diehard
Man, If you don't have anything to say, please pixx off!!


First, what is pixx?

Second, he did have something to say - that is, you should use source tags so it's easier for us to help you - so I fail to see the relevance of this reply.

Third, what is it supposed to look like? If it's supposed to look like an biological alien spacecraft, I'd say it looks fine. Is the color wrong? Is it not supposed to be such a spacecraft? Is it the aliasing, the blue background...

Fourth, Graphics Programming and Theory may be a more appropriate forum.

Fifth, it may do you good to learn how to split a project into multiple files. Honest.

Sixth, your post still isn't using source tags. The FAQ linked earlier will help you with this.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this