#include "dxstdafx.h" #include ".\meshexploder.h" #include "TriangleMesh.h" #include "Vector.hpp" #include "L.h" #include #include #include "xmlwriter.h" #include "FlexVertex.h" using namespace xmlw; MeshExploder::MeshExploder(LPDIRECT3DDEVICE9 device, LPD3DXMESH originalMesh, D3DXMATERIAL* originalMaterials, wchar_t** materialNames, D3DXEFFECTINSTANCE* originalShaders, unsigned int nPieces) { this->device = device; this->originalMesh = originalMesh; this->originalMaterials = originalMaterials; this->originalShaders = originalShaders; this->nPieces = nPieces; this->materialNames = materialNames; fragmentMeshes = NULL; fragmentAttribIndices = NULL; composedMaterials = NULL; composedShaders = NULL; composedMaterialNames = NULL; } MeshExploder::~MeshExploder(void) { if(fragmentMeshes) { for(int f=0; fRelease(); } delete [] fragmentMeshes; } if(fragmentAttribIndices) delete [] fragmentAttribIndices; //we need these as output /* if(composedMaterials) delete [] composedMaterials; if(composedShaders) delete [] composedShaders;*/ if(composedMaterialNames) delete [] composedMaterialNames; } struct Tri { unsigned short origMeshIndex; Vector pos; Vector normal; }; void MeshExploder::explode() { fragmentMeshes = new LPD3DXMESH[nPieces]; fragmentAttribIndices = new DWORD[nPieces]; originalMesh->OptimizeInplace(D3DXMESHOPT_ATTRSORT, NULL, NULL, NULL, NULL); LPDIRECT3DVERTEXBUFFER9 vertexBuffer; originalMesh->GetVertexBuffer(&vertexBuffer); FlexVertexArray vertexData(originalMesh->GetNumBytesPerVertex()); D3DVERTEXELEMENT9 elem[64]; originalMesh->GetDeclaration(elem); vertexData.setFormat(elem); vertexBuffer->Lock(0,originalMesh->GetNumVertices()*originalMesh->GetNumBytesPerVertex(),vertexData.getDataPointerReference(),0); LPDIRECT3DINDEXBUFFER9 indexBuffer; originalMesh->GetIndexBuffer(&indexBuffer); DWORD nSubsets; originalMesh->GetAttributeTable(NULL, &nSubsets); D3DXATTRIBUTERANGE* subsetRanges = new D3DXATTRIBUTERANGE[nSubsets]; originalMesh->GetAttributeTable(subsetRanges, &nSubsets); unsigned int piecesToGo = nPieces; unsigned int facesToGo = originalMesh->GetNumFaces(); int iPiece=0; for(int iSubset=0; iSubsetLock(subsetRanges[iSubset].FaceStart*3*sizeof(unsigned short), nTris*3*sizeof(unsigned short), (void**)&indexData,0); Tri* tris = new Tri[nTris]; //partition to small meshes for(int g=0; gGetNumVertices()]; for(int zzz=0; zzzGetNumVertices(); zzz++) ill[zzz] = 0; for(int rmi = triClusterStart; rmiGetNumVertices(); ccc++) if(ill[ccc]) nVertices++; LPD3DXMESH fragMesh; // create new mesh HRESULT dhre = D3DXCreateMeshFVF( slabNTris[ict], nVertices, 0, originalMesh->GetFVF(), device, &fragMesh); // fill with tris LPDIRECT3DVERTEXBUFFER9 svertexBuffer; fragMesh->GetVertexBuffer(&svertexBuffer); FlexVertexArray svertexData(fragMesh->GetNumBytesPerVertex()); svertexBuffer->Lock(0, nVertices * fragMesh->GetNumBytesPerVertex(),svertexData.getDataPointerReference(),0); LPDIRECT3DINDEXBUFFER9 sindexBuffer; fragMesh->GetIndexBuffer(&sindexBuffer); unsigned short* sindexData; sindexBuffer->Lock(0,slabNTris[ict]*3*sizeof(unsigned short),(void**)&sindexData,0); int ufi = 0; for(int ifi=0; ifiGetNumVertices(); ifi++) if(ill[ifi]) { //svertexData[ufi] = vertexData[ifi]; svertexData.assign(ufi, vertexData[ifi]); ill[ifi] = ufi; ufi++; } else ill[ifi] = 0xffff; for(int trifi=0; trifiUnlock(); sindexBuffer->Unlock(); svertexBuffer->Release(); sindexBuffer->Release(); triClusterStart += slabNTris[ict]; fragmentMeshes[iPiece] = fragMesh; fragmentAttribIndices[iPiece] = iSubset; iPiece++; } indexBuffer->Unlock(); } vertexBuffer->Unlock(); vertexBuffer->Release(); indexBuffer->Release(); delete subsetRanges; } void MeshExploder::clusterTrisKMeans(Tri* triArray, int nTris, int nClusters, int* clusterLenghts) { Tri* centroids = new Tri[nClusters]; std::vector* result = new std::vector[nClusters]; //initial clusters: uniform length for(unsigned int i=0; i> 1; clusterLenghts[i-1] -= clusterLenghts[i-1] >> 1; } } for(int i=nClusters - 1; i >= 0; i--) { if(clusterLenghts[i] == 0) { clusterLenghts[i] = clusterLenghts[i+1] >> 1; clusterLenghts[i+1] -= clusterLenghts[i+1] >> 1; } } } delete [] centroids; delete [] result; } void MeshExploder::saveFragMeshes() { for(int i=0; iGetFVF() & D3DFVF_TEXCOUNT_MASK) / D3DFVF_TEX1 - 1; HRESULT hr = D3DXUVAtlasCreate( fragmentMeshes[i], // LPD3DXMESH pMesh, 0, // UINT dwMaxChartNumber, 1.0f, // FLOAT fMaxStretch, atlasSize - 4, // UINT dwWidth, atlasSize - 4, // UINT dwHeight, 2.0f, // FLOAT fGutter, atlasIndex, // DWORD dwTextureIndex, NULL, // CONST DWORD * pdwAdjacency, NULL, // CONST CHAR * pcFalseEdges, NULL, // FLOAT * pfIMTArray, NULL, // LPD3DXUVATLASCB pCallback, 0.001f, // FLOAT fCallbackFrequency, NULL, // LPVOID pUserContent, 0, // options &tempMesh, // LPD3DXMESH * ppMeshOut, NULL, // LPD3DXBUFFER * ppFacePartitioning, NULL, // LPD3DXBUFFER * ppVertexRemapArray, &maxStretchApplied, // FLOAT * pfMaxStretchOut, &nCharts // UINT * pdwNumChartsOut ); if(hr == S_OK) { //forget the old mesh fragmentMeshes[i]->Release(); fragmentMeshes[i] = tempMesh; } else { MessageBoxA( NULL, "Sorry!", "Impossible to create UVatlas, please increase PRM resolution!", MB_OK); } LPDIRECT3DVERTEXBUFFER9 vertexBuffer; fragmentMeshes[i]->GetVertexBuffer(&vertexBuffer); FlexVertexArray vertexData(fragmentMeshes[i]->GetNumBytesPerVertex()); D3DVERTEXELEMENT9 elem[64]; fragmentMeshes[i]->GetDeclaration(elem); vertexData.setFormat(elem); vertexBuffer->Lock(0,fragmentMeshes[i]->GetNumVertices()*fragmentMeshes[i]->GetNumBytesPerVertex(),vertexData.getDataPointerReference(),0); for(unsigned int u=0; u < fragmentMeshes[i]->GetNumVertices(); u++ ) vertexData[u].tex(atlasIndex) = (vertexData[u].tex(atlasIndex) * (atlasSize - 4) + D3DXVECTOR2(2.0,2.0)) / (float)atlasSize; vertexBuffer->Unlock(); vertexBuffer->Release(); } } void MeshExploder::merge() { int sumVertices=0; int sumFaces=0; for(int i=0; iGetNumVertices(); sumFaces += fragmentMeshes[i]->GetNumFaces(); } composedMaterials = new D3DXMATERIAL[nPieces]; composedShaders = new D3DXEFFECTINSTANCE[nPieces]; composedMaterialNames = new wchar_t*[nPieces]; for(int t=0; tGetFVF(), device, &composedMesh); LPDIRECT3DVERTEXBUFFER9 composedVertexBuffer; composedMesh->GetVertexBuffer(&composedVertexBuffer); FlexVertexArray composedVertexData(composedMesh->GetNumBytesPerVertex()); D3DVERTEXELEMENT9 elem[64]; composedMesh->GetDeclaration(elem); composedVertexData.setFormat(elem); composedVertexBuffer->Lock(0,composedMesh->GetNumVertices()*composedMesh->GetNumBytesPerVertex(),composedVertexData.getDataPointerReference(),0); LPDIRECT3DINDEXBUFFER9 composedIndexBuffer; composedMesh->GetIndexBuffer(&composedIndexBuffer); unsigned short* composedIndexData; composedIndexBuffer->Lock(0, composedMesh->GetNumFaces()*3*sizeof(unsigned short), (void**)&composedIndexData,0); DWORD* composedAttributeData; composedMesh->LockAttributeBuffer(0, &composedAttributeData); int vertexOffset = 0; int faceOffset = 0; for(int f=0; fGetVertexBuffer(&fragmentVertexBuffer); FlexVertexArray fragmentVertexData(fragmentMeshes[f]->GetNumBytesPerVertex()); fragmentVertexBuffer->Lock(0,fragmentMeshes[f]->GetNumVertices()*fragmentMeshes[f]->GetNumBytesPerVertex(),fragmentVertexData.getDataPointerReference(),0); LPDIRECT3DINDEXBUFFER9 fragmentIndexBuffer; fragmentMeshes[f]->GetIndexBuffer(&fragmentIndexBuffer); unsigned short* fragmentIndexData; fragmentIndexBuffer->Lock(0, fragmentMeshes[f]->GetNumFaces()*3*sizeof(unsigned short), (void**)&fragmentIndexData,0); for(int iv=0; ivGetNumVertices(); iv++) composedVertexData.assign(iv + vertexOffset, fragmentVertexData[iv]); //composedVertexData[iv + vertexOffset] = fragmentVertexData[iv]; for(int ic=0; icGetNumFaces(); ic++) { composedAttributeData[ic + faceOffset] = f; composedIndexData[(ic + faceOffset) * 3] = fragmentIndexData[ic * 3] + vertexOffset; composedIndexData[(ic + faceOffset) * 3 + 1] = fragmentIndexData[ic * 3 + 1] + vertexOffset; composedIndexData[(ic + faceOffset) * 3 + 2] = fragmentIndexData[ic * 3 + 2] + vertexOffset; } fragmentVertexBuffer->Unlock(); fragmentVertexBuffer->Release(); fragmentIndexBuffer->Unlock(); fragmentIndexBuffer->Release(); vertexOffset += fragmentMeshes[f]->GetNumVertices(); faceOffset += fragmentMeshes[f]->GetNumFaces(); } composedMesh->UnlockAttributeBuffer(); composedVertexBuffer->Unlock(); composedVertexBuffer->Release(); composedIndexBuffer->Unlock(); composedIndexBuffer->Release(); } void MeshExploder::saveComposedMesh(LPCSTR name) { char sname[256]; sprintf(sname, "processedMeshes/%s.x", name); HRESULT hr = D3DXSaveMeshToX(L::l+sname, //LPCTSTR pFilename, composedMesh, //LPD3DXMESH pMesh, NULL, //CONST DWORD * pAdjacency, composedMaterials, //CONST D3DXMATERIAL * pMaterials, composedShaders, //CONST D3DXEFFECTINSTANCE * pEffectInstances, nPieces, //DWORD NumMaterials, D3DXF_FILEFORMAT_TEXT //DWORD Format ); } void MeshExploder::saveComposedMeshToOgreXML(LPCSTR name) { char sname[256]; sprintf(sname, "processedMeshes/%s.mesh.xml", name); std::ofstream f(sname); XmlStream xml(f); DWORD mfvf = composedMesh->GetFVF(); unsigned int nTexCoords = ( mfvf & D3DFVF_TEXCOUNT_MASK) / D3DFVF_TEX1; xml << tag("mesh"); xml << tag("sharedgeometry") << attr("vertexcount") << composedMesh->GetNumVertices(); xml << tag("vertexbuffer"); if(mfvf & D3DFVF_XYZ) xml << attr("positions") << "true"; else xml << attr("positions") << "false"; if(mfvf & D3DFVF_NORMAL) xml << attr("normals") << "true"; else xml << attr("normals") << "false"; if(mfvf & D3DFVF_DIFFUSE) xml << attr("colours_diffuse") << "true"; else xml << attr("colours_diffuse") << "false"; if(mfvf & D3DFVF_SPECULAR) xml << attr("colours_specular") << "true"; else xml << attr("colours_specular") << "false"; xml << attr("texture_coords") << nTexCoords; LPDIRECT3DVERTEXBUFFER9 composedVertexBuffer; composedMesh->GetVertexBuffer(&composedVertexBuffer); FlexVertexArray composedVertexData(composedMesh->GetNumBytesPerVertex()); D3DVERTEXELEMENT9 elem[64]; composedMesh->GetDeclaration(elem); composedVertexData.setFormat(elem); composedVertexBuffer->Lock(0,composedMesh->GetNumVertices()*composedMesh->GetNumBytesPerVertex(),composedVertexData.getDataPointerReference(),0); LPDIRECT3DINDEXBUFFER9 composedIndexBuffer; composedMesh->GetIndexBuffer(&composedIndexBuffer); unsigned short* composedIndexData; composedIndexBuffer->Lock(0, composedMesh->GetNumFaces()*3*sizeof(unsigned short), (void**)&composedIndexData,0); DWORD* composedAttributeData; composedMesh->LockAttributeBuffer(0, &composedAttributeData); for(int xvi = 0; xvi < composedMesh->GetNumVertices(); xvi++) { xml << tag("vertex"); if(mfvf & D3DFVF_XYZ) { xml << tag("position"); xml << attr("x") << composedVertexData[xvi].pos().x; xml << attr("y") << composedVertexData[xvi].pos().y; xml << attr("z") << composedVertexData[xvi].pos().z; xml << endtag(); } if(mfvf & D3DFVF_NORMAL) { xml << tag("normal"); xml << attr("x") << composedVertexData[xvi].normal().x; xml << attr("y") << composedVertexData[xvi].normal().y; xml << attr("z") << composedVertexData[xvi].normal().z; xml << endtag(); } if(mfvf & D3DFVF_DIFFUSE) { char colval[256]; D3DCOLOR dc = composedVertexData[xvi].diffuse(); unsigned char* pdc = (unsigned char*)&dc; sprintf(colval, "%f %f %f %f", pdc[3], pdc[0], pdc[1], pdc[2] ); xml << tag("colours_diffuse"); xml << attr("value") << colval; xml << endtag(); } if(mfvf & D3DFVF_SPECULAR) { char colval[256]; D3DCOLOR dc = composedVertexData[xvi].specular(); unsigned char* pdc = (unsigned char*)&dc; sprintf(colval, "%f %f %f %f", pdc[3], pdc[0], pdc[1], pdc[2] ); xml << tag("colours_specular"); xml << attr("value") << colval; xml << endtag(); } for(int taxi=0; taxiGetNumFaces(); for(int ic = 0; ic < fragmentMeshes[xai]->GetNumFaces(); ic++) { xml << tag("face") << attr("v1") << composedIndexData[(ic + faceOffset) * 3] << attr("v2") << composedIndexData[(ic + faceOffset) * 3 + 1] << attr("v3") << composedIndexData[(ic + faceOffset) * 3 + 2]; xml << endtag(); } faceOffset += fragmentMeshes[xai]->GetNumFaces(); xml << endtag(); xml << endtag(); } xml << endtag(); // submeshes xml << tag("submeshnames"); xml << endtag(); composedMesh->UnlockAttributeBuffer(); composedVertexBuffer->Unlock(); composedVertexBuffer->Release(); composedIndexBuffer->Unlock(); composedIndexBuffer->Release(); }