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 D3DXMeshCreateIndexEnumer( LPD3DXMESH pMesh, D3DXMeshIndexEnumer& enumer ) { _ASSERTE(! enumer.IsValid()); ZeroMemory(&enumer, sizeof(D3DXMeshIndexEnumer)); //因为外部传入的enumer是可能重用的,这里绝对要重新清空一次 _ASSERTE(NULL != pMesh); KG_PROCESS_ERROR(NULL != pMesh); { HRESULT hr = pMesh->LockIndexBuffer(0, reinterpret_cast<LPVOID*>(&enumer.m_pBuffer)); KG_COM_PROCESS_ERROR(hr); _ASSERTE(1 == sizeof(BYTE) && 2 == sizeof(WORD) && 4 == sizeof(DWORD)); enumer.m_pMesh = pMesh; enumer.m_pMesh->AddRef(); enumer.m_dwNumBytePerIndex = (pMesh->GetOptions() & D3DXMESH_32BIT) ? 4 : 2; enumer.m_dwNumIndexCount = pMesh->GetNumFaces() * 3; return S_OK; } Exit0: return E_FAIL; }
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; }
//------------------------------------------------------ // 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; }
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; }
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; }
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; }
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 ); }
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(); } }
void MeshParameterization::GenerateCache( LPD3DXMESH meshOut, LPD3DXBUFFER remapped ) { paramVertex * pNewVerts = NULL; IToolBox * tool = EngineGetToolBox(); HRESULT hr; m_Cache.Clean(); //have to now be able to map a face to a texture area, or, a face to a chart. int numVertices = m_CollapsedMesh->size(); int numNewVertices = remapped->GetBufferSize() / sizeof( DWORD ); if( numNewVertices != numVertices ) { //Our cache is a remapping cache! New vertices were generated!!!! m_Cache.m_bRemapped = true; //First we remap our vertices int remapsize = remapped->GetBufferSize() / sizeof( DWORD ); DWORD * remappedData = (DWORD*) remapped->GetBufferPointer(); m_Cache.m_NumVertices = remapsize; m_Cache.ResizeRemappedData( remapsize ); m_Cache.ResizeUVData( remapsize*2 ); memcpy( m_Cache.m_RemappedData, remappedData, sizeof( DWORD )*remapsize ); vector< ParameterizationVertex > newVertBuffer; newVertBuffer.resize( remapsize ); //loop through and assign new vertices hr = meshOut->LockVertexBuffer( 0, (LPVOID*)&pNewVerts ); if( hr == D3D_OK && pNewVerts) { for( int i = 0; i < remapsize; i++ ) { int oldIndex = remappedData[ i ]; newVertBuffer[ i ] = (*m_CollapsedMesh)[ oldIndex ]; //UV for internal lightmap calcs NormalizeUV( pNewVerts[ i ].u ); NormalizeUV( pNewVerts[ i ].v ); newVertBuffer[ i ].generatedU = pNewVerts[ i ].u; newVertBuffer[ i ].generatedV = pNewVerts[ i ].v; //Duplicate uv to pass to render object as a stream m_Cache.m_UVData[ i*2 ] = pNewVerts[ i ].u; m_Cache.m_UVData[ i*2 + 1 ] = pNewVerts[ i ].v; } meshOut->UnlockVertexBuffer(); //assign new mesh m_CollapsedMesh->clear(); (*m_CollapsedMesh) = newVertBuffer; newVertBuffer.clear(); }else { tool->Log( LOGERROR, _T("Could not lock mesh param vertex buffer to remap vertices\n")); } //now do indices int numIndices = 3*meshOut->GetNumFaces(); m_Cache.m_NumIndices = numIndices; m_Cache.ResizeRemappedIndices( numIndices ); WORD * pIndices = NULL; hr = meshOut->LockIndexBuffer( 0, (LPVOID*)&pIndices ); if( hr == D3D_OK && pIndices) { for( int i = 0; i < numIndices; i++ ) { m_Cache.m_RemappedIndices[ i ] = (DWORD)pIndices[ i ]; //faces int faceIndex = i/3; int triIndex = i%3; (*m_Faces)[ faceIndex ].index[ triIndex ] = pIndices[ i ]; } }else if( tool ) { tool->Log( LOGERROR, _T("Could not lock mesh param index buffer to remap indices\n")); } } else //no remapping, just uvs needed { BYTE * pNewVerts = NULL; hr = meshOut->LockVertexBuffer( 0, (LPVOID*)&pNewVerts ); m_Cache.m_NumVertices = m_CollapsedMesh->size(); m_Cache.ResizeUVData( m_Cache.m_NumVertices*2 ); if( hr == D3D_OK ) { //copy new uvs paramVertex * pv = (paramVertex*)pNewVerts; for( int i = 0; i < (int)m_CollapsedMesh->size(); i++ ) { NormalizeUV( pv[ i ].u ); NormalizeUV( pv[ i ].v ); (*m_CollapsedMesh)[i].generatedU = pv[ i ].u; (*m_CollapsedMesh)[i].generatedV = pv[ i ].v; //copy uvs for passing to render object as a stream m_Cache.m_UVData[ i*2 ] = pv[ i ].u; m_Cache.m_UVData[ i*2 + 1 ] = pv[ i ].v; } meshOut->UnlockVertexBuffer(); } } }
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; }
//************************************************************************************************************* 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(); }
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(); }
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 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; }
//----------------------------------------------------------------------------- // 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; }
//------------------------------------------------------------------------------------------------ // 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; }
DWORD MeshParameterization::OnGenerateAtlas( DWORD size, void * params ) { VERIFY_MESSAGE_SIZE( size, sizeof( GENERATEATLASMESSAGE ) ); GENERATEATLASMESSAGE * msg = (GENERATEATLASMESSAGE*)params; if( !msg ) { return MSG_ERROR; } bool bUseIncomingTexCoords = msg->useIncomingTexCoords; GenerateBounds(); HRESULT hr; //This should be changed to use a new mesh parameterization technique DWORD numFaces = (DWORD)m_Faces->size(); DWORD numVertices = (DWORD)m_CollapsedMesh->size(); DWORD curError = 0; if( !bUseIncomingTexCoords && numFaces > 0 && numVertices > 0 ) { DWORD fvf = D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_TEX1 ; DWORD flags = D3DXMESH_SYSTEMMEM ;// | D3DXMESH_MANAGED ;// | D3DXMESH_SOFTWAREPROCESSING | D3DXMESH_SYSTEMMEM |; LPD3DXMESH mesh = NULL; hr = D3DXCreateMeshFVF( numFaces, numVertices, flags, fvf, m_pDevice, &mesh ); if( FAILED( hr ) ) { curError = GetLastError(); EngineGetToolBox()->Log(LOGERROR, _T("MeshParameterization: Error in create mesh fvf\n")); return MSG_ERROR; } //now fill with data BYTE * vertexData; BYTE * indexData; hr = mesh->LockVertexBuffer( 0, (LPVOID*)&vertexData ); hr = mesh->LockIndexBuffer( 0, (LPVOID*)&indexData ); D3DVERTEXELEMENT9 Decl[ MAX_FVF_DECL_SIZE ]; mesh->GetDeclaration( Decl ); paramVertex * pVertOriginal = (paramVertex*)vertexData; for( int i = 0; i < (int)numVertices; i++ ) { paramVertex * pVert = (paramVertex*)vertexData; pVert->x = (*m_CollapsedMesh)[i].originalPosition.x; pVert->y = (*m_CollapsedMesh)[i].originalPosition.y; pVert->z = (*m_CollapsedMesh)[i].originalPosition.z; pVert->nx = -(*m_CollapsedMesh)[i].normal.x; pVert->ny = -(*m_CollapsedMesh)[i].normal.y; pVert->nz = -(*m_CollapsedMesh)[i].normal.z; pVert->u = (*m_CollapsedMesh)[i].generatedU; pVert->v = (*m_CollapsedMesh)[i].generatedV; NormalizeUV( pVert->u ); NormalizeUV( pVert->v ); vertexData += sizeof( paramVertex ); } for( int i = 0; i < (int)numFaces; i++ ) { unsigned short * index = (unsigned short*)indexData; index[0] = ( unsigned short )(*m_Faces)[ i ].index[ 0 ]; index[1] = ( unsigned short )(*m_Faces)[ i ].index[ 1 ]; index[2] = ( unsigned short )(*m_Faces)[ i ].index[ 2 ]; indexData += sizeof( unsigned short )*3;//32 bit indices triangles } LPD3DXBUFFER imt; hr = D3DXComputeIMTFromPerVertexSignal( mesh, (const float*)pVertOriginal + 3*sizeof(float), 3, sizeof(paramVertex), 0L, 0, 0, &imt ); mesh->UnlockIndexBuffer(); mesh->UnlockVertexBuffer(); //tensors float * tensors = new float[ 3*numFaces ]; for( int i = 0; i < 3*(int)numFaces; i += 3 ) { tensors[ i ] = 4.f; tensors[ i + 1 ] = 0.f; tensors[ i + 2 ] = 4.f; } //some checks numVertices = mesh->GetNumVertices(); numFaces = mesh->GetNumFaces(); //create adjacency DWORD * adjacency = new DWORD[ 3*numFaces ]; memset( adjacency, 0, sizeof(DWORD)*3*numFaces ); hr = mesh->GenerateAdjacency( 0.001f, adjacency ); //hr = mesh->ConvertPointRepsToAdjacency( NULL, adjacency ); if( FAILED( hr ) ) { curError = GetLastError(); EngineGetToolBox()->Log(LOGERROR, _T("MeshParameterization: Error in generate adjacency\n")); return MSG_ERROR; } /* save to mesh to check model uvs D3DXMATERIAL mat; mat.MatD3D.Ambient.r = mat.MatD3D.Ambient.a =mat.MatD3D.Ambient.b =mat.MatD3D.Ambient.g = 0; mat.MatD3D.Diffuse.r = mat.MatD3D.Diffuse.a =mat.MatD3D.Diffuse.b =mat.MatD3D.Diffuse.g = 1; mat.pTextureFilename = "tex.dds"; D3DXSaveMeshToX( "mesh.x", mesh, adjacency, &mat, NULL, 0, D3DXF_FILEFORMAT_TEXT ); */ float * imtTensor = tensors;//(float*)imt->GetBufferPointer(); float stretchout; unsigned int charts; LPD3DXMESH meshOut = NULL; LPD3DXBUFFER remappedData = NULL; LPD3DXBUFFER faceData = NULL; D3DXATTRIBUTERANGE Attrib; memset(&Attrib, 0, sizeof(D3DXATTRIBUTERANGE)); Attrib.FaceCount = numFaces; Attrib.VertexCount = numVertices; mesh->SetAttributeTable(&Attrib, 1); int gutter = m_TexSize / 32; gutter = min( gutter, 6 ); hr = D3DXUVAtlasCreate( mesh, 0, .5, m_TexSize, m_TexSize, 6, //gutter 0, adjacency, 0, imtTensor, (LPD3DXUVATLASCB)UVGenCallback, .0001f, 0, //D3DXUVATLAS_GEODESIC_QUALITY , D3DXUVATLAS_GEODESIC_FAST, &meshOut, &faceData, &remappedData, &stretchout, &charts ); if( FAILED( hr ) ) { curError = GetLastError(); EngineGetToolBox()->Log(LOGERROR, _T("MeshParameterization: Error in uv atlas create\n")); return MSG_ERROR; } /* save to mesh to check model uvs hr = meshOut->ConvertPointRepsToAdjacency( NULL, adjacency ); D3DXSaveMeshToX( "mesh2.x", meshOut, adjacency, &mat, NULL, 0, D3DXF_FILEFORMAT_TEXT ); */ delete [] adjacency; delete [] tensors; //Generate our lightmap cache data for passing on and saving GenerateCache( meshOut, remappedData ); GenerateTriangleTexelData(); meshOut->Release(); faceData->Release(); remappedData->Release(); mesh->Release(); } else if( bUseIncomingTexCoords ) { GenerateCache(); GenerateTriangleTexelData(); } return MSG_HANDLED_STOP; }