//-------------------------------------------------------------------------------------------------------------- static BOOL dcl_equal (D3DVERTEXELEMENT9* a, D3DVERTEXELEMENT9* b) { // check sizes u32 a_size = D3DXGetDeclLength(a); u32 b_size = D3DXGetDeclLength(b); if (a_size!=b_size) return FALSE; return 0==memcmp (a,b,a_size*sizeof(D3DVERTEXELEMENT9)); }
SDeclaration* CResourceManager::_CreateDecl (D3DVERTEXELEMENT9* dcl) { // Search equal code for (u32 it=0; it<v_declarations.size(); it++) { SDeclaration* D = v_declarations[it];; if (dcl_equal(dcl,&*D->dcl_code.begin())) return D; } // Create _new SDeclaration* D = xr_new<SDeclaration>(); u32 dcl_size = D3DXGetDeclLength(dcl)+1; CHK_DX (HW.pDevice->CreateVertexDeclaration(dcl,&D->dcl)); D->dcl_code.assign (dcl,dcl+dcl_size); D->dwFlags |= xr_resource_flagged::RF_REGISTERED; v_declarations.push_back(D); return D; }
//----------------------------------------------------------------------------- // Convert the mesh to the format specified by the given vertex declarations. //----------------------------------------------------------------------------- HRESULT CDXUTMesh::SetVertexDecl( LPDIRECT3DDEVICE9 pd3dDevice, const D3DVERTEXELEMENT9 *pDecl, bool bAutoComputeNormals, bool bAutoComputeTangents, bool bSplitVertexForOptimalTangents ) { LPD3DXMESH pTempMesh = NULL; if( m_pMesh ) { if( FAILED( m_pMesh->CloneMesh( m_pMesh->GetOptions(), pDecl, pd3dDevice, &pTempMesh ) ) ) { SAFE_RELEASE( pTempMesh ); return E_FAIL; } } // Check if the old declaration contains a normal. bool bHadNormal = false; bool bHadTangent = false; D3DVERTEXELEMENT9 aOldDecl[MAX_FVF_DECL_SIZE]; if( m_pMesh && SUCCEEDED( m_pMesh->GetDeclaration( aOldDecl ) ) ) { for( UINT index = 0; index < D3DXGetDeclLength( aOldDecl ); ++index ) { if( aOldDecl[index].Usage == D3DDECLUSAGE_NORMAL ) { bHadNormal = true; } if( aOldDecl[index].Usage == D3DDECLUSAGE_TANGENT ) { bHadTangent = true; } } } // Check if the new declaration contains a normal. bool bHaveNormalNow = false; bool bHaveTangentNow = false; D3DVERTEXELEMENT9 aNewDecl[MAX_FVF_DECL_SIZE]; if( pTempMesh && SUCCEEDED( pTempMesh->GetDeclaration( aNewDecl ) ) ) { for( UINT index = 0; index < D3DXGetDeclLength( aNewDecl ); ++index ) { if( aNewDecl[index].Usage == D3DDECLUSAGE_NORMAL ) { bHaveNormalNow = true; } if( aNewDecl[index].Usage == D3DDECLUSAGE_TANGENT ) { bHaveTangentNow = true; } } } SAFE_RELEASE( m_pMesh ); if( pTempMesh ) { m_pMesh = pTempMesh; if( !bHadNormal && bHaveNormalNow && bAutoComputeNormals ) { // Compute normals in case the meshes have them D3DXComputeNormals( m_pMesh, NULL ); } if( bHaveNormalNow && !bHadTangent && bHaveTangentNow && bAutoComputeTangents ) { ID3DXMesh* pNewMesh; HRESULT hr; DWORD *rgdwAdjacency = NULL; rgdwAdjacency = new DWORD[m_pMesh->GetNumFaces() * 3]; if( rgdwAdjacency == NULL ) return E_OUTOFMEMORY; V( m_pMesh->GenerateAdjacency(1e-6f,rgdwAdjacency) ); float fPartialEdgeThreshold; float fSingularPointThreshold; float fNormalEdgeThreshold; if( bSplitVertexForOptimalTangents ) { fPartialEdgeThreshold = 0.01f; fSingularPointThreshold = 0.25f; fNormalEdgeThreshold = 0.01f; } else { fPartialEdgeThreshold = -1.01f; fSingularPointThreshold = 0.01f; fNormalEdgeThreshold = -1.01f; } // Compute tangents, which are required for normal mapping hr = D3DXComputeTangentFrameEx( m_pMesh, D3DDECLUSAGE_TEXCOORD, 0, D3DDECLUSAGE_TANGENT, 0, D3DX_DEFAULT, 0, D3DDECLUSAGE_NORMAL, 0, 0, rgdwAdjacency, fPartialEdgeThreshold, fSingularPointThreshold, fNormalEdgeThreshold, &pNewMesh, NULL ); SAFE_DELETE_ARRAY( rgdwAdjacency ); if( FAILED(hr) ) return hr; SAFE_RELEASE( m_pMesh ); m_pMesh = pNewMesh; } } return S_OK; }
void CRender::LoadBuffers (CStreamReader *base_fs, BOOL _alternative) { R_ASSERT2 (base_fs,"Could not load geometry. File not found."); dxRenderDeviceRender::Instance().Resources->Evict (); // u32 dwUsage = D3DUSAGE_WRITEONLY; xr_vector<VertexDeclarator> &_DC = _alternative?xDC:nDC; xr_vector<ID3DVertexBuffer*> &_VB = _alternative?xVB:nVB; xr_vector<ID3DIndexBuffer*> &_IB = _alternative?xIB:nIB; // Vertex buffers { // Use DX9-style declarators CStreamReader *fs = base_fs->open_chunk(fsL_VB); R_ASSERT2 (fs,"Could not load geometry. File 'level.geom?' corrupted."); u32 count = fs->r_u32(); _DC.resize (count); _VB.resize (count); u32 bufferSize = (MAXD3DDECLLENGTH+1)*sizeof(D3DVERTEXELEMENT9); D3DVERTEXELEMENT9* dcl = (D3DVERTEXELEMENT9*)_alloca(bufferSize); for (u32 i=0; i<count; i++) { // decl // D3DVERTEXELEMENT9* dcl = (D3DVERTEXELEMENT9*) fs().pointer(); fs->r (dcl,bufferSize); fs->advance (-(int)bufferSize); u32 dcl_len = D3DXGetDeclLength (dcl)+1; _DC[i].resize (dcl_len); fs->r (_DC[i].begin(),dcl_len*sizeof(D3DVERTEXELEMENT9)); // count, size u32 vCount = fs->r_u32 (); u32 vSize = D3DXGetDeclVertexSize (dcl,0); Msg ("* [Loading VB] %d verts, %d Kb",vCount,(vCount*vSize)/1024); // Create and fill //BYTE* pData = 0; //R_CHK (HW.pDevice->CreateVertexBuffer(vCount*vSize,dwUsage,0,D3DPOOL_MANAGED,&_VB[i],0)); //R_CHK (_VB[i]->Lock(0,0,(void**)&pData,0)); // CopyMemory (pData,fs().pointer(),vCount*vSize); //fs->r (pData,vCount*vSize); //_VB[i]->Unlock (); // TODO: DX10: Check fragmentation. // Check if buffer is less then 2048 kb BYTE* pData = xr_alloc<BYTE>(vCount*vSize); fs->r (pData,vCount*vSize); dx10BufferUtils::CreateVertexBuffer (&_VB[i], pData, vCount*vSize); HW.stats_manager.increment_stats_vb (_VB[i]); xr_free(pData); // fs->advance (vCount*vSize); } fs->close (); } // Index buffers { CStreamReader *fs = base_fs->open_chunk(fsL_IB); u32 count = fs->r_u32(); _IB.resize (count); for (u32 i=0; i<count; i++) { u32 iCount = fs->r_u32 (); Msg("* [Loading IB] %d indices, %d Kb",iCount,(iCount*2)/1024); // Create and fill //BYTE* pData = 0; //R_CHK (HW.pDevice->CreateIndexBuffer(iCount*2,dwUsage,D3DFMT_INDEX16,D3DPOOL_MANAGED,&_IB[i],0)); //R_CHK (_IB[i]->Lock(0,0,(void**)&pData,0)); // CopyMemory (pData,fs().pointer(),iCount*2); //fs->r (pData,iCount*2); //_IB[i]->Unlock (); // TODO: DX10: Check fragmentation. // Check if buffer is less then 2048 kb BYTE* pData = xr_alloc<BYTE>(iCount*2); fs->r (pData,iCount*2); dx10BufferUtils::CreateIndexBuffer (&_IB[i], pData, iCount*2); HW.stats_manager.increment_stats_ib (_IB[i]); xr_free(pData); // fs().advance (iCount*2); } fs->close (); } }
//----------------------------------------------------------------------------- // Name: CDXUTMesh::SetVertexDecl // Desc: Convert the mesh to the format specified by the given vertex // declarations. //----------------------------------------------------------------------------- HRESULT CDXUTMesh::SetVertexDecl( LPDIRECT3DDEVICE9 pd3dDevice, const D3DVERTEXELEMENT9 *pDecl ) { LPD3DXMESH pTempSysMemMesh = NULL; LPD3DXMESH pTempLocalMesh = NULL; if( m_pSysMemMesh ) { if( FAILED( m_pSysMemMesh->CloneMesh( m_pSysMemMesh->GetOptions(), pDecl, pd3dDevice, &pTempSysMemMesh ) ) ) return E_FAIL; } if( m_pLocalMesh ) { if( FAILED( m_pLocalMesh->CloneMesh( m_pLocalMesh->GetOptions(), pDecl, pd3dDevice, &pTempLocalMesh ) ) ) { SAFE_RELEASE( pTempSysMemMesh ); return E_FAIL; } } // Check if the old declaration contains a normal. bool bHadNormal = false; D3DVERTEXELEMENT9 aOldDecl[MAX_FVF_DECL_SIZE]; if( m_pSysMemMesh && SUCCEEDED( m_pSysMemMesh->GetDeclaration( aOldDecl ) ) ) { for( UINT index = 0; index < D3DXGetDeclLength( aOldDecl ); ++index ) if( aOldDecl[index].Usage == D3DDECLUSAGE_NORMAL ) { bHadNormal = true; break; } } // Check if the new declaration contains a normal. bool bHaveNormalNow = false; D3DVERTEXELEMENT9 aNewDecl[MAX_FVF_DECL_SIZE]; if( pTempSysMemMesh && SUCCEEDED( pTempSysMemMesh->GetDeclaration( aNewDecl ) ) ) { for( UINT index = 0; index < D3DXGetDeclLength( aNewDecl ); ++index ) if( aNewDecl[index].Usage == D3DDECLUSAGE_NORMAL ) { bHaveNormalNow = true; break; } } SAFE_RELEASE( m_pSysMemMesh ); SAFE_RELEASE( m_pLocalMesh ); if( pTempSysMemMesh ) { m_pSysMemMesh = pTempSysMemMesh; if( !bHadNormal && bHaveNormalNow ) { // Compute normals in case the meshes have them D3DXComputeNormals( m_pSysMemMesh, NULL ); } } if( pTempLocalMesh ) { m_pLocalMesh = pTempLocalMesh; if( !bHadNormal && bHaveNormalNow ) { // Compute normals in case the meshes have them D3DXComputeNormals( m_pLocalMesh, NULL ); } } return S_OK; }
ETOOLS_API UINT WINAPI D3DX_GetDeclLength( CONST D3DVERTEXELEMENT9 *pDecl) { return D3DXGetDeclLength(pDecl); }