LPD3DXMESH Renderer::CreateD3DXTextMesh( const char* pString, bool bCentered ) { HRESULT hr; LPD3DXMESH pMeshNew = NULL; HDC hdc = CreateCompatibleDC( NULL ); if( hdc == NULL ) return NULL; HFONT newfont=CreateFont(10, //Height 0, //Width 0, //Escapement 0, //Orientation FW_NORMAL, //Weight false, //Italic false, //Underline false, //Strikeout DEFAULT_CHARSET,//Charset OUT_DEFAULT_PRECIS, //Output Precision CLIP_DEFAULT_PRECIS, //Clipping Precision DEFAULT_QUALITY, //Quality DEFAULT_PITCH|FF_DONTCARE, //Pitch and Family "Arial"); HFONT hFontOld; hFontOld = ( HFONT )SelectObject( hdc, newfont ); hr = D3DXCreateText( m_pD3DDevice, hdc, pString, 0.001f, 0.2f, &pMeshNew, NULL, NULL ); SelectObject( hdc, hFontOld ); DeleteDC( hdc ); if( SUCCEEDED( hr ) ) { if( bCentered ) { // Center text D3DXVECTOR3 vMin, vMax; PosNormalVertex* pVertices; pMeshNew->LockVertexBuffer( 0, reinterpret_cast<VOID**>(&pVertices)); D3DXComputeBoundingBox( (D3DXVECTOR3*)pVertices, pMeshNew->GetNumVertices(), sizeof ( PosNormalVertex ), &vMin, &vMax ); D3DXVECTOR3 vOffset; D3DXVec3Subtract( &vOffset, &vMax, &vMin ); D3DXVec3Scale( &vOffset, &vOffset, 0.5f ); for ( unsigned int i = 0; i < pMeshNew->GetNumVertices(); i++) { D3DXVec3Subtract( &pVertices[i].Coord, &pVertices[i].Coord, &vOffset ); } pMeshNew->UnlockVertexBuffer(); } } return pMeshNew; }
HRESULT D3DXMeshTransformation( LPD3DXMESH pMesh, const D3DXMATRIX* pMatrix , VisitorForD3DXVECTOR3* pPointFilter) { KG_PROCESS_ERROR(NULL != pMesh && NULL != pMatrix); { DWORD fvf = pMesh->GetFVF(); KG_PROCESS_ERROR(fvf | D3DFVF_XYZ); DWORD dwNumBytePerVertex = pMesh->GetNumBytesPerVertex(); _ASSERTE(dwNumBytePerVertex >= sizeof(D3DXVECTOR3)); DWORD dwNumVertex = pMesh->GetNumVertices(); BYTE* pBufferStart = NULL; _ASSERTE(sizeof(BYTE) == 1); if(NULL == pPointFilter) { HRESULT hr = pMesh->LockVertexBuffer(0, (LPVOID*)&pBufferStart); KG_COM_PROCESS_ERROR(hr); D3DXVec3TransformCoordArray((D3DXVECTOR3*)(pBufferStart), dwNumBytePerVertex , (D3DXVECTOR3*)pBufferStart, dwNumBytePerVertex, pMatrix, dwNumVertex); pMesh->UnlockVertexBuffer(); } else { //加了Filter之后性能下降是当然的,但是这不是给实时用的,所以没有关系,控制 //调用次数和调用时机就好了 D3DXMeshVertexEnumer vertexEnumer; HRESULT hr = D3DXMeshCreateVertexEnumer(pMesh, vertexEnumer); KG_COM_PROCESS_ERROR(hr); _ASSERTE(vertexEnumer.IsValid()); HRESULT hrForVisitor = E_FAIL; for (UINT i = 0; i < vertexEnumer.GetVertexCount(); ++i) { const D3DXVECTOR3& vTemp = vertexEnumer.GetPos(i); hrForVisitor = pPointFilter->Accept(vTemp); if (FAILED(hr)) { continue; } D3DXVECTOR3 vTransformed; D3DXVec3TransformCoord(&vTransformed, &vTemp, pMatrix); vertexEnumer.SetPos(i, vTransformed); } } } return S_OK; Exit0: return E_FAIL; }
LPD3DXMESH SkyBox::CreateMappedSphere(float fRad, UINT slices, UINT stacks) { // create the sphere LPD3DXMESH mesh; if (FAILED(D3DXCreateSphere(GameManager::GetDevice( ), fRad, slices, stacks, &mesh, NULL))) return NULL; // create a copy of the mesh with texture coordinates, // since the D3DX function doesn't include them LPD3DXMESH texMesh; if (FAILED(mesh->CloneMeshFVF(D3DXMESH_SYSTEMMEM, FVF_PositionNormalTexture::FVF, GameManager::GetDevice( ), &texMesh))) return mesh; // failed, return un-textured mesh mesh->Release( ); // finished with the original mesh, release it // lock the vertex buffer FVF_PositionNormalTexture* pVerts; //if (SUCCEEDED(texMesh->LockVertexBuffer(0, (BYTE **)&pVerts))) if (SUCCEEDED(texMesh->LockVertexBuffer(0, (LPVOID*)&pVerts))) { int numVerts = texMesh->GetNumVertices( ); // get vertex count // loop through the vertices for (int i = 0; i < numVerts; i++) { // calculate texture coordinates pVerts->tex.x = asinf(pVerts->normal.x) / D3DX_PI + 0.5f; pVerts->tex.y = asinf(pVerts->normal.y) / D3DX_PI + 0.5f; //pVerts->tex.x = 0.5f - (atan2f(pVerts->normal.z, pVerts->normal.x) / (2 * D3DX_PI)); //pVerts->tex.y = 0.5f - asinf(pVerts->normal.y) / (D3DX_PI); //pVerts->tex.y = pVerts->normal.y * 0.5 + 0.5; //if (pVerts->tex.x <(FLOAT)0.9) pVerts->tex.x = (FLOAT)0.0; //pVerts->tex.x = pVerts->pos.x / sqrtf((pVerts->pos.x * pVerts->pos.x) + (pVerts->pos.y * pVerts->pos.x) + (pVerts->pos.z * pVerts->pos.z)); //pVerts->tex.y = pVerts->pos.y / sqrtf((pVerts->pos.x * pVerts->pos.x) + (pVerts->pos.y * pVerts->pos.x) + (pVerts->pos.z * pVerts->pos.z)); //float theta = asinf(pVerts->normal.z); //float phi = atan2(pVerts->normal.y, pVerts->normal.x); // //pVerts->tex = D3DXVECTOR2(phi / 2 / 3.14159265, theta / 3.14159265); // go to next vertex pVerts++; } texMesh->UnlockVertexBuffer( ); // unlock the vertex buffer } // return pointer to caller return texMesh; }
LPD3DXMESH CWall::convertMesh(IDirect3DDevice9* pDevice, LPD3DXMESH& mesh){ D3DVERTEXELEMENT9 decl[] = { { 0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0 }, { 0, sizeof(D3DXVECTOR3), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0 }, { 0, sizeof(D3DXVECTOR3) * 2, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0 }, D3DDECL_END()//will be declared on }; LPD3DXMESH newMesh = nullptr; VERTEX* pVerts; HRESULT result = mesh->CloneMesh(D3DXMESH_SYSTEMMEM, decl, pDevice, &newMesh); if (FAILED(result)) return nullptr; float u = 0; float v = 0; bool reverse = false; if (SUCCEEDED(newMesh->LockVertexBuffer(0, (LPVOID*)&pVerts))){ int numVerts = newMesh->GetNumVertices(); for (int i = 0; i < numVerts; i++){ pVerts->tu = u; pVerts->tv = v; if (u == 0 && v==0){ if (reverse) u++; else v++; } else if (v == 1 && u == 0){ u++; } else if (v == 0 && u == 1){ v++; } else{ if (reverse) reverse = false; else reverse = true; u = 0; v = 0; } pVerts++; } newMesh->UnlockVertexBuffer(); //temporary uv generator return newMesh; } else{ return nullptr; } }
/** * \brief Called to render a mesh * \param device - the Direct3D device object * \param meshContainerBase - the mesh container * \param frameBase - frame containing the mesh * \author Keith Ditchburn \date 18 July 2005 */ void CXFileEntity::DrawMeshContainer(LPD3DXMESHCONTAINER meshContainerBase, LPD3DXFRAME frameBase) { DWORD attrSize = 0; // Cast to our extended frame type D3DXFRAME_EXTENDED *frame = (D3DXFRAME_EXTENDED*)frameBase; // Cast to our extended mesh container D3DXMESHCONTAINER_EXTENDED *meshContainer = (D3DXMESHCONTAINER_EXTENDED*)meshContainerBase; // Set the world transform m_d3dDevice->SetTransform(D3DTS_WORLD, &frame->exCombinedTransformationMatrix); unsigned int pass; if (effect) { effect->SetMatrix("worldmat",&frame->exCombinedTransformationMatrix); effect->Begin(&pass,0); effect->BeginPass(0); } // Loop through all the materials in the mesh rendering each subset for (unsigned int iMaterial = 0; iMaterial < meshContainer->NumMaterials; iMaterial++) { // use the material in our extended data rather than the one in meshContainer->pMaterials[iMaterial].MatD3D //m_d3dDevice->SetMaterial( &meshContainer->exMaterials[iMaterial] ); //m_d3dDevice->SetTexture( 0, meshContainer->exTextures[iMaterial] ); // Select the mesh to draw, if there is skin then use the skinned mesh else the normal one LPD3DXMESH pDrawMesh = (meshContainer->pSkinInfo) ? meshContainer->exSkinMesh: meshContainer->MeshData.pMesh; // Finally Call the mesh draw function //pDrawMesh->DrawSubset(iMaterial); pDrawMesh->GetVertexBuffer(&vb.vb); pDrawMesh->GetIndexBuffer(&ib.ib); //D3DVERTEXELEMENT9 pDecl[MAX_FVF_DECL_SIZE]; //pDrawMesh->GetDeclaration(pDecl); //renderSystem->CreateVertexDeclaration(&pDecl[0],&vb.declaration); // Получение данных о количестве вершин, индексов и полигонов dwNumVerticies = pDrawMesh->GetNumVertices(); dwNumIndecies = pDrawMesh->GetNumFaces()*3; dwNumFaces = pDrawMesh->GetNumFaces(); vb.vertexSize = (short)pDrawMesh->GetNumBytesPerVertex(); renderSystem->DrawIndexedPrimitive(vb,0,dwNumVerticies,ib,0,dwNumFaces); } if (effect) { effect->EndPass(); effect->End(); } }
bool Floor::ComputeBoundingBox() { if( m_computedBoundingBox) return true; BYTE* pVertices = NULL; LPD3DXMESH mesh = m_mesh->GetD3DMesh(); HRESULT hr = mesh->LockVertexBuffer(D3DLOCK_READONLY, (LPVOID*)&pVertices); if(FAILED(hr)) return false; D3DXComputeBoundingBox((D3DXVECTOR3*)pVertices, mesh->GetNumVertices(), mesh->GetNumBytesPerVertex(), &m_bottomLeft, &m_topRight); mesh->UnlockVertexBuffer(); m_computedBoundingBox = true; return true; }
void cMyASELoader::LoadMesh(){ #ifdef _DEBUG _ASSERT(m_bLoaded && "Data Not Loaded"); #endif int check = 0; for (size_t i = 0; i < m_vecASENode.size(); i++){ if (m_vecASENode[i].nRef != INT_MAX){ m_vecsubSet.push_back(m_vecASENode[i].nRef); LPD3DXMESH pMesh = NULL; HRESULT hr = D3DXCreateMeshFVF(m_vecASENode[i].vecVertex.size() / 3, m_vecASENode[i].vecVertex.size(), D3DXMESH_MANAGED, ST_PNT_VERTEX::FVF, g_pD3DDevice, &pMesh); ST_PNT_VERTEX* pV = NULL; pMesh->LockVertexBuffer(0, (LPVOID*)&pV); memcpy(pV, &m_vecASENode[i].vecVertex[0], m_vecASENode[i].vecVertex.size() * sizeof(ST_PNT_VERTEX)); pMesh->UnlockVertexBuffer(); WORD* pI = NULL; pMesh->LockIndexBuffer(0, (LPVOID*)&pI); for (size_t j = 0; j < pMesh->GetNumVertices(); ++j) { pI[j] = j; } pMesh->UnlockIndexBuffer(); DWORD* pA = NULL; pMesh->LockAttributeBuffer(0, &pA); for (size_t j = 0; j < pMesh->GetNumFaces(); j++){ pA[j] = m_vecASENode[i].nRef; } pMesh->UnlockAttributeBuffer(); std::vector<DWORD> vecAdjBuffer(m_vecASENode[i].vecVertex.size()); pMesh->GenerateAdjacency(0.0f, &vecAdjBuffer[0]); pMesh->OptimizeInplace( D3DXMESHOPT_ATTRSORT | D3DXMESHOPT_COMPACT | D3DXMESHOPT_VERTEXCACHE, &vecAdjBuffer[0], 0, 0, 0); m_vecMeshs.push_back(pMesh); } } m_bMeshed = true; }
HRESULT initGeometry(){ LPD3DXBUFFER pD3DXMtrlBuffer; if(FAILED(D3DXLoadMeshFromX(L"seafloor.x", D3DXMESH_MANAGED, g_pDevice, NULL, &pD3DXMtrlBuffer, NULL, &g_dwNumMaterials, &g_pMesh))) return E_FAIL; //Extract material & texture D3DXMATERIAL* d3dxMaterials = (D3DXMATERIAL*)pD3DXMtrlBuffer->GetBufferPointer(); g_pMeshMaterials = new D3DMATERIAL9[g_dwNumMaterials]; if(g_pMeshMaterials == NULL) return E_OUTOFMEMORY; g_pMeshTextures = new LPDIRECT3DTEXTURE9[g_dwNumMaterials]; if(g_pMeshTextures == NULL) return E_OUTOFMEMORY; //Extract for(DWORD i=0; i<g_dwNumMaterials; ++i){ g_pMeshMaterials[i] = d3dxMaterials[i].MatD3D; g_pMeshMaterials[i].Ambient = g_pMeshMaterials[i].Diffuse; g_pMeshTextures[i] = NULL; if(d3dxMaterials[i].pTextureFilename != NULL && strlen(d3dxMaterials[i].pTextureFilename) > 0){ WCHAR name[256]; removePathFromFileName(d3dxMaterials[i].pTextureFilename, name); if(FAILED(D3DXCreateTextureFromFile(g_pDevice, name, &g_pMeshTextures[i]))){ MessageBox(NULL, L"Cound not find texture file", L"initGeometry()", MB_OK); } } } pD3DXMtrlBuffer->Release(); //Modify the mesh LPDIRECT3DVERTEXBUFFER9 pVB; if(SUCCEEDED(g_pMesh->GetVertexBuffer(&pVB))){ struct VERTEX{FLOAT x,y,z,tu,tv;}; VERTEX* pVertices; DWORD dwNumVertices = g_pMesh->GetNumVertices(); pVB->Lock(0,0,(void**)&pVertices, 0); for(DWORD i=0; i<dwNumVertices; ++i) pVertices[i].y = heightField(pVertices[i].x, pVertices[i].z); pVB->Unlock(); pVB->Release(); } return S_OK; };
PRIVATE inline void _MDLCenterMesh(float trans[eMaxPt], LPD3DXMESH mesh) { gfxVtx *pVtx; if(SUCCEEDED(mesh->LockVertexBuffer(0, (BYTE**)&pVtx))) { for(int i = 0; i < mesh->GetNumVertices(); i++) { pVtx[i].x -= trans[eX]; pVtx[i].y -= trans[eY]; pVtx[i].z -= trans[eZ]; } mesh->UnlockVertexBuffer(); } }
bool CMesh::__GetBoundBox(const LPD3DXMESH pMesh, CRectangle3D& Rect3d) { if (pMesh == NULL) return false; UINT uVertexNum = pMesh->GetNumVertices(); LPD3DXMESH pTempMesh; pMesh->CloneMeshFVF(D3DXMESH_SYSTEMMEM, D3DFVF_XYZ, &DEVICE, &pTempMesh); LPDIRECT3DVERTEXBUFFER9 pVertexBuffer; pTempMesh->GetVertexBuffer(&pVertexBuffer); FLOAT maxX = 0.0f, maxY = 0.0f, maxZ = 0.0f; FLOAT minX = 0.0f, minY = 0.0f, minZ = 0.0f; D3DXVECTOR3* pVertices; pVertexBuffer->Lock(0, 0, (void**)&pVertices, 0); for(UINT i = 0; i < uVertexNum; i ++) { if(pVertices[i].x > maxX) maxX = pVertices[i].x; if(pVertices[i].y > maxY) maxY = pVertices[i].y; if(pVertices[i].z > maxZ) maxZ = pVertices[i].z; if(pVertices[i].x < minX) minX = pVertices[i].x; if(pVertices[i].y < minY) minY = pVertices[i].y; if(pVertices[i].z < minZ) minZ = pVertices[i].z; } pVertexBuffer->Unlock(); Rect3d.Set(minX, maxX, minY, maxY, minZ, maxZ); DEBUG_RELEASE(pVertexBuffer); DEBUG_RELEASE(pTempMesh); return true; }
/* ================================================================================ */ bool init_ff (const sD3D9_XMSH* xmesh, DWORD idx, const map_acs<crh3d9_texr>* texpool) { int32u* ptr; crh3d9_texr* texr; D3DXMATERIAL* mtrl; mtrl = (D3DXMATERIAL*)xmesh->xattr->GetBufferPointer(); mtrl += idx; if (mtrl->pTextureFilename != NULL) { texr = texpool->get(mtrl->pTextureFilename); if (texr == NULL) return (false); m_map_kd = texr->get_texr(); } else { m_map_kd = NULL; } m_idx = idx; m_msh = xmesh->xmesh; if (idx == 0) { m_nv = m_msh->GetNumVertices(); m_nt = m_msh->GetNumFaces(); } else { m_nv = m_nt = 0; } m_mtl = &mtrl->MatD3D; m_mtl->Ambient.r = m_mtl->Diffuse.r; m_mtl->Ambient.g = m_mtl->Diffuse.g; m_mtl->Ambient.b = m_mtl->Diffuse.b; m_mtl->Ambient.a = 0.0f; if (m_mtl->Diffuse.a < 1.0f) m_type |= ATTR_TYPE_ALPHAOP; if (m_map_kd != NULL) m_type |= ATTR_TYPE_TEXTURE; ptr = (int32u*)(&m_mtl->Specular); for (idx = 0; idx < 3; idx++) { if (*ptr != 0) { m_type |= ATTR_TYPE_SPECULAR; break; } ptr += 1; } return (true); }
HRESULT KG3DMesh::_LoadBSPFileFromMemory(IKG_Buffer *piBSPFile) { HRESULT hrResult = E_FAIL; HRESULT hrRetCode = E_FAIL; DWORD dwBSPVertexCount = 0; DWORD dwBSPFaceCount = 0; DWORD dwMeshVerticesCount = 0; DWORD dwMeshFacesCount = 0; LPD3DXMESH piMesh = m_ppMeshes[SMBT_NORMAL]; KG3DBsp *pBSP = NULL; ASSERT(piBSPFile); KGLOG_PROCESS_ERROR(piMesh); dwMeshFacesCount = piMesh->GetNumFaces(); dwMeshVerticesCount = piMesh->GetNumVertices(); pBSP = new KG3DBsp; KGLOG_PROCESS_ERROR(pBSP); hrRetCode = pBSP->LoadFromMemory(piBSPFile); KGLOG_COM_PROCESS_ERROR(hrRetCode); hrRetCode = pBSP->GetMeshInfo(&dwBSPVertexCount, &dwBSPFaceCount); KGLOG_COM_PROCESS_ERROR(hrRetCode); if ((dwBSPVertexCount != dwMeshVerticesCount) || (dwBSPFaceCount != dwMeshFacesCount)) { KGLogPrintf(KGLOG_ERR, "%s, BSP unmatch Mesh :(", m_scName.c_str()); KG_PROCESS_ERROR(FALSE); } ASSERT(!m_lpBsp); m_lpBsp = pBSP; pBSP = NULL; hrResult = S_OK; Exit0: KG_DELETE(pBSP); if(FAILED(hrResult)) { KGLogPrintf(KGLOG_ERR, "%s BSP加载失败", m_scName.c_str()); } return hrResult; }
HRESULT D3DXMeshCreateVertexEnumer( LPD3DXMESH pMesh, D3DXMeshVertexEnumer& enumer ) { _ASSERTE(! enumer.IsValid()); ZeroMemory(&enumer, sizeof(D3DXMeshVertexEnumer));//因为外部传入的enumer是可能重用的,这里绝对要重新清空一次 _ASSERTE(NULL != pMesh); KG_PROCESS_ERROR(NULL != pMesh); { BOOL bIsAcceptableMesh = pMesh->GetFVF() & D3DFVF_XYZ; KG_PROCESS_ERROR(bIsAcceptableMesh && _T("不支持没有XYZ标志的Mesh,那样不能保证每个节点开头是顶点")); HRESULT hr = pMesh->LockVertexBuffer(0, reinterpret_cast<LPVOID*>(&enumer.m_pBuffer)); KG_COM_PROCESS_ERROR(hr); _ASSERTE(1 == sizeof(BYTE)); enumer.m_pMesh = pMesh; enumer.m_pMesh->AddRef(); enumer.m_dwNumBytePerVertex = pMesh->GetNumBytesPerVertex(); enumer.m_dwNumVertexCount = pMesh->GetNumVertices(); return S_OK; } Exit0: return E_FAIL; }
VOID Update() { DWORD currentTime = GetTickCount(); static DWORD preTime; g_ElapsedTime = currentTime - preTime; preTime = currentTime; if ( GetAsyncKeyState( VK_LEFT ) ) { g_Box[0].CenterPos.x -= g_ElapsedTime*0.002f; } if ( GetAsyncKeyState( VK_RIGHT ) ) { g_Box[0].CenterPos.x += g_ElapsedTime*0.002f; } if ( GetAsyncKeyState( VK_UP ) ) { g_Box[0].CenterPos.y += g_ElapsedTime*0.002f; } if ( GetAsyncKeyState( VK_DOWN ) ) { g_Box[0].CenterPos.y -= g_ElapsedTime*0.002f; } if ( GetAsyncKeyState( VK_LBUTTON ) ) { if (g_ElapsedTime > 20) { g_Method = !g_Method; } } if ( GetAsyncKeyState( VK_HOME ) ) { g_Box[1].BoxRotateZ -= 0.2f; } if ( GetAsyncKeyState( VK_END ) ) { g_Box[1].BoxRotateZ += 0.2f; } D3DXVECTOR3 *vertices; g_pMesh->LockVertexBuffer( D3DLOCK_READONLY, (void**) &vertices ); D3DXComputeBoundingBox( vertices, g_pMesh->GetNumVertices(), g_pMesh->GetNumBytesPerVertex(), &g_MinPoint, &g_MaxPoint ); g_pMesh->UnlockVertexBuffer(); D3DXMATRIX matScale, matTrans, matRotateZ, matWorld; D3DXMatrixTranslation( &matTrans, g_Box[0].CenterPos.x, g_Box[0].CenterPos.y, g_Box[0].CenterPos.z ); D3DXMatrixScaling( &matScale, g_Box[0].BoxScaling, g_Box[0].BoxScaling, g_Box[0].BoxScaling ); D3DXMatrixRotationZ( &matRotateZ, g_Box[0].BoxRotateZ ); matWorld = matRotateZ* matScale * matTrans; D3DXVec3TransformCoord( &g_Box[0].MinPoint, &g_MinPoint, &matWorld ); D3DXVec3TransformCoord( &g_Box[0].MaxPoint, &g_MaxPoint, &matWorld ); if (!g_Method) { g_CheckFlag = CheckAABBIntersection( &g_Box[0].MinPoint, &g_Box[0].MaxPoint, &g_Box[1].MinPoint, &g_Box[1].MaxPoint ); } else { g_CheckFlag = CheckOBBIntersection( &g_Box[0], &g_Box[1] ); } }
HRESULT InitGeometry( ) { if (FAILED(D3DXCreateBox(g_pD3DDevice, 1.f, 1.f, 1.f, &g_pMesh, NULL))) { return E_FAIL; } D3DXVECTOR3 *vertices; g_pMesh->LockVertexBuffer( D3DLOCK_READONLY, (void**) &vertices ); D3DXComputeBoundingBox( vertices, g_pMesh->GetNumVertices(), g_pMesh->GetNumBytesPerVertex(), &g_MinPoint, &g_MaxPoint ); g_pMesh->UnlockVertexBuffer(); D3DXMATRIX matScale, matTrans, matRotateZ, matWorld; g_Box[0].BoxScaling = 1.5f; g_Box[0].CenterPos = D3DXVECTOR3( 0.f, 0.f, 0.f ); g_Box[0].BoxRotateZ = 0.f; g_Box[0].AxisDir[0] = D3DXVECTOR3( 1, 0, 0 ); g_Box[0].AxisDir[1] = D3DXVECTOR3( 0, 1, 0 ); g_Box[0].AxisDir[2] = D3DXVECTOR3( 0, 0, 1 ); for ( int i = 0; i < 3; ++i ) { g_Box[0].AxisLen[i] = 0.5f; D3DXVec3TransformNormal( &(g_Box[0].AxisDir[i]), &(g_Box[0].AxisDir[i]), &matRotateZ ); D3DXVec3Normalize( &( g_Box[0].AxisDir[i] ), &( g_Box[0].AxisDir[i] ) ); g_Box[0].AxisLen[i] = g_Box[0].AxisLen[i] * g_Box[0].BoxScaling; } D3DXMatrixTranslation( &matTrans, g_Box[0].CenterPos.x, g_Box[0].CenterPos.y, g_Box[0].CenterPos.z ); D3DXMatrixScaling( &matScale, g_Box[0].BoxScaling, g_Box[0].BoxScaling, g_Box[0].BoxScaling ); D3DXMatrixRotationZ( &matRotateZ, g_Box[0].BoxRotateZ ); matWorld = matRotateZ* matScale * matTrans; D3DXVec3TransformCoord( &g_Box[0].MinPoint, &g_MinPoint, &matWorld ); D3DXVec3TransformCoord( &g_Box[0].MaxPoint, &g_MaxPoint, &matWorld ); g_Box[1].BoxScaling = 2.f; g_Box[1].CenterPos = D3DXVECTOR3( 3.f, 3.f, 0.f ); g_Box[1].BoxRotateZ = 0.f; g_Box[1].AxisDir[0] = D3DXVECTOR3( 1, 0, 0 ); g_Box[1].AxisDir[1] = D3DXVECTOR3( 0, 1, 0 ); g_Box[1].AxisDir[2] = D3DXVECTOR3( 0, 0, 1 ); for ( int i = 0; i < 3; ++i ) { g_Box[1].AxisLen[i] = 0.5f; D3DXVec3TransformNormal( &( g_Box[0].AxisDir[i] ), &( g_Box[1].AxisDir[i] ), &matRotateZ ); D3DXVec3Normalize( &( g_Box[1].AxisDir[i] ), &( g_Box[1].AxisDir[i] ) ); g_Box[1].AxisLen[i] = g_Box[1].AxisLen[i] * g_Box[1].BoxScaling; } D3DXMatrixTranslation( &matTrans, g_Box[1].CenterPos.x, g_Box[1].CenterPos.y, g_Box[1].CenterPos.z ); D3DXMatrixScaling( &matScale, g_Box[1].BoxScaling, g_Box[1].BoxScaling, g_Box[1].BoxScaling ); D3DXMatrixRotationZ( &matRotateZ, g_Box[1].BoxRotateZ ); matWorld = matRotateZ* matScale * matTrans; D3DXVec3TransformCoord( &g_Box[1].MinPoint, &g_MinPoint, &matWorld ); D3DXVec3TransformCoord( &g_Box[1].MaxPoint, &g_MaxPoint, &matWorld ); return S_OK; }
//------------------------------------------------------------------------------ //this is a check function //------------------------------------------------------------------------------ void TriPickDemo::checkPick(LPD3DXMESH mesh, D3DXMATRIX matWorld) { HRESULT hr; D3DXMATRIX mWorldViewProjection; mWorldViewProjection = matWorld * g_Camera->viewProj(); HR(m_FX->SetTechnique("RenderScene")); // send matrix to shader HR(m_FX->SetMatrix("g_mWorldViewProjection", &mWorldViewProjection)); HR(m_FX->SetMatrix("g_mWorld", &matWorld)); UINT uPasses; V(m_FX->Begin(&uPasses, 0)); g_pDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID); V(m_FX->BeginPass(0)); //get select ray D3DXVECTOR3 originW(0.0f, 0.0f, 0.0f); D3DXVECTOR3 dirW(0.0f, 0.0f, 0.0f); if (gDInput->mouseButtonDown(0)) { getWorldPickingRay(originW, dirW, matWorld); LPD3DXMESH pMesh; mesh->CloneMeshFVF(D3DXMESH_MANAGED, D3DVERTEX::FVF, g_pDevice, &pMesh); BOOL hit = 0; DWORD faceIndex = -1; float u = 0.0f; float v = 0.0f; float dist = 0.0f; ID3DXBuffer* allhits = 0; DWORD numHits = 0; HR(D3DXIntersect(pMesh, &originW, &dirW, &hit, &faceIndex, &u, &v, &dist, &allhits, &numHits)); SAFE_RELEASE(allhits); //if hit if (hit) { IDirect3DVertexBuffer9* vb = 0; IDirect3DIndexBuffer9* ib = 0; HR(pMesh->GetVertexBuffer(&vb)); HR(pMesh->GetIndexBuffer(&ib)); HR(g_pDevice->SetIndices(ib)); HR(g_pDevice->SetFVF(D3DVERTEX::FVF)); HR(g_pDevice->SetStreamSource(0, vb, 0, sizeof(D3DVERTEX))); //render hit surface HR(g_pDevice->DrawIndexedPrimitive( D3DPT_TRIANGLELIST, 0, 0, pMesh->GetNumVertices(), faceIndex * 3, 1)) g_pDevice->SetRenderState(D3DRS_LIGHTING, FALSE); SAFE_RELEASE(vb); SAFE_RELEASE(ib); SAFE_RELEASE(pMesh); } } HR(m_FX->EndPass()); HR(m_FX->End()); }
//----------------------------------------------------------------------------- // Name: InitGeometry() // Desc: Load the mesh and build the material and texture arrays //----------------------------------------------------------------------------- HRESULT InitGeometry() { LPD3DXBUFFER pD3DXMtrlBuffer; LPDIRECT3DVERTEXBUFFER9 pMeshSourceVB; LPDIRECT3DINDEXBUFFER9 pMeshSourceIB; D3DVERTEX* pSrc; D3DVERTEX* pDst; // load the textures we are going to be using if( FAILED( D3DXCreateTextureFromFile( g_pd3dDevice, L"cartoonpallet-white-to-black.bmp", &g_pTexture ) ) ) MessageBox(NULL, L"Texture Load Problem", NULL, NULL); if( FAILED( D3DXCreateTextureFromFile( g_pd3dDevice, L"cartoonpallet-black-to-white.bmp", &g_pTexture2 ) ) ) MessageBox(NULL, L"Texture Load Problem", NULL, NULL); if( FAILED( D3DXCreateTextureFromFile( g_pd3dDevice, L"marble.bmp", &marbleTexture ) ) ) MessageBox(NULL, L"Texture Load Problem", NULL, NULL); if( FAILED( D3DXCreateTextureFromFile( g_pd3dDevice, L"background.jpg", &backgroundTexture ) ) ) MessageBox(NULL, L"Texture Load Problem", NULL, NULL); // Load the mesh from the specified file if( FAILED( D3DXLoadMeshFromX( L"skull.x", D3DXMESH_SYSTEMMEM, g_pd3dDevice, NULL, &pD3DXMtrlBuffer, NULL, &g_dwNumMaterials, &g_pMesh ) ) ) g_pd3dDevice->SetFVF(D3DFVF_D3DVERTEX ); g_dwNumVertices = g_pMesh->GetNumVertices(); g_dwNumFaces = g_pMesh->GetNumFaces(); //Clone the mesh to set the FVF LPD3DXMESH pTempSysMemMesh = NULL; if( FAILED( g_pMesh->CloneMeshFVF( D3DXMESH_SYSTEMMEM, D3DFVF_D3DVERTEX, g_pd3dDevice, &pTempSysMemMesh ) ) ) MessageBox(NULL,L"Mesh clone problem",NULL,NULL); g_pMesh->Release(); g_pMesh = pTempSysMemMesh; //Compute normals in case the meshes have them if( g_pMesh ) D3DXComputeNormals( g_pMesh, NULL ); //Meshes cloned if( FAILED(g_pd3dDevice->CreateVertexBuffer( g_dwNumVertices * sizeof(D3DVERTEX), D3DUSAGE_WRITEONLY, 0, D3DPOOL_MANAGED, &g_pMeshVB, NULL ))) MessageBox(NULL,L"Vertex buffer create problem",NULL,NULL); if( FAILED(g_pd3dDevice->CreateIndexBuffer( g_dwNumFaces * 3 * sizeof(WORD), D3DUSAGE_WRITEONLY, D3DFMT_INDEX16, D3DPOOL_MANAGED, &g_pMeshIB, NULL ))) MessageBox(NULL,L"Index buffer create problem",NULL,NULL); g_pMesh->GetVertexBuffer(&pMeshSourceVB); g_pMeshVB->Lock( 0, 0, (void**)&pDst, 0 ); pMeshSourceVB->Lock( 0, 0, (void**)&pSrc, 0 ); memcpy( pDst, pSrc, g_dwNumVertices * sizeof(D3DVERTEX) ); g_pMeshVB->Unlock(); pMeshSourceVB->Unlock(); pMeshSourceVB->Release(); g_pMesh->GetIndexBuffer(&pMeshSourceIB); g_pMeshIB->Lock( 0, 0, (void**)&pDst, 0 ); pMeshSourceIB->Lock( 0, 0, (void**)&pSrc, 0 ); memcpy( pDst, pSrc, g_dwNumFaces * 3 * sizeof(WORD)); g_pMeshIB->Unlock(); pMeshSourceIB->Unlock(); pMeshSourceIB->Release(); //// Done with the material buffer pD3DXMtrlBuffer->Release(); return S_OK; }
void CShowPoints9::SetMesh(LPD3DXMESH pNewMesh, LPD3DXSKININFO pNewSkin) { HRESULT hr = S_OK; NumPoints = 0; UnskinnedVB.resize(0); SAFE_RELEASE(SkinnedVB); SAFE_RELEASE(Skin); if(pNewMesh == NULL) return; IDirect3DDevice9* device = DXUTGetD3D9Device(); {//EFFECT V( device->CreateVertexDeclaration( Elements, &Declaration ) ); ID3DXBuffer* pErrors = NULL; V( SASCreateEffectFromResource( device, NULL, MAKEINTRESOURCE(IDR_SHOWLINES9FX), MAKEINTRESOURCE(RT_RCDATA), NULL, NULL, 0, NULL, &Effect, &pErrors)); if(pErrors) DXVGetApp().OutputA( (const char*)pErrors->GetBufferPointer() ); SAFE_RELEASE(pErrors); }//EFFECT D3DVERTEXELEMENT9 declIn[ MAX_FVF_DECL_SIZE ]; V( pNewMesh->GetDeclaration(declIn) ); int iPos= -1; int iNorm= -1; for( int i = 0 ; declIn[i].Stream != 255 && i < MAX_FVF_DECL_SIZE; i++) { if(declIn[i].Usage == D3DDECLUSAGE_POSITION && declIn[i].UsageIndex == 0) iPos = i; if(declIn[i].Usage == D3DDECLUSAGE_NORMAL && declIn[i].UsageIndex == 0) iNorm = i; } if(iPos == -1 || iNorm == -1) return; if( (( declIn[iPos].Type & (D3DDECLTYPE_FLOAT3|D3DDECLTYPE_FLOAT4)) == 0 ) || (( declIn[iNorm].Type & (D3DDECLTYPE_FLOAT3|D3DDECLTYPE_FLOAT4)) == 0 ) ) return; NumPoints = pNewMesh->GetNumVertices(); int MeshStride = pNewMesh->GetNumBytesPerVertex(); if(pNewSkin) { V( pNewSkin->Clone( &Skin ) ); V( Skin->SetDeclaration(Elements) ); } //GET VERTEX DATA BYTE* pSrcVB= NULL; V( pNewMesh->LockVertexBuffer( D3DLOCK_READONLY, (LPVOID*)&pSrcVB ) ); UnskinnedVB.resize(pNewMesh->GetNumVertices()); for( DWORD iVert = 0; iVert < pNewMesh->GetNumVertices(); iVert++) { Vertex& v0 = UnskinnedVB[iVert]; v0.Position = *(D3DXVECTOR3*) (pSrcVB+(MeshStride*iVert)+declIn[iPos].Offset); } V( pNewMesh->UnlockVertexBuffer() ); V( device->CreateVertexBuffer( NumPoints*Stride , D3DUSAGE_WRITEONLY, 0, D3DPOOL_MANAGED, &SkinnedVB, NULL) ); //Fill in with initial values so unskinned meshes do not have to do this every render. pSrcVB=(BYTE*)(void*)&UnskinnedVB.front(); BYTE* pDstVB=NULL; V( SkinnedVB->Lock(0, 0, (void**)&pDstVB, 0 ) ); { memcpy( pDstVB, pSrcVB, Stride*pNewMesh->GetNumVertices() ); } V( SkinnedVB->Unlock() ); }
void optimizePhysXMesh(int flag, IDirect3DDevice9* D3DDevice, float epsilon, std::vector<physx::PxVec3>& pxVertices, oiram::IndexBuffer& indexBuffer) { assert(D3DDevice); D3DVERTEXELEMENT9 szDecl[] = { {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, {0xFF, 0, D3DDECLTYPE_UNUSED, 0, 0, 0} }; // 创建D3D MESH LPD3DXMESH pMesh = 0; DWORD options = D3DXMESH_SYSTEMMEM | D3DXMESH_DYNAMIC; if (indexBuffer.use32BitIndices) options |= D3DXMESH_32BIT; DWORD numVertices = static_cast<DWORD>(pxVertices.size()), numFaces = numVertices / 3; HRESULT hr = D3DXCreateMesh(numFaces, numVertices, options, szDecl, D3DDevice, &pMesh); if (SUCCEEDED(hr)) { LPVOID pData = nullptr; // 填充Index Buffer if (SUCCEEDED(pMesh->LockIndexBuffer(D3DLOCK_DISCARD, &pData))) { if (indexBuffer.use32BitIndices) memcpy(pData, indexBuffer.uiIndexBuffer.data(), indexBuffer.uiIndexBuffer.size() * sizeof(physx::PxU32)); else memcpy(pData, indexBuffer.usIndexBuffer.data(), indexBuffer.usIndexBuffer.size() * sizeof(physx::PxU16)); pMesh->UnlockIndexBuffer(); } // 填充Vertex Buffer if (SUCCEEDED(pMesh->LockVertexBuffer(D3DLOCK_DISCARD, &pData))) { memcpy(pData, pxVertices.data(), pxVertices.size() * sizeof(physx::PxVec3)); pMesh->UnlockVertexBuffer(); } // 进行Mesh优化 DWORD dwFaces = pMesh->GetNumFaces(); std::vector<DWORD> szAdjacencies(dwFaces * 3); DWORD* pAdjacency = &szAdjacencies[0]; pMesh->GenerateAdjacency(epsilon, pAdjacency); // 清理mesh hr = D3DXCleanMesh(D3DXCLEAN_SIMPLIFICATION, pMesh, pAdjacency, &pMesh, pAdjacency, NULL); if (SUCCEEDED(hr)) { // 去除mesh中重复的顶点 hr = D3DXWeldVertices(pMesh, D3DXWELDEPSILONS_WELDALL, NULL, pAdjacency, pAdjacency, NULL, NULL); if (SUCCEEDED(hr)) { // 将优化后的数据写回mesh data DWORD numIndices = pMesh->GetNumFaces() * 3; indexBuffer.use32BitIndices = numIndices > 65535; if (indexBuffer.use32BitIndices) indexBuffer.uiIndexBuffer.resize(numIndices); else indexBuffer.usIndexBuffer.resize(numIndices); // 取出Index Buffer if (SUCCEEDED(pMesh->LockIndexBuffer(D3DLOCK_READONLY | D3DLOCK_DISCARD, &pData))) { if (indexBuffer.use32BitIndices) memcpy(indexBuffer.uiIndexBuffer.data(), pData, indexBuffer.uiIndexBuffer.size() * sizeof(physx::PxU32)); else memcpy(indexBuffer.usIndexBuffer.data(), pData, indexBuffer.usIndexBuffer.size() * sizeof(physx::PxU16)); pMesh->UnlockIndexBuffer(); } // 取出Vertex Buffer DWORD dwVertices = pMesh->GetNumVertices(); pxVertices.resize(dwVertices); if (SUCCEEDED(pMesh->LockVertexBuffer(D3DLOCK_READONLY | D3DLOCK_DISCARD, &pData))) { memcpy(pxVertices.data(), pData, pxVertices.size() * sizeof(physx::PxVec3)); pMesh->UnlockVertexBuffer(); } } } pMesh->Release(); } }
int main(int argc, char* argv[]) { if (argc < 3) { puts("Usage: MeshConv meshfile rdffile"); return 1; } // Initialize DirectDraw pD3D = Direct3DCreate9(D3D_SDK_VERSION); if (pD3D == NULL) { puts("Cannot init D3D"); return 1; } MeshMender mender; std::vector<MeshMender::Vertex> MendVerts; std::vector<unsigned int> MendIndices; std::vector<unsigned int> mappingNewToOld; HRESULT hr; D3DDISPLAYMODE dispMode; D3DPRESENT_PARAMETERS presentParams; pD3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &dispMode); ZeroMemory(&presentParams, sizeof(presentParams)); presentParams.Windowed = TRUE; presentParams.hDeviceWindow = GetConsoleWindow(); presentParams.SwapEffect = D3DSWAPEFFECT_COPY; presentParams.BackBufferWidth = 8; presentParams.BackBufferHeight = 8; presentParams.BackBufferFormat = dispMode.Format; hr = pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, NULL, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &presentParams, &pD3DDevice); if (FAILED(hr)) { printf("Cannot init D3D device: %08x\n", hr); pD3D->Release(); return 1; } printf("Loading mesh %s: ", argv[1]); LPD3DXBUFFER pAdjacency, pMaterials, pEffects; DWORD n; LPD3DXMESH pLoadMesh; hr = D3DXLoadMeshFromX(argv[1], D3DXMESH_SYSTEMMEM, pD3DDevice, &pAdjacency, &pMaterials, &pEffects, &n, &pLoadMesh); if (FAILED(hr)) { printf("ERROR: %08x\n", hr); goto mesherror; } pEffects->Release(); pMaterials->Release(); printf("%d faces, %d verts\n", pLoadMesh->GetNumFaces(), pLoadMesh->GetNumVertices()); LPD3DXMESH pMesh; if (pLoadMesh->GetFVF() != MESHFVF) { hr = pLoadMesh->CloneMeshFVF(D3DXMESH_SYSTEMMEM, MESHFVF, pD3DDevice, &pMesh); pLoadMesh->Release(); if (FAILED(hr)) { printf("CloneMesh error: %08x\n", hr); goto mesherror; } } else pMesh = pLoadMesh; printf("Welding verts: "); DWORD* pAdj = new DWORD[pAdjacency->GetBufferSize() / 4]; D3DXWELDEPSILONS Eps; memset(&Eps, 0, sizeof(Eps)); hr = D3DXWeldVertices(pMesh, D3DXWELDEPSILONS_WELDPARTIALMATCHES, &Eps, (DWORD*)pAdjacency->GetBufferPointer(), pAdj, NULL, NULL); if (FAILED(hr)) { printf("ERROR: %08x\n", hr); goto mesherror; } hr = pMesh->OptimizeInplace(D3DXMESHOPT_VERTEXCACHE, pAdj, (DWORD*)pAdjacency->GetBufferPointer(), NULL, NULL); if (FAILED(hr)) { printf("ERROR: %08x\n", hr); goto mesherror; } pAdjacency->Release(); delete [] pAdj; printf("%d faces, %d verts\n", pMesh->GetNumFaces(), pMesh->GetNumVertices()); printf("Mending mesh: "); DWORD NumVerts = pMesh->GetNumVertices(); DWORD NumFaces = pMesh->GetNumFaces(); MESHVERT* MeshVert; pMesh->LockVertexBuffer(0, (LPVOID*)&MeshVert); //fill up Mend vectors with your mesh's data MendVerts.reserve(NumVerts); for(DWORD i = 0; i < NumVerts; ++i) { MeshMender::Vertex v; v.pos = MeshVert[i].pos; v.s = MeshVert[i].s; v.t = MeshVert[i].t; v.normal = MeshVert[i].norm; MendVerts.push_back(v); } pMesh->UnlockVertexBuffer(); WORD* MeshIdx; pMesh->LockIndexBuffer(0, (LPVOID*)&MeshIdx); MendIndices.reserve(NumFaces * 3); for(DWORD i = 0; i < NumFaces * 3; ++i) { MendIndices.push_back(MeshIdx[i]); } pMesh->UnlockIndexBuffer(); pMesh->Release(); pMesh = 0; //pass it in to Mend mender to do it's stuff mender.Mend(MendVerts, MendIndices, mappingNewToOld, 0.9f, 0.9f, 0.9f, 1.0f, MeshMender::DONT_CALCULATE_NORMALS, MeshMender::RESPECT_SPLITS); mappingNewToOld.clear(); printf("%d faces, %d verts\n", MendIndices.size() / 3, MendVerts.size()); printf("Saving data: "); FILE* fp = fopen("meshdata.bin", "wb"); n = MendIndices.size() / 3; fwrite(&n, 4, 1, fp); n = MendVerts.size(); fwrite(&n, 4, 1, fp); fclose(fp); // Load existing file HANDLE hFile = CreateFile(argv[2], GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, 0); if (hFile == INVALID_HANDLE_VALUE) { printf("ERROR: %08x\n", GetLastError()); goto mesherror; } DWORD Size = GetFileSize(hFile, 0); char* FileData = (char*)VirtualAlloc(0, 64*1024*1024, MEM_RESERVE, PAGE_NOACCESS); VirtualAlloc(FileData, Size, MEM_COMMIT, PAGE_READWRITE); ReadFile(hFile, FileData, Size, &n, 0); FileData[n] = 0; Size = n; char *p, *q; // Find vertex data p = strstr(FileData, "VertexBuffer"); if (!p) { printf("ERROR: Invalid output file\n"); goto mesherror; } p = strchr(p, '{'); q = p+1; int depth = 1; do { if (*q == '}') --depth; else if (*q == '{') ++depth; ++q; } while (depth > 0); // move post-vertex data to temp buffer Size = (FileData + Size) - q; char* TempData = (char*)VirtualAlloc(0, Size, MEM_COMMIT, PAGE_READWRITE); memcpy(TempData, q, Size); // write vertex data strcpy(p, "{\r\n VertexFormat {D3DVSDT_FLOAT3 D3DVSDT_NORMPACKED3 D3DVSDT_FLOAT2 D3DVSDT_NORMPACKED3 D3DVSDT_NORMPACKED3}\r\n VertexData\r\n {\r\n"); p += strlen(p); for (std::vector<MeshMender::Vertex>::iterator i = MendVerts.begin(); i != MendVerts.end(); ++i) { VirtualAlloc(p, 500, MEM_COMMIT, PAGE_READWRITE); p += sprintf(p, " %12f %12f %12f %12f %12f %12f %12f %12f %12f %12f %12f %12f %12f %12f\r\n", i->pos.x, i->pos.y, i->pos.z, i->normal.x, i->normal.y, i->normal.z, i->s, i->t, i->tangent.x, i->tangent.y, i->tangent.z, i->binormal.x, i->binormal.y, i->binormal.z); } strcpy(p, " }\r\n}"); p += strlen(p); VirtualAlloc(p, Size, MEM_COMMIT, PAGE_READWRITE); memcpy(p, TempData, Size); Size += p - FileData; VirtualFree(TempData, 0, MEM_RELEASE); // Find index data p = strstr(FileData, "IndexBuffer"); if (!p) { printf("ERROR: Invalid output file\n"); goto mesherror; } p = strchr(p, '{'); q = p+1; depth = 1; do { if (*q == '}') --depth; else if (*q == '{') ++depth; ++q; } while (depth > 0); // move post-index data to temp buffer Size = (FileData + Size) - q; TempData = (char*)VirtualAlloc(0, Size, MEM_COMMIT, PAGE_READWRITE); memcpy(TempData, q, Size); // write index data strcpy(p, "{\r\n IndexData\r\n {\r\n "); p += strlen(p); n = 0; for (std::vector<unsigned>::iterator i = MendIndices.begin(); i != MendIndices.end(); ++i) { VirtualAlloc(p, 20, MEM_COMMIT, PAGE_READWRITE); p += sprintf(p, " %5hu", *i); if (n++ == 2) { p += sprintf(p, "\r\n "); n = 0; } } strcpy(p-3, "}\r\n}"); p += strlen(p); VirtualAlloc(p, Size, MEM_COMMIT, PAGE_READWRITE); memcpy(p, TempData, Size); Size += p - FileData; VirtualFree(TempData, 0, MEM_RELEASE); SetFilePointer(hFile, 0, 0, FILE_BEGIN); WriteFile(hFile, FileData, Size, &n, 0); SetEndOfFile(hFile); CloseHandle(hFile); VirtualFree(FileData, 0, MEM_RELEASE); printf("Done\n"); pD3D->Release(); pD3DDevice->Release(); return 0; mesherror: pD3D->Release(); pD3DDevice->Release(); return 1; }
HRESULT D3DXMeshCreateDiamond( LPDIRECT3DDEVICE9 pDevice, DWORD dwFVF, DWORD dwOption, UINT uSlice , FLOAT fRadius, FLOAT fUpperConeHeight, FLOAT fLowerConeHeight, LPD3DXMESH* pRet ) { //创建上下各一棱锥的钻石型 _ASSERTE(fRadius > 0 && fUpperConeHeight >= 0 && fLowerConeHeight >= 0 && uSlice >= 3); HRESULT hr = E_FAIL; LPD3DXMESH pMesh = NULL; KG_PROCESS_ERROR(NULL != pRet); KG_PROCESS_ERROR(fRadius > 0 && fUpperConeHeight >= 0 && fLowerConeHeight >= 0 && uSlice >= 3); { UINT uNumVertices = uSlice + 2; //2是上下两个点 UINT uNumFaces = uSlice * 2; _ASSERTE(IsMeshValidToBeCreated(dwOption, uNumVertices, uNumFaces * 3)); hr = D3DXCreateMeshFVF(uNumFaces, uNumVertices, dwOption, dwFVF, pDevice, &pMesh); KG_COM_CHECK_ERROR(hr); //点的分布是先填圆周的一圈,然后填上下两个点 { D3DXMeshVertexEnumer vertexEnumer; hr = D3DXMeshCreateVertexEnumer(pMesh, vertexEnumer); KG_COM_PROCESS_ERROR(hr); _ASSERTE(vertexEnumer.IsValid() && vertexEnumer.GetVertexCount() == uNumVertices); float fAnglePerVertex = 2 * D3DX_PI /static_cast<FLOAT>(uSlice); float fAngleRotate = D3DX_PI / 4.f; //把所有顶点旋转45度,这样子好些 //注意Angle是不可能超过cos和sin的值域的,不用检查了 for (UINT i = 0; i < vertexEnumer.GetVertexCount() - 2; ++i) { FLOAT fAngle = fAnglePerVertex * i; D3DXVECTOR3 vTemp; vTemp.x = fRadius * cosf(fAngle + fAngleRotate); //单位圆锥,最后再放缩,所以这里用1 vTemp.y = 0; vTemp.z = fRadius * sinf(fAngle + fAngleRotate); vertexEnumer.SetPos(i, vTemp); } _ASSERTE(vertexEnumer.GetVertexCount() > 2); //填上上下两个点 UINT uTopPoint = vertexEnumer.GetVertexCount() - 2; vertexEnumer.SetPos(uTopPoint, D3DXVECTOR3(0, fUpperConeHeight, 0)); UINT uBottomPoint = vertexEnumer.GetVertexCount() - 1; vertexEnumer.SetPos(uBottomPoint, D3DXVECTOR3(0, -fLowerConeHeight, 0)); } { D3DXMeshIndexEnumer indexEnumer; hr = D3DXMeshCreateIndexEnumer(pMesh, indexEnumer); KG_COM_PROCESS_ERROR(hr); _ASSERTE(indexEnumer.IsValid()&& indexEnumer.GetIndexCount() == 2 * uSlice * 3); UINT uVertexCountInCircle = pMesh->GetNumVertices() - 2; { UINT uUpperFaceCount = uVertexCountInCircle; DWORD uTopPointIndex = pMesh->GetNumVertices() - 2; for (UINT uIt = 0, uIndexIndex = 0; uIt < uUpperFaceCount; ++uIt, uIndexIndex += 3) { indexEnumer.SetIndex(uIndexIndex, uIt); indexEnumer.SetIndex(uIndexIndex + 1, uTopPointIndex); indexEnumer.SetIndex(uIndexIndex + 2, (uIt + 1) % uVertexCountInCircle); } } { UINT uBottomFaceCount = uVertexCountInCircle; UINT uUpperFaceCount = uVertexCountInCircle; DWORD uBottomPointIndex = pMesh->GetNumVertices() - 1; for (UINT uIt = 0, uIndexIndex = uUpperFaceCount * 3 ; uIt < uBottomFaceCount; ++uIt, uIndexIndex += 3) { indexEnumer.SetIndex(uIndexIndex, uIt); indexEnumer.SetIndex(uIndexIndex + 1, (uIt + 1) % uVertexCountInCircle); indexEnumer.SetIndex(uIndexIndex + 2, uBottomPointIndex); } } } hr = D3DXMeshZeroMeshAttributes(pMesh); } _ASSERTE(NULL != pRet); *pRet = pMesh; return S_OK; Exit0: SAFE_RELEASE(pMesh); return E_FAIL; }
HRESULT D3DXMeshCreatePlane( LPDIRECT3DDEVICE9 pDevice, DWORD dwFVF, DWORD dwOption, UINT uXSlice, UINT uZSlice , FLOAT fXLength, FLOAT fZLength, LPD3DXMESH* pRet ) { HRESULT hr = E_FAIL; LPD3DXMESH pMesh = NULL; KG_PROCESS_ERROR(D3DFVF_XYZ & dwFVF);//不是XYZ型的Mesh无法自动处理 KG_PROCESS_ERROR(NULL != pRet); KG_PROCESS_ERROR(uXSlice < 2048 && uZSlice < 2048 && _T("不能创建太大的Plane")); { DWORD dwVertexCountInXAxis = (uXSlice + 1); DWORD dwVertexCountInZAxis = (uZSlice + 1); DWORD dwVertexCount = dwVertexCountInXAxis * dwVertexCountInZAxis; DWORD dwNumFaces = uXSlice * uZSlice; _ASSERTE(IsMeshValidToBeCreated(dwOption, dwVertexCount, dwNumFaces * 3)); hr = D3DXCreateMeshFVF(dwNumFaces, dwVertexCount, dwOption, dwFVF, pDevice, &pMesh); KG_COM_PROCESS_ERROR(hr); _ASSERTE(sizeof(BYTE) == 1); ////填点,D3DXMeshVertexEnumer生命域 { D3DXMeshVertexEnumer vertexEnumer; hr = D3DXMeshCreateVertexEnumer(pMesh, vertexEnumer); KG_COM_PROCESS_ERROR(hr); FLOAT XSliceGap = fXLength / static_cast<FLOAT>(uXSlice); FLOAT ZSliceGap = fZLength / static_cast<FLOAT>(uZSlice); _ASSERTE(vertexEnumer.GetVertexCount() == dwVertexCount); for (UINT i = 0; i < dwVertexCountInXAxis; ++i) { for (UINT j = 0; j < dwVertexCountInZAxis; ++j) { FLOAT xPos = i * XSliceGap; FLOAT zPos = i * ZSliceGap; UINT uIndex = i * dwVertexCountInXAxis + j; vertexEnumer.SetPos(uIndex, D3DXVECTOR3(xPos, 0, zPos)); } } //把坐标填上 if (D3DFVF_TEX1 & dwFVF) //这个默认就是UV两个浮点的。如果用了D3DFVF_TEXCOORDn的话,位会变 { D3DXMeshVertexTexCoordEnumer texEnumer; hr = D3DXMeshCreateVertexTexCoordEnumer(vertexEnumer, texEnumer); FLOAT xUGap = 1.f / static_cast<FLOAT>(uXSlice); FLOAT zVGap = 1.f / static_cast<FLOAT>(uZSlice); if (SUCCEEDED(hr)) { _ASSERTE(2 == texEnumer.GetTexCoordSize()); for (UINT i = 0; i < dwVertexCountInXAxis; ++i) { for (UINT j = 0; j < dwVertexCountInZAxis; ++j) { UINT uIndex = i * dwVertexCountInXAxis + j; texEnumer.GetTexCoord2(uIndex) = D3DXVECTOR2(xUGap * i, zVGap * j); } } } } }////填点,D3DXMeshVertexEnumer生命域 //填Index { D3DXMeshIndexEnumer indexEnumer; hr = D3DXMeshCreateIndexEnumer(pMesh, indexEnumer); KG_COM_PROCESS_ERROR(hr); if (! indexEnumer.Is32Bit()) { KG_PROCESS_ERROR((pMesh->GetNumVertices() < SHRT_MAX) && _T("顶点数超过IndexBuffer的最大数")); } for (UINT i = 0; i < uXSlice; ++i) { for (UINT j = 0; j < uZSlice; ++j) { DWORD uLowerLeftVertexIndex = i * (uXSlice + 1) + j; DWORD uLowerRightVertexIndex = uLowerLeftVertexIndex + 1; DWORD uUpperLeftVertexIndex = uLowerLeftVertexIndex + (uXSlice + 1); DWORD uUpperRightVertexIndex = uUpperLeftVertexIndex + 1; UINT uRegionIndexBegin = (i * uXSlice + j) * 6; indexEnumer.SetIndex(uRegionIndexBegin, uLowerLeftVertexIndex); indexEnumer.SetIndex(uRegionIndexBegin + 1, uUpperLeftVertexIndex); indexEnumer.SetIndex(uRegionIndexBegin + 2, uLowerRightVertexIndex); indexEnumer.SetIndex(uRegionIndexBegin + 3, uLowerLeftVertexIndex); indexEnumer.SetIndex(uRegionIndexBegin + 4, uUpperLeftVertexIndex); indexEnumer.SetIndex(uRegionIndexBegin + 5, uUpperRightVertexIndex); indexEnumer.SetIndex(uRegionIndexBegin + 6, uLowerRightVertexIndex); } } } //填Attribute hr = D3DXMeshZeroMeshAttributes(pMesh); _ASSERTE(NULL != pRet); *pRet = pMesh; return S_OK; } Exit0: SAFE_RELEASE(pMesh); return NULL; return E_FAIL; }
//----------------------------------------------------------------------------- // Name: RestorePolygonMesh() // Desc: Initialize device dependent objects. // Params: // pd3dDevice // [in] Pointer to an IDirect3DDevice9 interface, representing the device associated with the created polygon mesh. // Length // [in] Length of each side. // Sides // [in] Number of sides for the polygon. Value must be greater than or equal to 3. // ppMesh // [out] Address of a pointer to the output shape, an ID3DXMesh interface. //----------------------------------------------------------------------------- HRESULT CD3DMesh::RestorePolygonMesh(LPDIRECT3DDEVICE9 pd3dDevice,FLOAT Length, UINT Sides, LPD3DXMESH *ppMesh) { HRESULT hr; // create the floor geometry LPD3DXMESH pMesh; hr = D3DXCreatePolygon( pd3dDevice, Length, Sides, & pMesh, NULL ); if( FAILED( hr ) ) return hr; hr = pMesh->CloneMeshFVF( D3DXMESH_SYSTEMMEM, D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_TEX1, pd3dDevice, ppMesh ); pMesh->Release(); if( FAILED( hr ) ) return hr; LPD3DXMESH pMeshFloor = *ppMesh; // rename variable DWORD dwNumVx = pMeshFloor->GetNumVertices(); struct Vx { D3DXVECTOR3 vPos; D3DXVECTOR3 vNorm; float fTex[ 2 ]; }; // Initialize its texture coordinates const int FLOOR_TILECOUNT = 2; Vx * pVx; hr = pMeshFloor->LockVertexBuffer( 0, (VOID **) & pVx ); if( FAILED( hr ) ) return hr; for( DWORD i = 0; i < dwNumVx; ++ i ) { if( fabs( pVx->vPos.x ) < 0.01 ) { if( pVx->vPos.y > 0 ) { pVx->fTex[ 0 ] = 0.0f; pVx->fTex[ 1 ] = 0.0f; } else if( pVx->vPos.y < 0.0f ) { pVx->fTex[ 0 ] = 1.0f * FLOOR_TILECOUNT; pVx->fTex[ 1 ] = 1.0f * FLOOR_TILECOUNT; } else { pVx->fTex[ 0 ] = 0.5f * FLOOR_TILECOUNT; pVx->fTex[ 1 ] = 0.5f * FLOOR_TILECOUNT; } } else if( pVx->vPos.x > 0.0f ) { pVx->fTex[ 0 ] = 1.0f * FLOOR_TILECOUNT; pVx->fTex[ 1 ] = 0.0f; } else { pVx->fTex[ 0 ] = 0.0f; pVx->fTex[ 1 ] = 1.0f * FLOOR_TILECOUNT; } ++ pVx; } pMeshFloor->UnlockVertexBuffer(); return S_OK; }
void CreateGeometry(const char* sourceFile) { cout << endl << "Reading " << sourceFile << endl; wstring wideSourceFile(sourceFile, sourceFile + strlen(sourceFile)); // Load the mesh from the specified file LPD3DXBUFFER pD3DXMtrlBuffer; LPD3DXBUFFER pD3DXEffectInstances; HRESULT hr = D3DXLoadMeshFromX( wideSourceFile.c_str(), D3DXMESH_SYSTEMMEM, g_pd3dDevice, 0, &pD3DXMtrlBuffer, &pD3DXEffectInstances, &g_dwNumMaterials, &g_pMesh); if (FAILED(hr)) { MessageBox(0, (L"Could not find " + wideSourceFile).c_str(), L"X2CTM", MB_OK); exit(1); } DWORD* adjacencyIn = new DWORD[3 * g_pMesh->GetNumFaces()]; g_pMesh->GenerateAdjacency(0.0001f, adjacencyIn); DWORD* adjacencyOut = new DWORD[3 * g_pMesh->GetNumFaces()]; LPD3DXMESH newMesh = 0; //hr = g_pMesh->Optimize(D3DXMESHOPT_ATTRSORT | D3DXMESHOPT_COMPACT, adjacencyIn, adjacencyOut, 0, 0, &newMesh); //hr = g_pMesh->OptimizeInplace(D3DXMESHOPT_ATTRSORT, adjacencyIn, adjacencyOut, 0, 0); if (FAILED(hr)) { MessageBox(0, L"Unable to build attribute table", L"Whatever", MB_OK); exit(1); } //g_pMesh = newMesh; if (WeldVertices) { DWORD beforeVertCount = g_pMesh->GetNumVertices(); DWORD beforeFaceCount = g_pMesh->GetNumFaces(); hr = D3DXWeldVertices(g_pMesh, D3DXWELDEPSILONS_WELDALL, 0, 0, 0, 0, 0); DWORD afterVertCount = g_pMesh->GetNumVertices(); DWORD afterFaceCount = g_pMesh->GetNumFaces(); } D3DXATTRIBUTERANGE table[256]; DWORD tableSize = sizeof(table) / sizeof(table[0]); g_pMesh->GetAttributeTable(&table[0], &tableSize); D3DXMATERIAL* d3dxMaterials = (D3DXMATERIAL*) pD3DXMtrlBuffer->GetBufferPointer(); D3DXEFFECTINSTANCE* d3dxEffects = (D3DXEFFECTINSTANCE*) pD3DXEffectInstances->GetBufferPointer(); g_pMeshMaterials = new D3DMATERIAL9[g_dwNumMaterials]; g_pMeshTextures = new LPDIRECT3DTEXTURE9[g_dwNumMaterials]; for (DWORD i = 0; i < g_dwNumMaterials; i++) { g_pMeshMaterials[i] = d3dxMaterials[i].MatD3D; g_pMeshMaterials[i].Ambient = g_pMeshMaterials[i].Diffuse; g_pMeshTextures[i] = 0; if (d3dxMaterials[i].pTextureFilename && lstrlenA(d3dxMaterials[i].pTextureFilename) > 0) { D3DXCreateTextureFromFileA(g_pd3dDevice, d3dxMaterials[i].pTextureFilename, &g_pMeshTextures[i]); } } /* for (DWORD attrib = 0; attrib < tableSize; ++attrib) { // I'm not so sure about material-to-attribute correlation // if (attrib < g_dwNumMaterials) // { LPSTR pTexture = d3dxMaterials[attrib].pTextureFilename; LPSTR pSlash = strchr(pTexture, '\\'); if (pSlash) { pTexture = ++pSlash; } cout << "{Texture='" << pTexture << "',"; // } string subMeshFilename = string("X_") + string("Armature.ctm"); // string(pTexture).substr(0, strlen(pTexture) - 4) + ".ctm"; subMeshFilename[0] = attrib + 'A'; ExportRangeCTM(table[attrib], g_pMesh, subMeshFilename.c_str()); cout //<< table[attrib].AttribId << ' ' << "FaceStart=" << table[attrib].FaceStart << ',' << "FaceCount=" << table[attrib].FaceCount << ',' << "VertexStart=" << table[attrib].VertexStart << ',' << "VertexCount=" << table[attrib].VertexCount << '}' << endl; } */ pD3DXMtrlBuffer->Release(); // Convert the filename from .X to .CTM while preserving the full path. char destFile[_MAX_PATH]; char drive[_MAX_DRIVE]; char dir[_MAX_DIR]; char fname[_MAX_FNAME]; char ext[_MAX_EXT]; _splitpath_s(sourceFile, drive, _MAX_DRIVE, dir, _MAX_DIR, fname, _MAX_FNAME, ext, _MAX_EXT); _makepath_s(destFile, _MAX_PATH, drive, dir, fname, "ctm"); ExportCTM(g_pMesh, destFile); cout << "Exported " << destFile << endl; /* const WORD MISSING_ATTRIBUTE = 0xffff; WORD positionsOffset = MISSING_ATTRIBUTE; WORD normalsOffset = MISSING_ATTRIBUTE; WORD texCoordsOffset = MISSING_ATTRIBUTE; D3DVERTEXELEMENT9 vertexLayout[MAX_FVF_DECL_SIZE]; D3DVERTEXELEMENT9 endMarker = D3DDECL_END(); g_pMesh->GetDeclaration(vertexLayout); D3DVERTEXELEMENT9* pVertexLayout = &vertexLayout[0]; for (int attrib = 0; attrib < MAX_FVF_DECL_SIZE; ++attrib, pVertexLayout++) { if (0 == memcmp(&vertexLayout[attrib], &endMarker, sizeof(endMarker))) { break; } if (pVertexLayout->Stream != 0) { cout << "Nonzero stream: " << pVertexLayout->Stream << endl; continue; } if (pVertexLayout->Usage == D3DDECLUSAGE_POSITION && pVertexLayout->Type == D3DDECLTYPE_FLOAT3) { cout << "Contains positions " << (int) pVertexLayout->UsageIndex << endl; positionsOffset = pVertexLayout->Offset; } else if (pVertexLayout->Usage == D3DDECLUSAGE_NORMAL && pVertexLayout->Type == D3DDECLTYPE_FLOAT3) { cout << "Contains normals " << (int) pVertexLayout->UsageIndex << endl; normalsOffset = pVertexLayout->Offset; } else if (pVertexLayout->Usage == D3DDECLUSAGE_TEXCOORD && pVertexLayout->Type == D3DDECLTYPE_FLOAT2) { cout << "Contains texture coordinates " << (int) pVertexLayout->UsageIndex << endl; texCoordsOffset = pVertexLayout->Offset; } else { cout << "Mysterious attribute" << endl; } } // Check that we support the format of the data. if (positionsOffset == MISSING_ATTRIBUTE) { exit(1); } // Obtain vertex & index counts from the D3D mesh; allocate memory for the CTM mesh. DWORD dwVertexCount = g_pMesh->GetNumVertices(); DWORD dwTriangleCount = g_pMesh->GetNumFaces(); DWORD dwIndexCount = dwTriangleCount * 3; // Lock down the verts and pluck out the positions and normals. { void* pData = 0; if (S_OK != g_pMesh->LockVertexBuffer(0, &pData)) { exit(1); } if (positionsOffset != MISSING_ATTRIBUTE) { unsigned char* pSource = ((unsigned char*) pData) + positionsOffset; DWORD dwSourceStride = g_pMesh->GetNumBytesPerVertex(); DWORD dwDestStride = sizeof(CTMfloat) * 3; for (DWORD dwVertex = 0; dwVertex < dwVertexCount; ++dwVertex) { float* pFloat = (float*) pSource; *pFloat = -*pFloat; //*pFloat = -*pFloat; pSource += dwSourceStride; } } g_pMesh->UnlockVertexBuffer(); } // Lock down the indices and convert them to unsigned 32-bit integers. { void* pData = 0; g_pMesh->LockIndexBuffer(0, &pData); DWORD dwOptions = g_pMesh->GetOptions(); DWORD dwSourceStride = (dwOptions & D3DXMESH_32BIT) ? 4 : 2; unsigned char* pSource = (unsigned char*) pData; for (DWORD dwIndex = 0; dwIndex < dwIndexCount / 3; ++dwIndex) { unsigned short* inds = (unsigned short*) pSource; std::swap(inds[0], inds[1]); pSource += dwSourceStride * 3; } g_pMesh->UnlockIndexBuffer(); } D3DXSaveMeshToX(L"new.x", g_pMesh, 0, d3dxMaterials, d3dxEffects, g_dwNumMaterials, D3DXF_FILEFORMAT_BINARY | D3DXF_FILEFORMAT_COMPRESSED); cout << "Saved." << endl; */ }
//----------------------------------------------------------------------------- // Name: InitDeviceObjects() // Desc: Initialize scene objects. //----------------------------------------------------------------------------- HRESULT CMeshRender::InitDeviceObjects() { DWORD cVerticesPerMesh; // Load mesh LPD3DXBUFFER pAdjacencyBuffer = NULL; LPDIRECT3DVERTEXBUFFER9 pVertexBuffer = NULL; LPD3DXMESH pMesh = NULL; LPD3DXPMESH pPMesh = NULL; LPD3DXMESH pTempMesh; LPD3DXBUFFER pD3DXMtrlBuffer = NULL; void* pVertices; TCHAR strMediaPath[512]; HRESULT hr; DWORD dw32BitFlag; DWORD cVerticesMin; DWORD cVerticesMax; DWORD iPMesh; D3DXWELDEPSILONS Epsilons; DWORD i; D3DXMATERIAL* d3dxMaterials; // Find the path to the mesh if( FAILED( DXUtil_FindMediaFileCb( strMediaPath, sizeof(strMediaPath), m_strMeshFilename ) ) ) return E_FAIL;//D3DAPPERR_MEDIANOTFOUND; // Load the mesh from the specified file if( FAILED( hr = D3DXLoadMeshFromX( strMediaPath, D3DXMESH_MANAGED, m_pd3dDevice, &pAdjacencyBuffer, &pD3DXMtrlBuffer, NULL, &m_dwNumMaterials, &pMesh ) ) ) { // hide error so that device changes will not cause exit, shows blank screen instead goto End; } dw32BitFlag = (pMesh->GetOptions() & D3DXMESH_32BIT); // perform simple cleansing operations on mesh if( FAILED( hr = D3DXCleanMesh( pMesh, (DWORD*)pAdjacencyBuffer->GetBufferPointer(), &pTempMesh, (DWORD*)pAdjacencyBuffer->GetBufferPointer(), NULL ) ) ) { m_dwNumMaterials = 0; goto End; } SAFE_RELEASE(pMesh); pMesh = pTempMesh; // Perform a weld to try and remove excess vertices like the model bigship1.x in the DX9.0 SDK (current model is fixed) // Weld the mesh using all epsilons of 0.0f. A small epsilon like 1e-6 works well too memset(&Epsilons, 0, sizeof(D3DXWELDEPSILONS)); if( FAILED( hr = D3DXWeldVertices( pMesh, 0, &Epsilons, (DWORD*)pAdjacencyBuffer->GetBufferPointer(), (DWORD*)pAdjacencyBuffer->GetBufferPointer(), NULL, NULL ) ) ) { m_dwNumMaterials = 0; goto End; } // verify validity of mesh for simplification if( FAILED( hr = D3DXValidMesh( pMesh, (DWORD*)pAdjacencyBuffer->GetBufferPointer(), NULL ) ) ) { m_dwNumMaterials = 0; goto End; } // Allocate a material/texture arrays d3dxMaterials = (D3DXMATERIAL*)pD3DXMtrlBuffer->GetBufferPointer(); m_mtrlMeshMaterials = new D3DMATERIAL9[m_dwNumMaterials]; m_pMeshTextures = new LPDIRECT3DTEXTURE9[m_dwNumMaterials]; // Copy the materials and load the textures for( i=0; i<m_dwNumMaterials; i++ ) { m_mtrlMeshMaterials[i] = d3dxMaterials[i].MatD3D; m_mtrlMeshMaterials[i].Ambient = m_mtrlMeshMaterials[i].Diffuse; // Find the path to the texture and create that texture DXUtil_FindMediaFileCb( strMediaPath, sizeof(strMediaPath), d3dxMaterials[i].pTextureFilename ); if( FAILED( D3DXCreateTextureFromFile( m_pd3dDevice, strMediaPath, &m_pMeshTextures[i] ) ) ) m_pMeshTextures[i] = NULL; } pD3DXMtrlBuffer->Release(); pD3DXMtrlBuffer = NULL; // Lock the vertex buffer, to generate a simple bounding sphere hr = pMesh->GetVertexBuffer( &pVertexBuffer ); if( FAILED(hr) ) goto End; hr = pVertexBuffer->Lock( 0, 0, &pVertices, D3DLOCK_NOSYSLOCK ); if( FAILED(hr) ) goto End; hr = D3DXComputeBoundingSphere( (D3DXVECTOR3*)pVertices, pMesh->GetNumVertices(), D3DXGetFVFVertexSize(pMesh->GetFVF()), &m_vObjectCenter, &m_fObjectRadius ); pVertexBuffer->Unlock(); pVertexBuffer->Release(); if( FAILED(hr) || m_dwNumMaterials == 0 ) goto End; if ( !(pMesh->GetFVF() & D3DFVF_NORMAL) ) { hr = pMesh->CloneMeshFVF( dw32BitFlag|D3DXMESH_MANAGED, pMesh->GetFVF() | D3DFVF_NORMAL, m_pd3dDevice, &pTempMesh ); if (FAILED(hr)) goto End; D3DXComputeNormals( pTempMesh, NULL ); pMesh->Release(); pMesh = pTempMesh; } hr = D3DXGeneratePMesh( pMesh, (DWORD*)pAdjacencyBuffer->GetBufferPointer(), NULL, NULL, 1, D3DXMESHSIMP_VERTEX, &pPMesh); if( FAILED(hr) ) goto End; cVerticesMin = pPMesh->GetMinVertices(); cVerticesMax = pPMesh->GetMaxVertices(); cVerticesPerMesh = (cVerticesMax - cVerticesMin) / 10; m_cPMeshes = max(1, (DWORD)ceil((cVerticesMax - cVerticesMin) / (float)cVerticesPerMesh)); m_pPMeshes = new LPD3DXPMESH[m_cPMeshes]; if (m_pPMeshes == NULL) { hr = E_OUTOFMEMORY; goto End; } memset(m_pPMeshes, 0, sizeof(LPD3DXPMESH) * m_cPMeshes); // clone full size pmesh hr = pPMesh->ClonePMeshFVF( D3DXMESH_MANAGED | D3DXMESH_VB_SHARE, pPMesh->GetFVF(), m_pd3dDevice, &m_pPMeshFull ); if (FAILED(hr)) goto End; // clone all the separate pmeshes for (iPMesh = 0; iPMesh < m_cPMeshes; iPMesh++) { hr = pPMesh->ClonePMeshFVF( D3DXMESH_MANAGED | D3DXMESH_VB_SHARE, pPMesh->GetFVF(), m_pd3dDevice, &m_pPMeshes[iPMesh] ); if (FAILED(hr)) goto End; // trim to appropriate space hr = m_pPMeshes[iPMesh]->TrimByVertices(cVerticesMin + cVerticesPerMesh * iPMesh, cVerticesMin + cVerticesPerMesh * (iPMesh+1), NULL, NULL); if (FAILED(hr)) goto End; hr = m_pPMeshes[iPMesh]->OptimizeBaseLOD(D3DXMESHOPT_VERTEXCACHE, NULL); if (FAILED(hr)) goto End; } // set current to be maximum number of vertices m_iPMeshCur = m_cPMeshes - 1; hr = m_pPMeshes[m_iPMeshCur]->SetNumVertices(cVerticesMax); if (FAILED(hr)) goto End; hr = m_pPMeshFull->SetNumVertices(cVerticesMax); if (FAILED(hr)) goto End; End: SAFE_RELEASE( pAdjacencyBuffer ); SAFE_RELEASE( pD3DXMtrlBuffer ); SAFE_RELEASE( pMesh ); SAFE_RELEASE( pPMesh ); if (FAILED(hr)) { for (iPMesh = 0; iPMesh < m_cPMeshes; iPMesh++) { SAFE_RELEASE( m_pPMeshes[iPMesh] ); } delete []m_pPMeshes; m_cPMeshes = 0; m_pPMeshes = NULL; SAFE_RELEASE( m_pPMeshFull ) } return hr; }
HRESULT InitScene() { HRESULT hr; D3DVERTEXELEMENT9 elem[] = { { 0, 0, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITIONT, 0 }, { 0, 16, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0 }, D3DDECL_END() }; SetWindowText(hwnd, TITLE); MYVALID(D3DXLoadMeshFromX("../media/meshes/box.X", D3DXMESH_MANAGED, device, NULL, NULL, NULL, NULL, &box)); MYVALID(D3DXLoadMeshFromX("../media/meshes/skullocc3.X", D3DXMESH_MANAGED, device, NULL, NULL, NULL, NULL, &skull)); MYVALID(D3DXCreateTextureFromFileA(device, "../media/textures/marble.dds", &texture1)); MYVALID(D3DXCreateTextureFromFileA(device, "../media/textures/wood2.jpg", &texture2)); MYVALID(D3DXCreateTextureFromFileA(device, "../media/textures/crate.jpg", &texture3)); MYVALID(D3DXCreateTextureFromFileA(device, "../media/textures/pcfnoise.bmp", &noise)); MYVALID(device->CreateTexture(SHADOWMAP_SIZE, SHADOWMAP_SIZE, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A32B32G32R32F, D3DPOOL_DEFAULT, &shadowmap, NULL)); MYVALID(device->CreateTexture(SHADOWMAP_SIZE, SHADOWMAP_SIZE, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A32B32G32R32F, D3DPOOL_DEFAULT, &blurRGBA32F, NULL)); MYVALID(device->CreateTexture(SHADOWMAP_SIZE, SHADOWMAP_SIZE, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &sincoeffs, NULL)); MYVALID(device->CreateTexture(SHADOWMAP_SIZE, SHADOWMAP_SIZE, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &coscoeffs, NULL)); MYVALID(device->CreateTexture(SHADOWMAP_SIZE, SHADOWMAP_SIZE, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &blurARGB8, NULL)); MYVALID(device->CreateTexture(800, 512, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &text, NULL)); MYVALID(device->CreateVertexDeclaration(elem, &vertexdecl)); MYVALID(DXCreateEffect("../media/shaders/exponentialshadow.fx", device, &exponential)); MYVALID(DXCreateEffect("../media/shaders/convolutionshadow.fx", device, &convolution)); MYVALID(DXCreateEffect("../media/shaders/varianceshadow.fx", device, &variance)); MYVALID(DXCreateEffect("../media/shaders/expvarianceshadow.fx", device, &expvariance)); MYVALID(DXCreateEffect("../media/shaders/boxblur5x5.fx", device, &boxblur5x5)); MYVALID(DXCreateEffect("../media/shaders/pcfshadow5x5.fx", device, &pcf5x5)); MYVALID(DXCreateEffect("../media/shaders/pcss.fx", device, &pcss)); MYVALID(DXCreateEffect("../media/shaders/irregularpcf.fx", device, &pcfirreg)); DXRenderText( "Use the mouse to rotate the camera and the light\n\n0 - Unfiltered\n1 - PCF (5x5)\n2 - Irregular PCF\n3 - Variance\n" "4 - Convolution\n5 - Exponential\n6 - Exponential variance\n7 - PCSS", text, 800, 512); cameraangle = D3DXVECTOR2(0.78f, 0.78f); lightangle = D3DXVECTOR2(3.2f, 0.85f); DXAABox boxbb; DXAABox skullbb; DXAABox tmpbb; D3DXMATRIX tmp1, tmp2, tmp3; D3DXVECTOR3* vdata; box->LockVertexBuffer(D3DLOCK_READONLY, (void**)&vdata); D3DXComputeBoundingBox(vdata, box->GetNumVertices(), box->GetNumBytesPerVertex(), &boxbb.Min, &boxbb.Max); box->UnlockVertexBuffer(); skull->LockVertexBuffer(D3DLOCK_READONLY, (void**)&vdata); D3DXComputeBoundingBox(vdata, skull->GetNumVertices(), skull->GetNumBytesPerVertex(), &skullbb.Min, &skullbb.Max); skull->UnlockVertexBuffer(); for( int i = 0; i < numobjects; ++i ) { SceneObject& obj = objects[i]; D3DXMatrixScaling(&tmp1, obj.scale.x, obj.scale.y, obj.scale.z); D3DXMatrixRotationYawPitchRoll(&tmp2, obj.angles.x, obj.angles.y, obj.angles.z); D3DXMatrixTranslation(&tmp3, obj.position.x, obj.position.y, obj.position.z); D3DXMatrixMultiply(&obj.world, &tmp1, &tmp2); D3DXMatrixMultiply(&obj.world, &obj.world, &tmp3); if( obj.type == SKULL ) tmpbb = skullbb; else tmpbb = boxbb; tmpbb.TransformAxisAligned(obj.world); scenebb.Add(tmpbb.Min); scenebb.Add(tmpbb.Max); } return S_OK; }
HRESULT KG3DMesh::CreateBspFile() { HRESULT hrResult = E_FAIL; HRESULT hrRetCode = E_FAIL; int nRetCode = false; TCHAR szBSPPathName[MAX_PATH]; void *pvVerticesBuffer = NULL; WORD* pIndexBuffer = NULL; D3DXVECTOR3 *pPos = NULL; DWORD *pdwFaceIndex = NULL; DWORD dwStride = 0; DWORD i = 0; DWORD dwNumFaces = 0; DWORD dwNumVertices = 0; DWORD dwStartTime = timeGetTime(); LPD3DXMESH piMesh = m_ppMeshes[SMBT_NORMAL]; KG3DBsp *pBSP = NULL; KGLOG_PROCESS_ERROR(piMesh); dwStride = piMesh->GetNumBytesPerVertex(); dwNumVertices = piMesh->GetNumVertices(); dwNumFaces = piMesh->GetNumFaces(); KG_PROCESS_SUCCESS(dwNumFaces < 256); pPos = new D3DXVECTOR3[dwNumVertices]; KG_ASSERT_EXIT(pPos); pdwFaceIndex = new DWORD[dwNumFaces * 3]; KG_ASSERT_EXIT(pdwFaceIndex); hrRetCode = piMesh->LockVertexBuffer(D3DLOCK_READONLY, (void **)&pvVerticesBuffer); KGLOG_COM_PROCESS_ERROR(hrRetCode); hrRetCode = piMesh->LockIndexBuffer(D3DLOCK_READONLY, (void **)&pIndexBuffer); KGLOG_COM_PROCESS_ERROR(hrRetCode); for (i = 0; i < dwNumVertices; ++i) { pPos[i] = *(D3DXVECTOR3 *)(((BYTE *)pvVerticesBuffer) + dwStride * i); } for (i = 0; i < dwNumFaces * 3; ++i) { pdwFaceIndex[i] = pIndexBuffer[i]; } // -------------------------- create BSP -------------------------- hrRetCode = ChangePathExtName(m_scName.c_str(), "bsp", sizeof(szBSPPathName), szBSPPathName); KGLOG_COM_PROCESS_ERROR(hrRetCode); pBSP = new KG3DBsp; KGLOG_PROCESS_ERROR(pBSP); hrRetCode = pBSP->CreateFromMesh(dwNumVertices, dwNumFaces, pPos, pdwFaceIndex); KGLOG_COM_PROCESS_ERROR(hrRetCode); hrRetCode = pBSP->SaveToFile(szBSPPathName); KGLOG_COM_PROCESS_ERROR(hrRetCode); DWORD dwCost = timeGetTime() - dwStartTime; if(dwCost > 500) { KGLogPrintf( KGLOG_WARNING, "BSP %d %d Face %s", dwCost, dwNumFaces, szBSPPathName ); } KG_DELETE(m_lpBsp); // recreate m_lpBsp = pBSP; pBSP = NULL; Exit1: hrResult = S_OK; Exit0: KG_DELETE(pBSP); if (pIndexBuffer) { piMesh->UnlockIndexBuffer(); pIndexBuffer = NULL; } if (pvVerticesBuffer) { piMesh->UnlockVertexBuffer(); pvVerticesBuffer = NULL; } KG_DELETE_ARRAY(pdwFaceIndex); KG_DELETE_ARRAY(pPos); if(FAILED(hrResult)) { KGLogPrintf(KGLOG_ERR, "%s 创建失败", szBSPPathName); } return hrResult; }
/** * * PRECONDITION: parameter EFacePosition _eSide must be either FACE_TOP, or FACE_BOTTOM. * * @author Rebeccah Cox * @param EFacePosition _eSide - the side the flag is on, either top or bottom. * @param int32 _iX - the position along the X axis. * @param int32 _iY - the position along the Z axis (looks like the y axis when * looking at the flag plate). * @param ETeam _eTeam - team the flagplate belongs to. * @param uint32 _uiTextureID * @param uint32 _uiModelID * @return bool - returns true if the initialisation was successful. */ bool CFlagPlate::Initialise(EFacePosition _eSide, int32 _iX, int32 _iY, ETeam _eTeam, uint32 _uiModelID, uint32 _uiTextureID) { // Set the position and side member variables in CTile. m_eFace = _eSide; m_iX = _iX; m_iY = _iY; m_vec3Position = g_atUpRightDirectionVecs[_eSide].vec3Up * 22.5f; m_vec3Position += g_atUpRightDirectionVecs[_eSide].vec3Right * ((_iX * 3.0f) - 21.0f); m_vec3Position -= g_atUpRightDirectionVecs[_eSide].vec3Direction * ((_iY * 3.0f) - 21.0f); // Set the world matrix using the vectors. m_matWorld._11 = g_atUpRightDirectionVecs[_eSide].vec3Right.x; m_matWorld._21 = g_atUpRightDirectionVecs[_eSide].vec3Up.x; m_matWorld._31 = g_atUpRightDirectionVecs[_eSide].vec3Direction.x; m_matWorld._12 = g_atUpRightDirectionVecs[_eSide].vec3Right.y; m_matWorld._22 = g_atUpRightDirectionVecs[_eSide].vec3Up.y; m_matWorld._32 = g_atUpRightDirectionVecs[_eSide].vec3Direction.y; m_matWorld._13 = g_atUpRightDirectionVecs[_eSide].vec3Right.z; m_matWorld._23 = g_atUpRightDirectionVecs[_eSide].vec3Up.z; m_matWorld._33 = g_atUpRightDirectionVecs[_eSide].vec3Direction.z; m_matWorld._41 = m_vec3Position.x; m_matWorld._42 = m_vec3Position.y; m_matWorld._43 = m_vec3Position.z; m_bTraversable = true; m_iModelID = _uiModelID; m_iTextureID = _uiTextureID; /*// Set the model ID if(BAD_ID == _uiModelID) { m_iModelID = CModelManager::GetInstance().CreateModel("../../models/tile_flagplate.x"); } // Set the texture ID if(BAD_ID == _uiTextureID) { if(TEAM_GREEN == _eTeam) { m_iTextureID = CTextureManager::GetInstance().CreateTexture("../../textures/tile_flagTile_green.png"); } else { m_iTextureID = CTextureManager::GetInstance().CreateTexture("../../textures/tile_flagTile_purple.png"); } }*/ D3DXVECTOR3* pFirstVertex = 0; LPD3DXMESH pMesh = CModelManager::GetInstance().GetModel(m_iModelID)->GetModel(); pMesh->LockVertexBuffer(0, (void**)&pFirstVertex); D3DXComputeBoundingBox(pFirstVertex, pMesh->GetNumVertices(), pMesh->GetNumBytesPerVertex(), &m_tOBB.m_vec3Min, &m_tOBB.m_vec3Max); pMesh->UnlockVertexBuffer(); CEntity::Initialise(); return (true); }
HRESULT D3DXMeshCreateByVerticesPos( DWORD dwFVF, D3DVECTOR* pPosArray, DWORD dwVertexCount , DWORD* pIndexArray, DWORD dwNumIndexCount , LPDIRECT3DDEVICE9 pDevice, DWORD dwOption, LPD3DXMESH* pRet ) { HRESULT hr = E_FAIL; LPD3DXMESH pMesh = NULL; KG_PROCESS_ERROR((dwFVF & D3DFVF_XYZ)); KG_PROCESS_ERROR(NULL != pPosArray && NULL != pIndexArray && NULL != pDevice && NULL != pRet); _ASSERTE(IsMeshValidToBeCreated(dwOption, dwVertexCount, dwNumIndexCount)); { DWORD dwNumFaces = dwNumIndexCount / 3; hr = D3DXCreateMeshFVF(dwNumFaces, dwVertexCount, dwOption, dwFVF, pDevice, &pMesh); KG_COM_PROCESS_ERROR(hr); #if defined(DEBUG) | defined(_DEBUG) ULONG uRefSave = KGGetRef(pMesh); #endif { BOOL bValidity = pMesh->GetNumVertices() == dwVertexCount && pMesh->GetNumFaces() == dwNumFaces; KG_PROCESS_ERROR(bValidity); } _ASSERTE(sizeof(BYTE) == 1); { D3DXMeshVertexEnumer vertexEnumer; hr = D3DXMeshCreateVertexEnumer(pMesh, vertexEnumer); KG_COM_PROCESS_ERROR(hr); _ASSERTE(vertexEnumer.IsValid() && vertexEnumer.GetVertexCount() == dwVertexCount); for (UINT i = 0; i < vertexEnumer.GetVertexCount(); ++i) { vertexEnumer.SetPos(i, pPosArray[i]); } } { D3DXMeshIndexEnumer indexEnumer; hr = D3DXMeshCreateIndexEnumer(pMesh, indexEnumer); KG_COM_PROCESS_ERROR(hr); _ASSERTE(indexEnumer.IsValid() && indexEnumer.GetIndexCount() <= dwNumIndexCount); for (UINT i = 0; i < indexEnumer.GetIndexCount(); ++i) { indexEnumer.SetIndex(i, pIndexArray[i]); } } D3DXMeshZeroMeshAttributes(pMesh); _ASSERTE(uRefSave == KGGetRef(pMesh)); } *pRet = pMesh; return S_OK; Exit0: SAFE_RELEASE(pMesh); return E_FAIL; }
HRESULT CMyD3DApplication::LoadMeshData ( LPD3DXMESH *ppMesh, LPD3DXBUFFER *ppAdjacencyBuffer ) { LPDIRECT3DVERTEXBUFFER8 pMeshVB = NULL; LPD3DXBUFFER pD3DXMtrlBuffer = NULL; BYTE* pVertices; TCHAR strMesh[512]; HRESULT hr = S_OK; BOOL bNormalsInFile; LPD3DXMESH pMeshSysMem = NULL; LPD3DXMESH pMeshTemp; DWORD *rgdwAdjacencyTemp = NULL; DWORD i; D3DXMATERIAL* d3dxMaterials; DWORD dw32Bit; // Get a path to the media file DXUtil_FindMediaFile( strMesh, m_strMeshFilename ); // Load the mesh from the specified file hr = D3DXLoadMeshFromX( strMesh, D3DXMESH_SYSTEMMEM, m_pd3dDevice, ppAdjacencyBuffer, &pD3DXMtrlBuffer, &m_dwNumMaterials, &pMeshSysMem ); if( FAILED(hr) ) goto End; // remember if the mesh is 32 or 16 bit, to be added in on the clones dw32Bit = pMeshSysMem->GetOptions() & D3DXMESH_32BIT; // Get the array of materials out of the returned buffer, and allocate a texture array d3dxMaterials = (D3DXMATERIAL*)pD3DXMtrlBuffer->GetBufferPointer(); m_pMeshMaterials = new D3DMATERIAL8[m_dwNumMaterials]; m_pMeshTextures = new LPDIRECT3DTEXTURE8[m_dwNumMaterials]; for( i=0; i<m_dwNumMaterials; i++ ) { m_pMeshMaterials[i] = d3dxMaterials[i].MatD3D; m_pMeshMaterials[i].Ambient = m_pMeshMaterials[i].Diffuse; m_pMeshTextures[i] = NULL; // Get a path to the texture TCHAR strPath[512]; if (d3dxMaterials[i].pTextureFilename != NULL) { DXUtil_FindMediaFile( strPath, d3dxMaterials[i].pTextureFilename ); // Load the texture D3DXCreateTextureFromFile( m_pd3dDevice, strPath, &m_pMeshTextures[i] ); } } // Done with the material buffer SAFE_RELEASE( pD3DXMtrlBuffer ); // Lock the vertex buffer, to generate a simple bounding sphere hr = pMeshSysMem->GetVertexBuffer( &pMeshVB ); if( SUCCEEDED(hr) ) { hr = pMeshVB->Lock( 0, 0, &pVertices, D3DLOCK_NOSYSLOCK ); if( SUCCEEDED(hr) ) { hr = D3DXComputeBoundingSphere( pVertices, pMeshSysMem->GetNumVertices(), pMeshSysMem->GetFVF(), &m_vObjectCenter, &m_fObjectRadius ); pMeshVB->Unlock(); } pMeshVB->Release(); } if( FAILED(hr) ) goto End; // remember if there were normals in the file, before possible clone operation bNormalsInFile = pMeshSysMem->GetFVF() & D3DFVF_NORMAL; // if using 32byte vertices, check fvf if (m_bForce32ByteFVF) { // force 32 byte vertices if (pMeshSysMem->GetFVF() != (D3DFVF_XYZ|D3DFVF_NORMAL|D3DFVF_TEX1)) { hr = pMeshSysMem->CloneMeshFVF( pMeshSysMem->GetOptions(), D3DFVF_XYZ|D3DFVF_NORMAL|D3DFVF_TEX1, m_pd3dDevice, &pMeshTemp ); if( FAILED(hr) ) goto End; pMeshSysMem->Release(); pMeshSysMem = pMeshTemp; } } // otherwise, just make sure that there is a normal mesh else if ( !(pMeshSysMem->GetFVF() & D3DFVF_NORMAL) ) { hr = pMeshSysMem->CloneMeshFVF( pMeshSysMem->GetOptions(), pMeshSysMem->GetFVF() | D3DFVF_NORMAL, m_pd3dDevice, &pMeshTemp ); if (FAILED(hr)) return hr; pMeshSysMem->Release(); pMeshSysMem = pMeshTemp; } // Compute normals for the mesh, if not present if (!bNormalsInFile) { D3DXComputeNormals( pMeshSysMem, NULL ); } *ppMesh = pMeshSysMem; pMeshSysMem = NULL; End: SAFE_RELEASE( pMeshSysMem ); return hr; }