void ProgressiveMesh(std::vector<float3> &vert, std::vector<tridata> &tri, std::vector<int> &map, std::vector<int> &permutation) { AddVertex(vert); // put input data into our data structures AddFaces(tri); ComputeAllEdgeCollapseCosts(); // cache all edge collapse costs permutation.resize(vertices.size()); // allocate space map.resize(vertices.size()); // allocate space // reduce the object down to nothing: while (vertices.size() > 0) { // get the next vertex to collapse Vertex *mn = MinimumCostEdge(); // keep track of this vertex, i.e. the collapse ordering permutation[mn->id] = vertices.size() - 1; // keep track of vertex to which we collapse to map[vertices.size() - 1] = (mn->collapse) ? mn->collapse->id : -1; // Collapse this edge Collapse(mn,mn->collapse); } // reorder the map Array based on the collapse ordering for (unsigned int i = 0; i<map.size(); i++) { map[i] = (map[i]==-1)?0:permutation[map[i]]; } // The caller of this function should reorder their vertices // according to the returned "permutation". }
void Chopper::chop( Array< Vector3 > & vert, Array< Triangle > &tri, Array< int > &map, Array< int > &permutation ) { AddVertex(vert); // put input data into our data structures AddFaces(tri); ComputeAllEdgeCollapseCosts(); // cache all edge collapse costs permutation.allocate(s_Vertices.size()); // allocate space map.allocate(s_Vertices.size()); // allocate space // reduce the object down to nothing: while(s_Vertices.size() > 0) { // get the next vertex to collapse Vertex *mn = MinimumCostEdge(); // keep track of this vertex, i.e. the collapse ordering permutation[mn->id]=s_Vertices.size()-1; // keep track of vertex to which we collapse to map[s_Vertices.size()-1] = (mn->collapse)?mn->collapse->id:-1; // Collapse this edge Collapse(mn,mn->collapse); } // reorder the map list based on the collapse ordering for(int i=0;i<map.size();i++) { map[i] = (map[i]==-1)?0:permutation[map[i]]; } // The caller of this function should reorder their vertices // according to the returned "permutation". }
void Pair::Merge (Pair *pair) { U32 SetCtx = 0; FacePtrSet *fset = pair->GetFaces(); Face *pFace = (Face*)fset->Begin(SetCtx); while(pFace) { pFace->ReplacePair (pair, this); pFace = (Face*)fset->Next(SetCtx); } AddFaces (fset); }
void IFXNeighborResController::IncreaseResolution() { // Undo distal merges IFXDistalEdgeMerge* pMerge = m_distalMerges[m_resolution]; while (pMerge) { ApplyEdgeMerge(pMerge); pMerge = pMerge->m_pNext; } ++m_resolution; for(I32 meshIndex = m_numMeshes - 1; meshIndex >= 0; meshIndex--) { U32* syncTable = m_pUpdatesGroup->GetSyncTable(meshIndex); U32 maxLocalRes = m_pUpdatesGroup->GetUpdates(meshIndex)->numResChanges; U32 localRes = m_pMeshStates[meshIndex].resolutionChangeIndex; if (localRes < maxLocalRes && m_resolution > syncTable[localRes]) { AddFaces(meshIndex); } } }
void IFXNeighborResController::DetermineCollapsedEdges() { IFXTRACE_GENERIC(L"IFX Neighbor res:\n"); // Reduce the mesh resolution U32 resolution; for (resolution = m_pUpdatesGroup->GetMaxResolution() - 1; (I32)resolution >= 0; --resolution) { IFXTRACE_GENERIC(L"%d%c", resolution, (resolution % 10) ? ' ' : '\n' ); // First pass: // Determine which faces are deleted by this resolution change. // Express as a range: // m_pMeshStates[i].numFaces => deleted < m_pMeshStates[i].prevNumFaces // U32 i; for(i = 0; i < m_numMeshes; i++) { U32* syncTable = m_pUpdatesGroup->GetSyncTable(i); U32 localRes = m_pMeshStates[i].resolutionChangeIndex; if (localRes > 0 && resolution <= syncTable[localRes-1]) { DecrementFaceCount(i); } else { // no faces deleted in this mesh; invalidate range m_pMeshStates[i].prevNumFaces = 0; } } // Analyze modified faces for merged edges for(i = 0; i < m_numMeshes; i++) { U32* syncTable = m_pUpdatesGroup->GetSyncTable(i); U32 localRes = m_pMeshStates[i].resolutionChangeIndex; if (localRes > 0 && resolution <= syncTable[localRes-1]) { AnalyzeMergingEdges(i, resolution); } } // Mark duplicate faces and determine the collapse edges // by analyzing the unique faces. Duplicate faces must be // marked in the reverse order that faces are removed. Faces // are removed from highest face index to lowest, from mesh 0 // to mesh n. Thus duplicate faces are marked from lowest face // face index to highest, from mesh n to 0. for(I32 j = m_numMeshes - 1; j >= 0; j--) { U32* syncTable = m_pUpdatesGroup->GetSyncTable(j); U32 localRes = m_pMeshStates[j].resolutionChangeIndex; if (localRes > 0 && resolution <= syncTable[localRes-1]) { MarkCollapseEdgesInMesh(j); } } // Remove deleted edges from edge map for(i = 0; i < m_numMeshes; i++) { U32* syncTable = m_pUpdatesGroup->GetSyncTable(i); U32 localRes = m_pMeshStates[i].resolutionChangeIndex; if (localRes > 0 && resolution <= syncTable[localRes-1]) { UpdateEdgesInMap(i); } } // Third pass: // Actually remove faces from connectivity for(i = 0; i < m_numMeshes; i++) { U32* syncTable = m_pUpdatesGroup->GetSyncTable(i); U32 localRes = m_pMeshStates[i].resolutionChangeIndex; if (localRes > 0 && resolution <= syncTable[localRes-1]) { AltRemoveFaces(i); } } // Apply distal merges IFXDistalEdgeMerge* pMerge = m_distalMerges[resolution]; while (pMerge) { ApplyEdgeMerge(pMerge); pMerge = pMerge->m_pNext; } m_pCLODManager->SetResolution(resolution); } // Restore the mesh resolution for (resolution = 1; resolution <= m_pUpdatesGroup->GetMaxResolution(); ++resolution) { // Undo distal merges IFXDistalEdgeMerge* pMerge = m_distalMerges[resolution-1]; while (pMerge) { ApplyEdgeMerge(pMerge); pMerge = pMerge->m_pNext; } for(I32 i = m_numMeshes - 1; i >= 0; i--) { U32* syncTable = m_pUpdatesGroup->GetSyncTable(i); U32 maxLocalRes = m_pUpdatesGroup->GetUpdates(i)->numResChanges; U32 localRes = m_pMeshStates[i].resolutionChangeIndex; if (localRes < maxLocalRes && resolution > syncTable[localRes]) { AddFaces(i); } } m_pCLODManager->SetResolution(resolution); } }