void CMesh::Simplify(int iVertices2Remain, float fMaxError, bool bConsiderMaterials) { TEdge *pEdge; bool bRemoveSecond; m_bConsiderMaterials = bConsiderMaterials; if (!m_arrCollapses.m_iCount) { InitOutputs(); InitBorders(); } InitEdgeEvaluation(); while (m_hashVertices.m_iCount > iVertices2Remain) { if (!SelectEdge(pEdge, bRemoveSecond, fMaxError)) break; RecordCollapse(pEdge, bRemoveSecond); CollapseEdge(pEdge, bRemoveSecond); // CheckEdges(); } }
//////////////////////////////////////////////////////////////////////// // MergeVertices /// merges two vertices and restructures the adjacent elements. void MergeVertices(Grid& grid, Vertex* v1, Vertex* v2) { // make sure that GRIDOPT_VERTEXCENTRIC_INTERCONNECTION is enabled if(grid.num_edges() && (!grid.option_is_enabled(VRTOPT_STORE_ASSOCIATED_EDGES))) { LOG(" WARNING in MergeVertices: autoenabling VRTOPT_STORE_ASSOCIATED_EDGES\n"); grid.enable_options(VRTOPT_STORE_ASSOCIATED_EDGES); } if(grid.num_faces() && (!grid.option_is_enabled(VRTOPT_STORE_ASSOCIATED_FACES))) { LOG(" WARNING in MergeVertices: autoenabling VRTOPT_STORE_ASSOCIATED_FACES\n"); grid.enable_options(VRTOPT_STORE_ASSOCIATED_FACES); } if(grid.num_volumes() && (!grid.option_is_enabled(VRTOPT_STORE_ASSOCIATED_VOLUMES))) { LOG(" WARNING in MergeVertices: autoenabling VRTOPT_STORE_ASSOCIATED_VOLUMES\n"); grid.enable_options(VRTOPT_STORE_ASSOCIATED_VOLUMES); } Edge* conEdge = grid.get_edge(v1, v2); if(conEdge) { // perform an edge-collapse on conEdge CollapseEdge(grid, conEdge, v1); } else { // notify the grid, that the two vertices will be merged grid.objects_will_be_merged(v1, v1, v2); // we have to check if there are elements that connect the vertices. // We have to delete those. EraseConnectingElements(grid, v1, v2); // create new edges for each edge that is connected with v2. // avoid double edges if(grid.num_edges() > 0) { EdgeDescriptor ed; Grid::AssociatedEdgeIterator iterEnd = grid.associated_edges_end(v2); for(Grid::AssociatedEdgeIterator iter = grid.associated_edges_begin(v2); iter != iterEnd; ++iter) { Edge* e = *iter; if(e->vertex(0) == v2) ed.set_vertices(v1, e->vertex(1)); else ed.set_vertices(e->vertex(0), v1); Edge* existingEdge = grid.get_edge(ed); if(!existingEdge) grid.create_by_cloning(e, ed, e); else grid.objects_will_be_merged(existingEdge, existingEdge, e); } } // create new faces for each face that is connected to v2 // avoid double faces. if(grid.num_faces() > 0) { FaceDescriptor fd; Grid::AssociatedFaceIterator iterEnd = grid.associated_faces_end(v2); for(Grid::AssociatedFaceIterator iter = grid.associated_faces_begin(v2); iter != iterEnd; ++iter) { Face* f = *iter; uint numVrts = f->num_vertices(); fd.set_num_vertices(numVrts); for(uint i = 0; i < numVrts; ++i) { if(f->vertex(i) == v2) fd.set_vertex(i, v1); else fd.set_vertex(i, f->vertex(i)); } Face* existingFace = grid.get_face(fd); if(!existingFace) grid.create_by_cloning(f, fd, f); else grid.objects_will_be_merged(existingFace, existingFace, f); } } // create new volumes for each volume that is connected to v2 if(grid.num_volumes() > 0) { VolumeDescriptor vd; Grid::AssociatedVolumeIterator iterEnd = grid.associated_volumes_end(v2); for(Grid::AssociatedVolumeIterator iter = grid.associated_volumes_begin(v2); iter != iterEnd; ++iter) { Volume* v = *iter; uint numVrts = v->num_vertices(); vd.set_num_vertices(numVrts); for(uint i = 0; i < numVrts; ++i) { if(v->vertex(i) == v2) vd.set_vertex(i, v1); else vd.set_vertex(i, v->vertex(i)); } //assert(!"avoid double volumes! implement FindVolume and use it here."); grid.create_by_cloning(v, vd, v); } } // new elements have been created. remove the old ones. // it is sufficient to simply erase v2. grid.erase(v2); } }