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; } }
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; }
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; }
//------------------------------------------------------ // DirectXメッシュの作成 //------------------------------------------------------ LPD3DXMESH iex3DObj::CreateMesh( LPIEMFILE lpIem ) { LPD3DXMESH lpMesh; u8 *pVertex, *pFace; u32 *pData; if( lpIem->version < 4 ) { u32 Declaration = D3DFVF_MESHVERTEX; // メッシュ作成 D3DXCreateMeshFVF( lpIem->NumFace, lpIem->NumVertex, D3DXMESH_MANAGED, Declaration, tdnSystem::GetDevice(), &lpMesh ); // 頂点設定 lpMesh->LockVertexBuffer( 0, (void**)&pVertex ); CopyMemory( pVertex, lpIem->lpVertex, sizeof(MESHVERTEX)*lpIem->NumVertex ); } else { u32 Declaration = D3DFVF_MESHVERTEX2; // メッシュ作成 D3DXCreateMeshFVF( lpIem->NumFace, lpIem->NumVertex, D3DXMESH_MANAGED, Declaration, tdnSystem::GetDevice(), &lpMesh ); // 頂点設定 lpMesh->LockVertexBuffer( 0, (void**)&pVertex ); CopyMemory( pVertex, lpIem->lpVertex, sizeof(MESHVERTEX2)*lpIem->NumVertex ); } lpMesh->UnlockVertexBuffer(); // 面設定 lpMesh->LockIndexBuffer( 0, (void**)&pFace ); CopyMemory( pFace, lpIem->lpFace, sizeof(u16)*lpIem->NumFace*3 ); lpMesh->UnlockIndexBuffer(); // 属性設定 lpMesh->LockAttributeBuffer( 0, &pData ); CopyMemory( pData, lpIem->lpAtr, sizeof(u32)*lpIem->NumFace ); lpMesh->UnlockAttributeBuffer(); return lpMesh; }
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; }
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(); } }
HRESULT AiPathReader::CreateMesh(LPDIRECT3DDEVICE9 pD3DDevice, LPD3DXMESH &pMesh) { //Todo: ID3DXMesh::SetAttributeTable (set materials how they are defined in the face struct) DWORD dwFVF = (D3DFVF_XYZ | D3DFVF_NORMAL); struct D3DVERTEX { D3DXVECTOR3 p; D3DXVECTOR3 n; }; HRESULT r = D3DXCreateMeshFVF(3 * nodes.size(), 3 * nodes.size(), D3DXMESH_MANAGED, dwFVF, pD3DDevice, &pMesh); if(FAILED(r)) { return r; } D3DVERTEX *vertexBuffer; WORD *indexBuffer = nullptr; unsigned long *pAdjacency = new unsigned long[nodes.size() * 3]; pMesh->LockIndexBuffer(0, reinterpret_cast<void **>(&indexBuffer)); pMesh->LockVertexBuffer(0, reinterpret_cast<void **>(&vertexBuffer)); for(int i = 0; i < nodes.size(); i++) { auto face = nodes[i]; for(int j = 0; j < 3; j++) { D3DVERTEX &vert = vertexBuffer[3 * i + j]; vert.p.x = face.triangle[j].x; vert.p.y = face.triangle[j].y; vert.p.z = face.triangle[j].z; indexBuffer[3 * i + j] = 3 * i + j; pAdjacency[3 * i + j] = (face.adjacency[j] == 0xffff) ? 0xffffffffUL : face.adjacency[j]; } } //D3DXWeldVertices(pMesh, D3DXWELDEPSILONS_WELDALL, nullptr, pAdjacency, nullptr, nullptr, nullptr); //pMesh->OptimizeInplace(D3DXMESHOPT_COMPACT | D3DXMESHOPT_IGNOREVERTS | D3DXMESHOPT_STRIPREORDER, newAdjacency, pAdjacency, nullptr, nullptr); delete[] pAdjacency; HRESULT hr = D3DXComputeNormals(pMesh, nullptr); D3DXMATERIAL *m_pMaterials = nullptr; DWORD m_dwNumMaterials = 0; hr = D3DXSaveMeshToX("NavMesh.x", pMesh, nullptr, m_pMaterials, nullptr, m_dwNumMaterials, D3DXF_FILEFORMAT_BINARY); pMesh->UnlockVertexBuffer(); pMesh->UnlockIndexBuffer(); return S_OK; }
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 Dx_Graphics3D::DrawMeshContainer(LPD3DXMESHCONTAINER pMeshContainer, LPD3DXFRAME pFrame) { DxMeshContainer *mesh_container = (DxMeshContainer*)pMeshContainer; DxFrame *frame = (DxFrame*)pFrame; // D3DMATERIAL9 mat; LPDIRECT3DTEXTURE9 pTex=NULL; //D3DXMESHDATA内のメッシュデータを抽出 LPD3DXMESH lpMesh = mesh_container->MeshData.pMesh; //スキニング情報がない場合 if(pMeshContainer->pSkinInfo==NULL) { //デバイスにフレームのワールド行列を設置 this->device->SetTransform( D3DTS_WORLD, &frame->CombinedTransformationMatrix); //メッシュ描画 for (DWORD i=0;i<mesh_container->NumMaterials;i++) { //マテリアル情報の取得 mat = mesh_container->pMaterials[i].MatD3D; //テクスチャ情報の取得 pTex = mesh_container->ppTextures[i]; //メッシュサブセットを描画 this->DrawSubset(lpMesh,i,&mat,pTex); } } //スキニング情報がある場合 else { D3DXMATRIX matId; PBYTE pVerticesSrc; PBYTE pVerticesDest; //ボーン数を取得 DWORD NumBones = pMeshContainer->pSkinInfo->GetNumBones(); for( DWORD i = 0; i < NumBones; i++ ){ D3DXMatrixMultiply( &mesh_container->pBoneMatrices[i], &mesh_container->pBoneOffsetMatrices[i], mesh_container->ppBoneMatrixPtrs[i] ); } //ワールド行列をクリア D3DXMatrixIdentity(&matId); this->device->SetTransform(D3DTS_WORLD, &matId); //頂点バッファをロック mesh_container->lpMesh->LockVertexBuffer( D3DLOCK_READONLY, (LPVOID*)&pVerticesSrc); lpMesh->LockVertexBuffer( 0, (LPVOID*)&pVerticesDest); //スキンメッシュ作成 mesh_container->pSkinInfo->UpdateSkinnedMesh( mesh_container->pBoneMatrices, NULL, pVerticesSrc, pVerticesDest); //頂点バッファのロックを解除 mesh_container->lpMesh->UnlockVertexBuffer(); lpMesh->UnlockVertexBuffer(); //メッシュ描画 for(UINT i = 0;i<mesh_container->NumAttributeGroups;i++) { //メッシュサブセットの属性IDを取得 unsigned AttribId = mesh_container->pAttributeTable[i].AttribId; //マテリアル情報を取得 mat = mesh_container->pMaterials[AttribId].MatD3D; //テクスチャ情報を取得 pTex = mesh_container->ppTextures[AttribId]; //メッシュのサブセットを描画 this->DrawSubset(lpMesh,AttribId,&mat,pTex); } } }
/** * * 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); }
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; }
void ObjParser::Load(LPCSTR Filename, LPDIRECT3DDEVICE9 pDevice) { FILE* fileHandle = fopen(Filename, "r+"); if( fileHandle == NULL ) return; char line[256]; D3DXVECTOR3 vec; while( !feof(fileHandle) )//Foreach Line { fgets(line, 256, fileHandle); #pragma region Line Read switch(line[0]) { case 'm': { LPCSTR name = new CHAR[256]; sscanf_s(line, "mtllib %s", name, 255); ParseMaterial(name); } break; case 'v'://Vertex Item { switch(line[1]) { case ' '://Vertex { sscanf_s(line, "v %f %f %f", &vec.x, &vec.y, &vec.z ); Vertexs.push_back(vec); mVertexsHT.push_back(NULL);//expand HashTable } break; case 't'://Texture Coordinates { D3DXVECTOR3 tex; sscanf_s(line, "vt %f %f %f", &vec.x, &vec.y, &vec.z); Textures.push_back(vec); } break; case 'n'://Normal { D3DXVECTOR3 nor; sscanf_s(line, "vn %f %f %f", &vec.x, &vec.y, &vec.z ); Normals.push_back(vec); } break; default:// Not supposed to happen assert( false ); } } break; case 'f'://Face Item { DWORD quadP[4];//Position Index quad DWORD quadT[4];//Texture Index quad DWORD quadN[4];//Normal Index quad memset(quadP, -1, sizeof(DWORD)*4); memset(quadT, -1, sizeof(DWORD)*4); memset(quadN, -1, sizeof(DWORD)*4); int size = strlen(line); int barCount = std::count(line, line+size, '/'); int readed = 0; //By default .obj file puts faces with CW winding switch( barCount ) { case 0:// tri/quad pos { if( m_Winding == VertexWinding::CCW ) readed = sscanf_s(line, "f %d %d %d %d", &quadP[3], &quadP[2], &quadP[1], &quadP[0] ); else readed = sscanf_s(line, "f %d %d %d %d", &quadP[0], &quadP[1], &quadP[2], &quadP[3] ); assert( readed == 3 || readed == 4 ); } break; case 3:// tri pos/tex { if( m_Winding == VertexWinding::CCW ) readed = sscanf_s(line, "f %d/%d %d/%d %d/%d", &quadP[2], &quadT[2], &quadP[1], &quadT[1], &quadP[0], &quadT[0] ); else readed = sscanf_s(line, "f %d/%d %d/%d %d/%d", &quadP[0], quadT[0], &quadP[1], quadT[1], &quadP[2], quadT[2] ); assert( readed == 6 ); readed /= 2; } break; case 4:// quad pos/tex { if( m_Winding == VertexWinding::CCW ) readed = sscanf_s(line, "f %d/%d %d/%d %d/%d %d/%d", &quadP[3], &quadT[3], &quadP[2], &quadT[2], &quadP[1], &quadT[1], &quadP[0], &quadT[0] ); else readed = sscanf_s(line, "f %d/%d %d/%d %d/%d %d/%d", &quadP[0], &quadT[0], &quadP[1], &quadT[1], &quadP[2], &quadT[2], &quadP[3], &quadT[3] ); assert( readed == 8 ); readed /= 2; } break; case 6:// tri pos/tex/nor { if( m_Winding == VertexWinding::CCW ) readed = sscanf_s(line, "f %d/%d/%d %d/%d/%d %d/%d/%d", &quadP[2], &quadT[2], &quadN[2], &quadP[1], &quadT[1], &quadN[1], &quadP[0], &quadT[0], &quadN[0] ); else readed = sscanf_s(line, "f %d/%d/%d %d/%d/%d %d/%d/%d", &quadP[0], &quadT[0], &quadN[0], &quadP[1], &quadT[1], &quadN[1], &quadP[2], &quadT[2], &quadN[2] ); assert( readed == 9 ); readed /= 3; } break; case 8:// quad pos/tex/nor { if( m_Winding == VertexWinding::CCW ) readed = sscanf_s(line, "f %d/%d/%d %d/%d/%d %d/%d/%d %d/%d/%d", &quadP[3], &quadT[3], &quadN[3], &quadP[2], &quadT[2], &quadN[2], &quadP[1], &quadT[1], &quadN[1], &quadP[0], &quadT[0], &quadN[0] ); else readed = sscanf_s(line, "f %d/%d/%d %d/%d/%d %d/%d/%d %d/%d/%d", &quadP[0], &quadT[0], &quadN[0], &quadP[1], &quadT[1], &quadN[1], &quadP[2], &quadT[2], &quadN[2], &quadP[3], &quadT[3], &quadN[3] ); assert( readed == 12 ); readed /= 3; } break; default:// Not supposed to happen assert( false ); } //The indexs are in 1 Base, we transform to 0 Base for( int i=0; i < 4 ; ++i ) { quadP[i]--; quadT[i]--; quadN[i]--; } for(int j=0; j < 3 ; ++j) { VertexTextureNormal NewVertex; NewVertex.SetPosition( Vertexs[quadP[j]] ); if( quadT[j] != (DWORD(-1)-1) ) NewVertex.SetTexture ( Textures[quadT[j]].x, Textures[quadT[j]].y ); if( quadN[j] != (DWORD(-1)-1) ) NewVertex.SetNormal ( Normals[quadN[j]] ); DWORD index = AddVertex(quadP[j], NewVertex); mIndexs.push_back(index); } if( readed == 4 )// quad readed { quadP[1] = quadP[2]; quadT[1] = quadT[2]; quadN[1] = quadN[2]; quadP[2] = quadP[3]; quadT[2] = quadT[3]; quadN[1] = quadN[2]; for(int j=0; j < 3 ; ++j) { VertexTextureNormal NewVertex; NewVertex.SetPosition( Vertexs[quadP[j]] ); if( quadT[j] != (DWORD(-1)-1) ) NewVertex.SetTexture ( Textures[quadT[j]].x, Textures[quadT[j]].y ); if( quadN[j] != (DWORD(-1)-1) ) NewVertex.SetNormal ( Normals[quadN[j]] ); DWORD index = AddVertex(quadP[j], NewVertex); mIndexs.push_back(index); } } } break; } #pragma endregion } fclose(fileHandle); DWORD FVF = NULL; D3DVERTEXELEMENT9* pMeshVDeclaration = NULL; int code = 0; IdentifieLoadedFormat(FVF, pMeshVDeclaration, code); if( code == 0 ) return; //Setup Mesh with VertexDeclaration corresponding to the loaded data LPD3DXMESH pMesh = NULL; HRESULT hr = NULL; int FacesCount = mIndexs.size()/3; switch( m_VertexMetaFormat ) { case VertexMetaFormat::VertexDeclaration: { if( FacesCount > 65535 )// if huge mesh, 32 bits face index hr = D3DXCreateMesh(FacesCount, mVertexs.size(), D3DXMESH_32BIT | D3DXMESH_VB_SYSTEMMEM | D3DXMESH_IB_SYSTEMMEM | D3DXMESH_SYSTEMMEM , pMeshVDeclaration, pDevice, &pMesh); else hr = D3DXCreateMesh(FacesCount, mVertexs.size(), D3DXMESH_VB_SYSTEMMEM | D3DXMESH_IB_SYSTEMMEM | D3DXMESH_SYSTEMMEM , pMeshVDeclaration, pDevice, &pMesh); } break; case VertexMetaFormat::FVF: { if( FacesCount > 65535 )// if huge mesh, 32 bits face index hr = D3DXCreateMeshFVF(FacesCount, Vertexs.size(), D3DXMESH_32BIT | D3DXMESH_VB_SYSTEMMEM | D3DXMESH_IB_SYSTEMMEM | D3DXMESH_SYSTEMMEM , FVF, pDevice, &pMesh); else hr = D3DXCreateMeshFVF(FacesCount, Vertexs.size(), D3DXMESH_VB_SYSTEMMEM | D3DXMESH_IB_SYSTEMMEM | D3DXMESH_SYSTEMMEM , FVF, pDevice, &pMesh); } break; default: assert( false ); } assert( !FAILED(hr) ); //Puts vertex data inside loadedData in the smallest format needed //(not nesesarily VertexTextureNormal) void* loadedData = NULL; void* loadedIndex = NULL; size_t size = 0; //Pass to our vertex format PutLoadedDataInVertexDeclarationFormat(loadedData,loadedIndex,size,code, FacesCount); //Free Auxiliary Arrays Vertexs.clear(); Textures.clear(); Normals.clear(); mVertexsHT.clear(); void* data = NULL; //Loads the Vertex Buffer if( FAILED(pMesh->LockVertexBuffer(NULL, &data)) ) return; memcpy(data, loadedData, size*mVertexs.size()); pMesh->UnlockVertexBuffer(); //Loads the Index Buffer if( FAILED(pMesh->LockIndexBuffer(NULL, &data)) ) return; if( FacesCount > 65535 ) memcpy(data, loadedIndex, sizeof(DWORD)*mIndexs.size()); else memcpy(data, loadedIndex, sizeof(WORD)*mIndexs.size()); pMesh->UnlockIndexBuffer(); //Free main Arrays mVertexs.clear(); mIndexs.clear(); //Mesh data ready m_RootMeshContainer = new D3DXMESHCONTAINER; m_RootMeshContainer->MeshData.pMesh = pMesh; return; }
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; }
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; }
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() ); }
//------------------------------------------------------------------------------------------------ // Name: XMesh // Desc: Constructs the subset geometry for a D3DXMesh //------------------------------------------------------------------------------------------------ bool XMesh::buildGeometryFromD3DXMesh(LPD3DXMESH d3dxMesh, SubsetGeometry* subsetGeometry, DWORD subsets) { // Check parameters if (APP_ERROR(!d3dxMesh || !subsetGeometry)("Invalid parameter to XMesh::buildGeometryFromD3DXMesh")) return false; // Add a reference to the mesh to counteract freeing it at the end d3dxMesh->AddRef(); // Get the device LPDIRECT3DDEVICE9 pd3dDevice = NULL; d3dxMesh->GetDevice(&pd3dDevice); // If this mesh isn't already in the correct format, have D3D do the grunt work of // converting it. bool generate_normals = false; // Whether or not normals need to be generated for this mesh if ((d3dxMesh->GetFVF() != D3DFVF_GEOMETRYVERTEX) || (D3DFMT_GEOMETRYINDEX == D3DFMT_INDEX32) && ((d3dxMesh->GetOptions() & D3DXMESH_32BIT) == 0)) { // Holds the mesh when its converted to the correct format LPD3DXMESH pTemd3dxMesh = NULL; // Duplicate the loaded mesh into the format if (APP_ERROR(d3dxMesh->CloneMeshFVF( D3DXMESH_SYSTEMMEM | ((D3DFMT_GEOMETRYINDEX == D3DFMT_INDEX32) ? D3DXMESH_32BIT : 0), D3DFVF_GEOMETRYVERTEX, pd3dDevice, &pTemd3dxMesh)) ("XMesh couldn't convert the source geometry format")) { d3dxMesh->Release(); pd3dDevice->Release(); return false; } // Generate normals if they didn't exist generate_normals = ((d3dxMesh->GetFVF()&D3DFVF_NORMAL)!=D3DFVF_NORMAL && (D3DFMT_GEOMETRYINDEX&D3DFVF_NORMAL)!=D3DFVF_NORMAL); // Use this mesh instead d3dxMesh->Release(); d3dxMesh = pTemd3dxMesh; } // The mesh must have its attributes sorted before it can be converted to single strips { // Allocate an adjacency buffer DWORD faces = d3dxMesh->GetNumFaces(); DWORD* pAdjacency = new DWORD[faces * 3]; bool failed = false; if (APP_ERROR(FAILED(d3dxMesh->GenerateAdjacency(ADJACENCY_EPSILON, pAdjacency)))("Unable to generate the mesh adjacency")) failed = true; { // Clean up "bowties" in the mesh that prevent lighting from being calculated correctly LPD3DXMESH cleaned_mesh = NULL; DWORD* cleaned_adjacency = new DWORD[faces * 3]; LPD3DXBUFFER errors_and_warnings = NULL; if (!failed && APP_ERROR(FAILED(D3DXCleanMesh(D3DXCLEAN_BOWTIES, d3dxMesh, pAdjacency, &cleaned_mesh, cleaned_adjacency, &errors_and_warnings))) ("Failed to clean mesh")) { failed = true; if (errors_and_warnings) { DEBUG_ERROR("Mesh cleaning error: %s", (const char*)errors_and_warnings->GetBufferPointer()); } } SAFE_RELEASE(errors_and_warnings); // If we successfully cleaned the mesh, use the new mesh and new set of // adjacencies. Otherwise, just delete anything that was allocated and // keep the original. if (failed) { SAFE_DELETE_ARRAY(cleaned_adjacency); SAFE_RELEASE(cleaned_mesh); } else { SAFE_DELETE_ARRAY(pAdjacency); SAFE_RELEASE(d3dxMesh) pAdjacency = cleaned_adjacency; d3dxMesh = cleaned_mesh; } } // Compute mesh normals, if necessary if (!failed && generate_normals && APP_ERROR(FAILED(D3DXComputeNormals(d3dxMesh, pAdjacency)))("Couldn't generate mesh normals")) { failed = true; } // Optimize the mesh if (!failed && APP_ERROR(FAILED(d3dxMesh->OptimizeInplace(D3DXMESHOPT_ATTRSORT, pAdjacency, NULL, NULL, NULL))) ("Couldn't optimize mesh attributes")) { failed = true; } // Get rid of the temporary adjacency buffer SAFE_DELETE_ARRAY(pAdjacency); // Return if there was an error if (failed) { SAFE_RELEASE(d3dxMesh); SAFE_RELEASE(pd3dDevice); return false; } } // Lock the vertex buffer GeometryVertex* pXVertices = NULL; if (APP_ERROR(d3dxMesh->LockVertexBuffer(D3DLOCK_READONLY, (VOID**)&pXVertices))("Couldn't lock source vertex buffer")) { // Erase this mesh d3dxMesh->Release(); pd3dDevice->Release(); // Failure return false; } // Iterate through all of the materials and copy vertex/index data, and assign material // information for the mesh. for (DWORD subset = 0; subset < subsets; subset++) { // Use D3DX to convert this subset into a nicely indexed form DWORD numStripIndices; LPDIRECT3DINDEXBUFFER9 pSubsetIB; if (APP_ERROR(D3DXConvertMeshSubsetToSingleStrip(d3dxMesh, subset, D3DXMESH_SYSTEMMEM, &pSubsetIB, &numStripIndices))("Couldn't convert mesh subset into indexable strip")) { // Erase any geometry we made DeallocateGeometry(subsetGeometry); // Get rid of the mesh d3dxMesh->UnlockVertexBuffer(); d3dxMesh->Release(); // Free our device pd3dDevice->Release(); // Return the error return false; } D3DINDEXBUFFER_DESC desc; GeometryIndex* pXIndices = NULL; // Check the format of the indices and lock the strip index buffer if (APP_ERROR(pSubsetIB->GetDesc(&desc))("Couldn't get .X mesh IB desc") || (desc.Format != D3DFMT_GEOMETRYINDEX) || APP_ERROR(pSubsetIB->Lock(0, 0, (VOID**)&pXIndices, D3DLOCK_READONLY))("Unable to lock the .X index buffer")) { // Erase any geometry we made DeallocateGeometry(subsetGeometry); // Get rid of the mesh pSubsetIB->Release(); d3dxMesh->UnlockVertexBuffer(); d3dxMesh->Release(); // Free our device pd3dDevice->Release(); // Error! return false; } // This table pairs an index from the .X file to an index in the buffer that // holds the vertices for this subset XIndicesTable xIndicesTable; // For each of the indices in the strip, puts its vertex ID into the indices // table. Use the counter to determine which vertex this is. { GeometryIndex vertexCounter = 0; for (DWORD e = 0; e < numStripIndices; ++e) { // Insert the entry [x-mesh index, subset index] into the table XIndicesTableInsertResult result = xIndicesTable.insert(XIndicesEntry(pXIndices[e], vertexCounter)); // If the result was successful (this isn't a duplicated X-mesh index) increment the vertex counter if (result.second) vertexCounter++; } } // Grab the number of vertices this geometry uses DWORD numVertices = (DWORD)xIndicesTable.size(); // This buffer holds all of the triangles in this subset TriangleList triangles; // This list keeps track of locations in the strip where the winding order changes. This is necessary // because this next part will remove degenerate triangles from the list. std::set<size_t> windingChanges; // Generate the list of triangles from the strip provided for (DWORD t = 0; t < numStripIndices - 2; ++t) { // Build the triangle that will be added to the buffer // CHANGED July 25, 2008: the winding order is wrong here //Triangle tri = { pXIndices[t + 0], pXIndices[t + 1], pXIndices[t + 2] }; Triangle tri = { pXIndices[t + 0], pXIndices[t + 2], pXIndices[t + 1] }; // Convert the triangle into subset-indices by using the lookup table // we generated before. tri.index[0] = xIndicesTable.find(tri.index[0])->second; tri.index[1] = xIndicesTable.find(tri.index[1])->second; tri.index[2] = xIndicesTable.find(tri.index[2])->second; // Check to make sure this triangle isn't degenerate. If it is, we can just skip // this triangle entirely to simplify the geometry. if (tri.index[0] == tri.index[1] || tri.index[1] == tri.index[2] || tri.index[0] == tri.index[2]) { // Try to find the winding in the list std::set<size_t>::iterator currentWinding = windingChanges.find(triangles.size()); // Add this to the winding change list, or remove the change if it's already there if (currentWinding != windingChanges.end()) windingChanges.erase(currentWinding); else windingChanges.insert(triangles.size()); // Don't insert a triangle here continue; } // Add this triangle to the list triangles.push_back(tri); } // Calculate the number of indices we need for the buffer DWORD numGeometryIndices = (DWORD)(triangles.size() * 3); // Allocate the destination geometry Geometry* pGeometry = NULL; if (APP_ERROR(AllocateGeometry(numVertices, numGeometryIndices, &pGeometry))("Couldn't allocate geometry")) { // Erase any geometry we made DeallocateGeometry(subsetGeometry); // Get rid of the mesh pSubsetIB->Unlock(); pSubsetIB->Release(); d3dxMesh->UnlockVertexBuffer(); d3dxMesh->Release(); // Free our device pd3dDevice->Release(); // Error! return false; } // Copy the vertices needed for this subset into the buffer GeometryVertex* pVertices = pGeometry->pVertices; for (XIndicesIterator i = xIndicesTable.begin(); i != xIndicesTable.end(); ++i) { GeometryVertex* pCurrentVertex = &pVertices[i->second]; *pCurrentVertex = pXVertices[i->first]; // Modify the vertex location to make this a unit mesh sitting on the X-Z plane pCurrentVertex->x = pCurrentVertex->x; pCurrentVertex->y = pCurrentVertex->y; pCurrentVertex->z = pCurrentVertex->z; //pVertices[i->second].color = D3DCOLOR_XRGB(255,255,255); // todo: enable color? } // Copy triangles into the indices buffer DWORD index = 0; GeometryIndex* pIndices = pGeometry->pIndices; DWORD windingOrder = 0; for (TriangleIterator t = triangles.begin(); t != triangles.end(); ++t) { // Find this index in the winding list if (windingChanges.find(index / 3) != windingChanges.end()) windingOrder = 1 - windingOrder; // Alternate the winding order so that everything shows up correctly if ((index / 3) % 2 == windingOrder) { pIndices[index + 0] = t->index[0]; pIndices[index + 1] = t->index[1]; pIndices[index + 2] = t->index[2]; } else { pIndices[index + 0] = t->index[1]; pIndices[index + 1] = t->index[0]; pIndices[index + 2] = t->index[2]; } // Increment the index counter index += 3; } // Unlock and delete strip index buffer pSubsetIB->Unlock(); pSubsetIB->Release(); // Store the buffers in the main array std::pair<SubsetGeometry::iterator,bool> result = subsetGeometry->insert(SubsetGeometry::value_type(subset, pGeometry)); if (APP_ERROR(!result.second)("Couldn't insert subset geometry into main array for .X mesh")) { // Get rid of this geometry DeallocateGeometry(pGeometry); DeallocateGeometry(subsetGeometry); // Erase the mesh d3dxMesh->UnlockVertexBuffer(); d3dxMesh->Release(); // Free our device pd3dDevice->Release(); // Return error return false; } //DEBUG_MSG("Subset %i has %i vertices %i indices (%i polygons)\n", subset, numVertices, numGeometryIndices, numGeometryIndices / 3); } // Done with the DirectX mesh. This will not erase the outside mesh. d3dxMesh->UnlockVertexBuffer(); d3dxMesh->Release(); // Free the device reference pd3dDevice->Release(); // Success return true; }
void CreateBox( const float &w, const float &h, const float &d, const bool ¢erWidth, const bool ¢erHeight, const bool ¢erDepth, LPD3DXMESH &mesh ) { float offsetX = 0, offsetY = 0, offsetZ = 0; if( centerWidth ) offsetX = -w / 2.f; if( centerHeight ) offsetY = -h / 2.f; if( centerDepth ) offsetZ = -d / 2.f; std::vector<DWORD> vIB; std::vector<VERTEX3> vVB; std::vector<DWORD> vAB; DWORD offset = 0; // fill in the front face index data vIB.push_back( 0 + offset ); vIB.push_back( 1 + offset ); vIB.push_back( 2 + offset ); vIB.push_back( 0 + offset ); vIB.push_back( 2 + offset ); vIB.push_back( 3 + offset ); // fill in the front face vertex data vVB.push_back( VERTEX3( 0.f + offsetX, 0.f + offsetY, 0.f + offsetZ, 0.f, 0.f, -1.f, 0.f, 1.f ) ); vVB.push_back( VERTEX3( 0.f + offsetX, h + offsetY, 0.f + offsetZ, 0.f, 0.f, -1.f, 0.f, 0.f ) ); vVB.push_back( VERTEX3( w + offsetX, h + offsetY, 0.f + offsetZ, 0.f, 0.f, -1.f, 1.f, 0.f ) ); vVB.push_back( VERTEX3( w + offsetX, 0.f + offsetY, 0.f + offsetZ, 0.f, 0.f, -1.f, 1.f, 1.f ) ); vAB.push_back( 0 ); vAB.push_back( 0 ); offset += 4; // fill in the back face index data vIB.push_back( 0 + offset ); vIB.push_back( 1 + offset ); vIB.push_back( 2 + offset ); vIB.push_back( 0 + offset ); vIB.push_back( 2 + offset ); vIB.push_back( 3 + offset ); // fill in the back face vertex data vVB.push_back( VERTEX3( 0.f + offsetX, 0.f + offsetY, d + offsetZ, 0.f, 0.f, 1.f, 1.f, 1.f ) ); vVB.push_back( VERTEX3( w + offsetX, 0.f + offsetY, d + offsetZ, 0.f, 0.f, 1.f, 0.f, 1.f ) ); vVB.push_back( VERTEX3( w + offsetX, h + offsetY, d + offsetZ, 0.f, 0.f, 1.f, 0.f, 0.f ) ); vVB.push_back( VERTEX3( 0.f + offsetX, h + offsetY, d + offsetZ, 0.f, 0.f, 1.f, 1.f, 0.f ) ); vAB.push_back( 1 ); vAB.push_back( 1 ); offset += 4; // fill in the top face index data vIB.push_back( 0 + offset ); vIB.push_back( 1 + offset ); vIB.push_back( 2 + offset ); vIB.push_back( 0 + offset ); vIB.push_back( 2 + offset ); vIB.push_back( 3 + offset ); //fill in the top face vertex data vVB.push_back( VERTEX3( 0.f + offsetX, h + offsetY, 0.f + offsetZ, 0.f, 1.f, 0.f, 0.f, 1.f ) ); vVB.push_back( VERTEX3( 0.f + offsetX, h + offsetY, d + offsetZ, 0.f, 1.f, 0.f, 0.f, 0.f ) ); vVB.push_back( VERTEX3( w + offsetX, h + offsetY, d + offsetZ, 0.f, 1.f, 0.f, 1.f, 0.f ) ); vVB.push_back( VERTEX3( w + offsetX, h + offsetY, 0.f + offsetZ, 0.f, 1.f, 0.f, 1.f, 1.f ) ); vAB.push_back( 2 ); vAB.push_back( 2 ); offset += 4; // fill in the bottom face index data vIB.push_back( 0 + offset ); vIB.push_back( 1 + offset ); vIB.push_back( 2 + offset ); vIB.push_back( 0 + offset ); vIB.push_back( 2 + offset ); vIB.push_back( 3 + offset ); // fill in the bottom face vertex data vVB.push_back( VERTEX3( 0.f + offsetX, 0.f + offsetY, 0.f + offsetZ, 0.f, -1.f, 0.f, 0.f, 1.f ) ); vVB.push_back( VERTEX3( w + offsetX, 0.f + offsetY, 0.f + offsetZ, 0.f, -1.f, 0.f, 0.f, 0.f ) ); vVB.push_back( VERTEX3( w + offsetX, 0.f + offsetY, d + offsetZ, 0.f, -1.f, 0.f, 1.f, 0.f ) ); vVB.push_back( VERTEX3( 0.f + offsetX, 0.f + offsetY, d + offsetZ, 0.f, -1.f, 0.f, 1.f, 1.f ) ); vAB.push_back( 3 ); vAB.push_back( 3 ); offset += 4; // fill in the left face index data vIB.push_back( 0 + offset ); vIB.push_back( 1 + offset ); vIB.push_back( 2 + offset ); vIB.push_back( 0 + offset ); vIB.push_back( 2 + offset ); vIB.push_back( 3 + offset ); // fill in the left face vertex data vVB.push_back( VERTEX3( 0.f + offsetX, 0.f + offsetY, d + offsetZ, -1.f, 0.f, 0.f, 0.f, 1.f ) ); vVB.push_back( VERTEX3( 0.f + offsetX, h + offsetY, d + offsetZ, -1.f, 0.f, 0.f, 0.f, 0.f ) ); vVB.push_back( VERTEX3( 0.f + offsetX, h + offsetY, 0.f + offsetZ, -1.f, 0.f, 0.f, 1.f, 0.f ) ); vVB.push_back( VERTEX3( 0.f + offsetX, 0.f + offsetY, 0.f + offsetZ, -1.f, 0.f, 0.f, 1.f, 1.f ) ); vAB.push_back( 4 ); vAB.push_back( 4 ); offset += 4; // fill in the right face index data vIB.push_back( 0 + offset ); vIB.push_back( 1 + offset ); vIB.push_back( 2 + offset ); vIB.push_back( 0 + offset ); vIB.push_back( 2 + offset ); vIB.push_back( 3 + offset ); // fill in the right face vertex data vVB.push_back( VERTEX3( w + offsetX, 0.f + offsetY, 0.f + offsetZ, 1.f, 0.f, 0.f, 0.f, 1.f ) ); vVB.push_back( VERTEX3( w + offsetX, h + offsetY, 0.f + offsetZ, 1.f, 0.f, 0.f, 0.f, 0.f ) ); vVB.push_back( VERTEX3( w + offsetX, h + offsetY, d + offsetZ, 1.f, 0.f, 0.f, 1.f, 0.f ) ); vVB.push_back( VERTEX3( w + offsetX, 0.f + offsetY, d + offsetZ, 1.f, 0.f, 0.f, 1.f, 1.f ) ); vAB.push_back( 5 ); vAB.push_back( 5 ); offset += 4; D3DXCreateMeshFVF( offset / 2, offset, D3DXMESH_MANAGED | D3DXMESH_32BIT, VERTEX3::FVF, g_pEngine->core->lpd3dd9, &mesh ); VERTEX3 *pVB = nullptr; mesh->LockVertexBuffer( D3DLOCK_DISCARD, reinterpret_cast< void** >( &pVB ) ); copy( vVB.begin(), vVB.end(), pVB ); mesh->UnlockVertexBuffer(); DWORD *pIB = nullptr; mesh->LockIndexBuffer( D3DLOCK_DISCARD, reinterpret_cast< void** >( &pIB ) ); copy( vIB.begin(), vIB.end(), pIB ); mesh->UnlockIndexBuffer(); DWORD *pAB = nullptr; mesh->LockAttributeBuffer( D3DLOCK_DISCARD, &pAB ); copy( vAB.begin(), vAB.end(), pAB ); mesh->UnlockAttributeBuffer(); std::vector<DWORD> adjacencyBuffer( mesh->GetNumFaces() * 3 ); mesh->GenerateAdjacency( 0.f, &adjacencyBuffer[ 0 ] ); mesh->OptimizeInplace( D3DXMESHOPT_COMPACT | D3DXMESHOPT_ATTRSORT | D3DXMESHOPT_VERTEXCACHE, &adjacencyBuffer[ 0 ], nullptr, nullptr, nullptr ); }
HRESULT KModelWater::LoadMesh(LPSTR pFileName) { HRESULT hr = S_OK; m_dwNumPoly_X = 63; //长方形网格的长,网格数 m_dwNumPoly_Z = 63; //长方形网格的宽,网格数 LPD3DXMESH pMesh = m_pWaterUp; LPD3DXMESH pDMesh = m_pWaterDn; DWORD m_dNumPloy = m_dwNumPoly_X * m_dwNumPoly_Z; DWORD m_dNumFaces = m_dNumPloy * 2; DWORD m_dNumVertices = (m_dwNumPoly_X+1)*(m_dwNumPoly_Z+1); SAFE_RELEASE(pMesh); SAFE_RELEASE(pDMesh); WORD *pwIndices; //建立水面网格 if(FAILED(hr = g_pd3dDevice->CreateIndexBuffer(m_dNumFaces * 3 * sizeof(WORD), D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, D3DFMT_INDEX16, D3DPOOL_DEFAULT, &m_pibIndices, NULL))) { return hr; } if (FAILED(hr = D3DXCreateMeshFVF(m_dNumFaces,m_dNumVertices,D3DXMESH_MANAGED|D3DXMESH_32BIT, D3DFVF_XYZ|D3DFVF_NORMAL|D3DFVF_NORMAL|D3DFVF_TEX1,g_pd3dDevice,&pMesh))) { return hr; } if (FAILED(hr = D3DXCreateMeshFVF(m_dNumFaces,m_dNumVertices,D3DXMESH_MANAGED|D3DXMESH_32BIT, D3DFVF_XYZ|D3DFVF_NORMAL|D3DFVF_NORMAL|D3DFVF_TEX1,g_pd3dDevice,&pDMesh))) { return hr; } VFormat::FACES_NORMAL_TEXTURE1 * pVers = NULL; DWORD* pIndex = NULL; DWORD * pAttrib = NULL; VFormat::FACES_NORMAL_TEXTURE1 * pDVers = NULL; DWORD* pDIndex = NULL; DWORD * pDAttrib = NULL; if(FAILED(hr = m_pibIndices->Lock(0, m_dNumFaces *3 * sizeof(WORD), (void**) &pwIndices, D3DLOCK_DISCARD))) return E_FAIL; if (FAILED(pMesh->LockVertexBuffer(0,(void**)&pVers))) return E_FAIL; if (FAILED(pMesh->LockIndexBuffer (0,(void**)&pIndex))) return E_FAIL; if (FAILED(pMesh->LockAttributeBuffer(0,(DWORD**)&pAttrib))) return E_FAIL; if (FAILED(pDMesh->LockVertexBuffer(0,(void**)&pDVers))) return E_FAIL; if (FAILED(pDMesh->LockIndexBuffer (0,(void**)&pDIndex))) return E_FAIL; if (FAILED(pDMesh->LockAttributeBuffer(0,(DWORD**)&pDAttrib))) return E_FAIL; DWORD i = 0; float _X = 1.0f/m_dwNumPoly_X; float _Z = 1.0f/m_dwNumPoly_Z; float m_fPolyWidth = 200; float m_fPolyHeight = 200; for(DWORD X =0;X<=m_dwNumPoly_X;X++) { for(DWORD Y =0;Y<=m_dwNumPoly_Z;Y++) { float PX = X * m_fPolyWidth; float PZ = Y * m_fPolyHeight; D3DXVECTOR2 Pos(PX,PZ); pVers[i].p = D3DXVECTOR3(PX,200,PZ); pVers[i].Normal = D3DXVECTOR3(0,1,0); pVers[i].tu1 = (X * _X); pVers[i].tv1 = (1 - Y *_Z); pDVers[i].p = D3DXVECTOR3(PX,0,PZ); pDVers[i].Normal = D3DXVECTOR3(0,1,0); pDVers[i].tu1 = (X * _X); pDVers[i].tv1 = (1 - Y *_Z); i++; } } DWORD Weight = m_dwNumPoly_X + 1; for(X =0;X<m_dwNumPoly_X;X++) { for(DWORD Y =0;Y<m_dwNumPoly_Z;Y++) { DWORD PloyIndex = Y*m_dwNumPoly_X +X; DWORD PolyMaterialID = 0; DWORD Vertex_A = X *Weight+ Y; DWORD Vertex_B = (X+1)*Weight+ Y; DWORD Vertex_C = (X+1)*Weight+(Y+1); DWORD Vertex_D = X *Weight+(Y+1); DWORD Faces_A1 = (PloyIndex*2)*3; DWORD Faces_B1 = Faces_A1 + 1; DWORD Faces_C1 = Faces_B1 + 1; pIndex[Faces_A1] = Vertex_A; pIndex[Faces_B1] = Vertex_B; pIndex[Faces_C1] = Vertex_D; pAttrib[PloyIndex*2] = PolyMaterialID; pDIndex[Faces_A1] = Vertex_A; pDIndex[Faces_B1] = Vertex_B; pDIndex[Faces_C1] = Vertex_D; pDAttrib[PloyIndex*2] = PolyMaterialID; pwIndices[Faces_A1] = WORD(Vertex_A); pwIndices[Faces_B1] = WORD(Vertex_B); pwIndices[Faces_C1] = WORD(Vertex_D); DWORD Faces_A2 = (PloyIndex*2+1)*3; DWORD Faces_B2 = Faces_A2 + 1; DWORD Faces_C2 = Faces_B2 + 1; pIndex[Faces_A2] = Vertex_D; pIndex[Faces_B2] = Vertex_B; pIndex[Faces_C2] = Vertex_C; pAttrib[PloyIndex*2+1] = PolyMaterialID; pDIndex[Faces_A2] = Vertex_D; pDIndex[Faces_B2] = Vertex_B; pDIndex[Faces_C2] = Vertex_C; pDAttrib[PloyIndex*2+1] = PolyMaterialID; pwIndices[Faces_A2] = WORD(Vertex_D); pwIndices[Faces_B2] = WORD(Vertex_B); pwIndices[Faces_C2] = WORD(Vertex_C); } } D3DXComputeBoundingBox((D3DXVECTOR3*)pVers,m_dNumVertices,sizeof(VFormat::FACES_NORMAL_TEXTURE1), &m_BBox_A,&m_BBox_B); D3DXComputeBoundingBox((D3DXVECTOR3*)pDVers,m_dNumVertices,sizeof(VFormat::FACES_NORMAL_TEXTURE1), &m_BBox_A,&m_BBox_B); if (FAILED(pMesh->UnlockVertexBuffer())) return E_FAIL; if (FAILED(pMesh->UnlockIndexBuffer())) return E_FAIL; if (FAILED(pMesh->UnlockAttributeBuffer())) return E_FAIL; if (FAILED(pDMesh->UnlockVertexBuffer())) return E_FAIL; if (FAILED(pDMesh->UnlockIndexBuffer())) return E_FAIL; if (FAILED(pDMesh->UnlockAttributeBuffer())) return E_FAIL; if (FAILED(m_pibIndices->Unlock())) return E_FAIL; m_pWaterUp = pMesh; m_pWaterDn = pDMesh; //水面网格的材质 m_dNumMaterial = 1; m_lpMaterial = new MATERIAL[m_dNumMaterial]; ZeroMemory(m_lpMaterial,sizeof(MATERIAL)*m_dNumMaterial); DWORD Def_Option = MATERIAL_OPTION_ZBUFFER_TRUE| MATERIAL_OPTION_FILL_SOLID| MATERIAL_OPTION_SHADE_GOURAUD| MATERIAL_OPTION_CULL_NONE| MATERIAL_OPTION_SPECULARENABLE; for(DWORD i=0;i<m_dNumMaterial;i++) { m_lpMaterial[i].m_sMaterial9.Diffuse.r = 0.7f ; m_lpMaterial[i].m_sMaterial9.Diffuse.g = 0.7f ; m_lpMaterial[i].m_sMaterial9.Diffuse.b = 0.7f ; m_lpMaterial[i].m_sMaterial9.Diffuse.a = 1.0f ; m_lpMaterial[i].m_sMaterial9.Ambient = m_lpMaterial[i].m_sMaterial9.Diffuse; m_lpMaterial[i].m_sMaterial9.Specular = m_lpMaterial[i].m_sMaterial9.Diffuse; m_lpMaterial[i].m_sMaterial9.Power = 15; m_lpMaterial[i].m_dOption = Def_Option; } TCHAR Name[256]; wsprintf(Name,"%s\\Water.Mtl",g_Def_ModelDirectory); LoadMaterial(Name); //天空盒的纹理 wsprintf(Name,"%s\\%s",g_Def_AppDirectory,"Textures\\LobbyCube.dds"); if( FAILED( hr = D3DXCreateCubeTextureFromFile( g_pd3dDevice,Name, &m_pSkyCubeTex ) ) ) return hr; //水面的纹理 wsprintf(Name,"%s\\%s",g_Def_AppDirectory,"Textures\\Water.bmp"); if( FAILED( hr = D3DXCreateTextureFromFileEx(g_pd3dDevice, Name, D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, 0, D3DFMT_UNKNOWN, D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT, 0, NULL, NULL, &m_pWaterTex) )) return hr; /* // Effect wsprintf(Name,"%s\\%s",g_Def_AppDirectory,"water.fx"); if(FAILED(hr = D3DXCreateEffectFromFile(g_pd3dDevice, Name, NULL, NULL, 0, NULL, &m_pEffect, NULL))) return hr; m_pEffect->OnResetDevice(); m_pEffect->SetTexture("tFLR", m_pWaterTex); m_pEffect->SetTexture("tENV", m_pSkyCubeTex); */ //创建水面bump纹理 if( FAILED( InitBumpMap() ) ) return E_FAIL; // m_pEffect->SetTexture("tBump", m_pBumpMapTexture); WSea.Initialize(m_dwNumPoly_X,m_dwNumPoly_Z); Water.Initialize(m_pWaterUp,m_dwNumPoly_X,m_dwNumPoly_Z); //初始化水纹 Water.Drop(); //产生水纹 Ripple.Initialize(m_pWaterUp,m_dwNumPoly_X,m_dwNumPoly_Z); //初始化涟漪纹 return S_OK; }
//----------------------------------------------------------------------------- // 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 Sombra::ConstruirSombra(LPD3DXMESH pMesh, D3DXVECTOR3 vLight) { // Note: the MeshVertex format depends on the FVF of the mesh struct MeshVertex { D3DXVECTOR3 p, n; DWORD diffuse; float tu,tv; }; MeshVertex *pVertices; WORD *pIndices; // Lock the geometry buffers pMesh->LockVertexBuffer( 0L, (LPVOID*)&pVertices ); pMesh->LockIndexBuffer( 0L, (LPVOID*)&pIndices ); DWORD dwNumFaces = pMesh->GetNumFaces(); // Allocate a temporary edge list WORD *pEdges = new WORD[dwNumFaces*6]; if( pEdges == NULL ) { pMesh->UnlockVertexBuffer(); pMesh->UnlockIndexBuffer(); return ; } DWORD dwNumEdges = 0; // For each face for( DWORD i = 0; i < dwNumFaces; ++i ) { WORD wFace0 = pIndices[3*i+0]; WORD wFace1 = pIndices[3*i+1]; WORD wFace2 = pIndices[3*i+2]; D3DXVECTOR3 v0 = pVertices[wFace0].p; D3DXVECTOR3 v1 = pVertices[wFace1].p; D3DXVECTOR3 v2 = pVertices[wFace2].p; // Transform vertices or transform light? D3DXVECTOR3 vCross1(v2-v1); D3DXVECTOR3 vCross2(v1-v0); D3DXVECTOR3 vNormal; D3DXVec3Cross( &vNormal, &vCross1, &vCross2 ); if( D3DXVec3Dot( &vNormal, &vLight ) >= 0.0f ) { InsertarSegmento( pEdges, dwNumEdges, wFace0, wFace1 ); InsertarSegmento( pEdges, dwNumEdges, wFace1, wFace2 ); InsertarSegmento( pEdges, dwNumEdges, wFace2, wFace0 ); } } // Se construyen las caras de la sombra extrudando los segmentos en la dirección // de la luz y una longitud 10 veces la del vector luz. for( i = 0; i < dwNumEdges; ++i ) { D3DXVECTOR3 v1 = pVertices[pEdges[2*i+0]].p; D3DXVECTOR3 v2 = pVertices[pEdges[2*i+1]].p; D3DXVECTOR3 v3 = v1 - vLight/10; D3DXVECTOR3 v4 = v2 - vLight/10; // Add a quad (two triangles) to the vertex list m_pVertices[m_dwNumVertices++] = v1; m_pVertices[m_dwNumVertices++] = v2; m_pVertices[m_dwNumVertices++] = v3; m_pVertices[m_dwNumVertices++] = v2; m_pVertices[m_dwNumVertices++] = v4; m_pVertices[m_dwNumVertices++] = v3; } // Delete the temporary edge list delete[] pEdges; // Unlock the geometry buffers pMesh->UnlockVertexBuffer(); pMesh->UnlockIndexBuffer(); }
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] ); } }
//************************************************************************************************************* void GenerateEdges(edgeset& out, LPD3DXMESH mesh) { D3DXVECTOR3 p1, p2, p3; D3DXVECTOR3 a, b, n; Edge e; BYTE* vdata = 0; WORD* idata = 0; size_t ind; DWORD numindices = mesh->GetNumFaces() * 3; DWORD stride = mesh->GetNumBytesPerVertex(); WORD i1, i2, i3; bool is32bit = (mesh->GetOptions() & D3DXMESH_32BIT); out.clear(); if( is32bit ) { MYERROR("GenerateEdges(): 4 byte indices not implemented yet"); return; } // generate edge info mesh->LockIndexBuffer(D3DLOCK_READONLY, (LPVOID*)&idata); mesh->LockVertexBuffer(D3DLOCK_READONLY, (LPVOID*)&vdata); out.reserve(512); for( DWORD i = 0; i < numindices; i += 3 ) { if( out.capacity() <= out.size() ) out.reserve(out.size() + 1024); i1 = idata[i + 0]; i2 = idata[i + 1]; i3 = idata[i + 2]; p1 = *((D3DXVECTOR3*)(vdata + i1 * stride)); p2 = *((D3DXVECTOR3*)(vdata + i2 * stride)); p3 = *((D3DXVECTOR3*)(vdata + i3 * stride)); a = p2 - p1; b = p3 - p1; D3DXVec3Cross(&n, &a, &b); D3DXVec3Normalize(&n, &n); if( i1 < i2 ) { e.i1 = i1; e.i2 = i2; e.v1 = p1; e.v2 = p2; e.n1 = n; if( !out.insert(e) ) std::cout << "Crack in mesh (first triangle)\n"; } if( i2 < i3 ) { e.i1 = i2; e.i2 = i3; e.v1 = p2; e.v2 = p3; e.n1 = n; if( !out.insert(e) ) std::cout << "Crack in mesh (first triangle)\n"; } if( i3 < i1 ) { e.i1 = i3; e.i2 = i1; e.v1 = p3; e.v2 = p1; e.n1 = n; if( !out.insert(e) ) std::cout << "Crack in mesh (first triangle)\n"; } } // find second triangle for each edge for( DWORD i = 0; i < numindices; i += 3 ) { i1 = idata[i + 0]; i2 = idata[i + 1]; i3 = idata[i + 2]; p1 = *((D3DXVECTOR3*)(vdata + i1 * stride)); p2 = *((D3DXVECTOR3*)(vdata + i2 * stride)); p3 = *((D3DXVECTOR3*)(vdata + i3 * stride)); a = p2 - p1; b = p3 - p1; D3DXVec3Cross(&n, &a, &b); D3DXVec3Normalize(&n, &n); if( i1 > i2 ) { e.i1 = i2; e.i2 = i1; ind = out.find(e); if( ind == edgeset::npos ) { std::cout << "Lone triangle\n"; continue; } if( out[ind].other == 0xffffffff ) { out[ind].other = i / 3; out[ind].n2 = n; } else std::cout << "Crack in mesh (second triangle)\n"; } if( i2 > i3 ) { e.i1 = i3; e.i2 = i2; ind = out.find(e); if( ind == edgeset::npos ) { std::cout << "Lone triangle\n"; continue; } if( out[ind].other == 0xffffffff ) { out[ind].other = i / 3; out[ind].n2 = n; } else std::cout << "Crack in mesh (second triangle)\n"; } if( i3 > i1 ) { e.i1 = i1; e.i2 = i3; ind = out.find(e); if( ind == edgeset::npos ) { std::cout << "Lone triangle\n"; continue; } if( out[ind].other == 0xffffffff ) { out[ind].other = i / 3; out[ind].n2 = n; } else std::cout << "Crack in mesh (second triangle)\n"; } } mesh->UnlockIndexBuffer(); mesh->UnlockVertexBuffer(); }
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; }
bool GraphicalPlane::GenerateBoard(const std::string& path, const int &width, const int &height, const TextureSP &texture) { // キーネーム設定 std::stringstream nameBuffer(""); // ファイルパス→生成番号→幅高さの順で追加 nameBuffer << path << ++_createCount << width << height; std::string name = nameBuffer.str(); // メッシュインスタンスの生成 _mesh = Mesh::CreateEmpty(name); // サイズを記録 _size.x = (float)width ; _size.y = (float)height ; //_size.z = 0 ; // テクスチャ指定がある場合そのサイズを取得 if(texture != NULL) { while(UINT(_textureSize.x) < _texture->GetImageInfo().Width) { _textureSize.x *= 2; } while(UINT(_textureSize.y) < _texture->GetImageInfo().Height) { _textureSize.y *= 2; } } // シェーダー設定 _shader = ShaderNormal::Create(); // メッシュを生成する LPD3DXMESH mesh; if (FAILED(D3DXCreateMeshFVF(2, 4, D3DXMESH_MANAGED, Vertex::FVF, GraphicsManager::_device, &mesh))) return false; //頂点データの作成 Vertex* vertex; mesh->LockVertexBuffer(0, (void**)&vertex); for (int y = 0 ; y < 2 ; y++) { for (int x = 0 ; x < 2 ; x++) { float x1 = (float)(x * width - ((float)width / 2)); float y1 = (float)(y * height - ((float)height / 2)); int index = y * 2 + x; vertex[index]._position.x = x1; vertex[index]._position.y = y1; vertex[index]._position.z = 0; vertex[index]._normal.x = 0; vertex[index]._normal.y = 0; vertex[index]._normal.z = 1; if( texture == NULL ) { vertex[index]._uv.x = (float)x * 1.0f; vertex[index]._uv.y = 1.0f - ((float)y * 1.0f); } } } if(texture) { vertex[0]._uv.x = (float)_rects[_number].left / _texture->GetImageInfo().Width; vertex[0]._uv.y = (float)_rects[_number].bottom / _texture->GetImageInfo().Height; vertex[1]._uv.x = (float)_rects[_number].right / _texture->GetImageInfo().Width; vertex[1]._uv.y = (float)_rects[_number].bottom / _texture->GetImageInfo().Height; vertex[2]._uv.x = (float)_rects[_number].left / _texture->GetImageInfo().Width; vertex[2]._uv.y = (float)_rects[_number].top / _texture->GetImageInfo().Height; vertex[3]._uv.x = (float)_rects[_number].right / _texture->GetImageInfo().Width; vertex[3]._uv.y = (float)_rects[_number].top / _texture->GetImageInfo().Height; } mesh->UnlockVertexBuffer(); //インデックスデータの作成 WORD *index; mesh->LockIndexBuffer(0, (void **)&index); index[0] = 0; index[1] = 2; index[2] = 1; index[3] = 1; index[4] = 2; index[5] = 3; mesh->UnlockIndexBuffer(); _mesh->SetMesh(mesh); return true; }
//----------------------------------------------------------------------------- // Name: buildShadowVolume() // Desc: Takes a mesh as input, and uses it to build a shadow volume. The // technique used considers each triangle of the mesh, and adds it's // edges to a temporary list. The edge list is maintained, such that // only silohuette edges are kept. Finally, the silohuette edges are // extruded to make the shadow volume vertex list. //----------------------------------------------------------------------------- HRESULT CShadowVolume::BuildShadowVolume(LPD3DXMESH pMesh, D3DXVECTOR3 vLight) { // pMesh的顶点结构 struct MeshVertex { D3DXVECTOR3 p; D3DXVECTOR3 n; float u, v; }; MeshVertex *pVertices; WORD *pIndices; // 锁缓存 pMesh->LockVertexBuffer(0L, (LPVOID*)&pVertices); pMesh->LockIndexBuffer(0L, (LPVOID*)&pIndices); DWORD dwNumFaces = pMesh->GetNumFaces(); // 分配一个临时的索引数组 WORD *pEdges = new WORD[dwNumFaces * 6]; if (pEdges == NULL) { pMesh->UnlockVertexBuffer(); pMesh->UnlockIndexBuffer(); return E_OUTOFMEMORY; } DWORD dwNumEdges = 0; // 对每个片面进行计算 for (DWORD i = 0; i < dwNumFaces; ++i) { WORD wFace0 = pIndices[3 * i + 0]; WORD wFace1 = pIndices[3 * i + 1]; WORD wFace2 = pIndices[3 * i + 2]; // 一个面的三个顶点坐标 D3DXVECTOR3 v0 = pVertices[wFace0].p; D3DXVECTOR3 v1 = pVertices[wFace1].p; D3DXVECTOR3 v2 = pVertices[wFace2].p; // 计算法线是否向光 D3DXVECTOR3 vCross1(v2 - v1); D3DXVECTOR3 vCross2(v1 - v0); D3DXVECTOR3 vNormal; D3DXVec3Cross(&vNormal, &vCross1, &vCross2); if (D3DXVec3Dot(&vNormal, &vLight) >= 0.0f) { AddEdge(pEdges, dwNumEdges, wFace0, wFace1); AddEdge(pEdges, dwNumEdges, wFace1, wFace2); AddEdge(pEdges, dwNumEdges, wFace2, wFace0); } } // pEdges中仅剩pMesh的边缘顶点,对每条边的两个顶点按光照的方向进行延伸 // 最终构建一个完整的阴影体 for (DWORD i = 0; i < dwNumEdges; ++i) { D3DXVECTOR3 v1 = pVertices[pEdges[2 * i + 0]].p; D3DXVECTOR3 v2 = pVertices[pEdges[2 * i + 1]].p; D3DXVECTOR3 v3 = v1 + vLight * 200; D3DXVECTOR3 v4 = v2 + vLight * 200; // 封边操作 m_pVertices[m_dwNumVertices++] = v1; m_pVertices[m_dwNumVertices++] = v2; m_pVertices[m_dwNumVertices++] = v3; m_pVertices[m_dwNumVertices++] = v2; m_pVertices[m_dwNumVertices++] = v4; m_pVertices[m_dwNumVertices++] = v3; } // Delete the temporary edge list delete[] pEdges; // Unlock the geometry buffers pMesh->UnlockVertexBuffer(); pMesh->UnlockIndexBuffer(); return S_OK; }
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(); } }
//------------------------------------------------------------------------------------------------ // Name: CreateTerrainMesh // Desc: //------------------------------------------------------------------------------------------------ bool CreateTerrainMesh(LPDIRECT3DDEVICE9 d3dDevice, LPD3DXMESH* terrainMesh) { // Calculate the number of faces and vertices required const unsigned int faces = (TMS_COUNT + 3) * 2; const unsigned int vertices = (TMS_COUNT + 3) * 4; // The internal terrain mesh LPD3DXMESH internalTerrainMesh; // Create the mesh HRESULT hr = D3DXCreateMeshFVF(faces, vertices, D3DXMESH_MANAGED, D3DFVF_GEOMETRYVERTEX, d3dDevice, &internalTerrainMesh); if (APP_ERROR(FAILED(hr))("Unable to create the terrain mesh")) return false; // Lock the mesh buffers GeometryVertex* lockedVertices = 0; WORD* lockedIndices = 0; DWORD* lockedAttributes = 0; if (APP_ERROR(FAILED(internalTerrainMesh->LockAttributeBuffer(0, &lockedAttributes)) || FAILED(internalTerrainMesh->LockVertexBuffer(0, (VOID**)&lockedVertices)) || FAILED(internalTerrainMesh->LockIndexBuffer(0, (VOID**)&lockedIndices)))("Unable to lock terrain mesh")) { // Deallocate the mesh SAFE_RELEASE(internalTerrainMesh); // Exit the method return false; } // Vertices that will be rotated 4x about Y at // 90-degree intervals to produce the wall mesh GeometryVertex wallSide[] = { { -0.5f, 0.0f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f }, { -0.5f, 0.0f, +0.5f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f }, { -0.5f, -1.0f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f }, { -0.5f, -1.0f, +0.5f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f }, }; // The flat square with unit size GeometryVertex flat[] = { { -0.5f, 0.0f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f }, { +0.5f, 0.0f, -0.5f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f }, { -0.5f, 0.0f, +0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f }, { +0.5f, 0.0f, +0.5f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f }, }; // Geometry template for the high-corner meshes, // with the high corner in the north-west GeometryVertex highCorner[] = { { -0.5f, +1.0f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f }, { +0.5f, 0.0f, -0.5f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f }, { -0.5f, 0.0f, +0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f }, { +0.5f, 0.0f, +0.5f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f }, }; // Geometry template for the low-corner meshes, // with the low corner in the north-west GeometryVertex lowCorner[] = { { -0.5f, -1.0f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f }, { +0.5f, 0.0f, -0.5f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f }, { -0.5f, 0.0f, +0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f }, { +0.5f, 0.0f, +0.5f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f }, }; // Geometry template for the high-side meshes, // with the high side to the north GeometryVertex highSide[] = { { -0.5f, +1.0f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f }, { +0.5f, +1.0f, -0.5f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f }, { -0.5f, 0.0f, +0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f }, { +0.5f, 0.0f, +0.5f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f }, }; // Geometry template for the low-corner meshes, // with the low corner in the north-west GeometryVertex raisedLowCorner[] = { { -0.5f, 0.0f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f }, { +0.5f, +1.0f, -0.5f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f }, { -0.5f, +1.0f, +0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f }, { +0.5f, +1.0f, +0.5f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f }, }; // Geometry template for the low-side meshes, // with the low side to the north GeometryVertex lowSide[] = { { -0.5f, -1.0f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f }, { +0.5f, -1.0f, -0.5f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f }, { -0.5f, 0.0f, +0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f }, { +0.5f, 0.0f, +0.5f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f }, }; // The subset that is currently being written unsigned int currentSubset = TMS_WALL_SIDES; // Copy the wall first--it does not have any texture rotations lockedVertices = CopyYRotatedGeometry(lockedVertices, wallSide, 4, 0.0f * D3DX_PI / 2.0f); lockedVertices = CopyYRotatedGeometry(lockedVertices, wallSide, 4, 1.0f * D3DX_PI / 2.0f); lockedVertices = CopyYRotatedGeometry(lockedVertices, wallSide, 4, 2.0f * D3DX_PI / 2.0f); lockedVertices = CopyYRotatedGeometry(lockedVertices, wallSide, 4, 3.0f * D3DX_PI / 2.0f); // Copy four sets of squares lockedIndices = PrintSquareIndices(lockedIndices, 0, 4); lockedAttributes = PrintAttributes(lockedAttributes, currentSubset, 4); // Move to the next subset currentSubset++; // Write the flat mesh first, since it only has texture rotations for (unsigned int textureDirection = 0; textureDirection < 4; ++textureDirection, ++currentSubset) { SetTerrainTexcoords(flat, textureDirection); lockedVertices = CopyYRotatedGeometry(lockedVertices, flat, 4, 0.0f); lockedIndices = PrintSquareIndices(lockedIndices, 4 + currentSubset - 1, 1); lockedAttributes = PrintAttributes(lockedAttributes, currentSubset, 1); } // Repeat for all combinations of texture direction and rotation for the remaining types for (int type = 0; type < 5; ++type) { GeometryVertex* sourceGeometry; switch(type) { case 0: sourceGeometry = highCorner; break; case 1: sourceGeometry = lowCorner; break; case 2: sourceGeometry = highSide; break; case 3: sourceGeometry = raisedLowCorner; break; case 4: sourceGeometry = lowSide; break; } // Repeat for all rotations for (int rotation = 0; rotation < 4; ++rotation) { // Calculate the rotation angle float rotationAngle = D3DX_PI / 2.0f * rotation; // Repeat for all texture directions for (unsigned int textureDirection = 0; textureDirection < 4; ++textureDirection, ++currentSubset) { // Reverse the rotation of the texture by the rotation of the element so that we get // consistent texture directions (i.e. north is texture-up on all tiles) SetTerrainTexcoords(sourceGeometry, (textureDirection - rotation + 4) % 4); lockedVertices = CopyYRotatedGeometry(lockedVertices, sourceGeometry, 4, rotationAngle); lockedIndices = PrintSquareIndices(lockedIndices, 4 + currentSubset - 1, 1); lockedAttributes = PrintAttributes(lockedAttributes, currentSubset, 1); } } } // Unlock the buffers internalTerrainMesh->UnlockVertexBuffer(); internalTerrainMesh->UnlockIndexBuffer(); internalTerrainMesh->UnlockAttributeBuffer(); // Normalize //CONFIRM(SUCCEEDED(D3DXComputeNormals(internalTerrainMesh, NULL))); // Assign the output mesh *terrainMesh = internalTerrainMesh; // Success return true; }
HRESULT InitMesh() { // Create mesh HRESULT hr = D3DXCreateMeshFVF( NumTriangles, NumVertex, D3DXMESH_MANAGED | D3DXMESH_32BIT, Vertex_FVF, g_pd3dDevice, &g_pMesh); if (FAILED(hr)) { return E_FAIL; } // Define the 8 vertex of the cube D3DXVECTOR3 vertex[] = { D3DXVECTOR3(-0.5f, -0.5f, -0.5f), D3DXVECTOR3( 0.5f, -0.5f, -0.5f), D3DXVECTOR3( 0.5f, 0.5f, -0.5f), D3DXVECTOR3(-0.5f, 0.5f, -0.5f), D3DXVECTOR3(-0.5f, -0.5f, 0.5f), D3DXVECTOR3( 0.5f, -0.5f, 0.5f), D3DXVECTOR3( 0.5f, 0.5f, 0.5f), D3DXVECTOR3(-0.5f, 0.5f, 0.5f), }; // Lock vertex buffer and copy data void* pVertices = NULL; g_pMesh->LockVertexBuffer(0, &pVertices); memcpy(pVertices, vertex, sizeof(vertex)); g_pMesh->UnlockVertexBuffer(); // Define 36 index of the cube DWORD index[] = { // Front face 0, 3, 1, 3, 2, 1, // Back face 5, 6, 2, 6, 7, 2, // Left face 4, 7, 0, 7, 3, 0, // Right face 1, 2, 5, 2, 6, 5, // Top face 3, 7, 2, 7, 6, 2, // Bottom face 4, 0, 5, 0, 1, 5, }; // Lock index buffer and copy data DWORD* pIndices = NULL; g_pMesh->LockIndexBuffer(0, (void**)&pIndices); memcpy(pIndices, index, sizeof(index)); g_pMesh->UnlockIndexBuffer(); // Compute normals D3DXComputeNormals(g_pMesh, 0); return D3D_OK; }