void SurfTrack::remove_vertex( size_t vertex_index ) { m_mesh.nondestructive_remove_vertex( vertex_index ); if ( m_collision_safety ) { m_broad_phase->remove_vertex( vertex_index ); } m_vertex_change_history.push_back( VertexUpdateEvent( VertexUpdateEvent::VERTEX_REMOVE, vertex_index, Vec2st(0,0) ) ); }
void SurfTrack::defrag_mesh( ) { // // First clear deleted vertices from the data stuctures // double start_time = get_time_in_seconds(); // do a quick pass through to see if any vertices have been deleted bool any_deleted = false; for ( size_t i = 0; i < get_num_vertices(); ++i ) { if ( m_mesh.vertex_is_deleted(i) ) { any_deleted = true; break; } } if ( !any_deleted ) { for ( size_t i = 0; i < get_num_vertices(); ++i ) { m_defragged_vertex_map.push_back( Vec2st(i,i) ); } double end_time = get_time_in_seconds(); g_stats.add_to_double( "total_clear_deleted_vertices_time", end_time - start_time ); } else { // Note: We could rebuild the mesh from scratch, rather than adding/removing // triangles, however this function is not a major computational bottleneck. size_t j = 0; std::vector<Vec3st> new_tris = m_mesh.get_triangles(); for ( size_t i = 0; i < get_num_vertices(); ++i ) { if ( !m_mesh.vertex_is_deleted(i) ) { pm_positions[j] = pm_positions[i]; pm_newpositions[j] = pm_newpositions[i]; m_masses[j] = m_masses[i]; m_defragged_vertex_map.push_back( Vec2st(i,j) ); // Now rewire the triangles containting vertex i // copy this, since we'll be changing the original as we go std::vector<size_t> inc_tris = m_mesh.m_vertex_to_triangle_map[i]; for ( size_t t = 0; t < inc_tris.size(); ++t ) { Vec3st triangle = m_mesh.get_triangle( inc_tris[t] ); assert( triangle[0] == i || triangle[1] == i || triangle[2] == i ); if ( triangle[0] == i ) { triangle[0] = j; } if ( triangle[1] == i ) { triangle[1] = j; } if ( triangle[2] == i ) { triangle[2] = j; } remove_triangle(inc_tris[t]); // mark the triangle deleted add_triangle(triangle); // add the updated triangle } ++j; } } pm_positions.resize(j); pm_newpositions.resize(j); m_masses.resize(j); } double end_time = get_time_in_seconds(); g_stats.add_to_double( "total_clear_deleted_vertices_time", end_time - start_time ); // // Now clear deleted triangles from the mesh // m_mesh.set_num_vertices( get_num_vertices() ); m_mesh.clear_deleted_triangles( &m_defragged_triangle_map ); if ( m_collision_safety ) { rebuild_continuous_broad_phase(); } }
void SurfTrack::defrag_mesh( ) { std::vector<Vec2st> old_edges = m_mesh.m_edges; PostDefragInfo info; info.m_defragged_vertex_map.clear(); // // First clear deleted vertices from the data stuctures // // do a quick pass through to see if any vertices have been deleted bool any_deleted = false; for ( size_t i = 0; i < get_num_vertices(); ++i ) { if ( m_mesh.vertex_is_deleted(i) ) { any_deleted = true; break; } } if ( !any_deleted ) { for ( size_t i = 0; i < get_num_vertices(); ++i ) { info.m_defragged_vertex_map.push_back( Vec2st(i,i) ); } } else { // Note: We could rebuild the mesh from scratch, rather than adding/removing // triangles, however this function is not a major computational bottleneck. size_t j = 0; std::vector<Vec3st> new_tris = m_mesh.get_triangles(); for ( size_t i = 0; i < get_num_vertices(); ++i ) { if ( !m_mesh.vertex_is_deleted(i) ) { pm_positions[j] = pm_positions[i]; pm_newpositions[j] = pm_newpositions[i]; m_masses[j] = m_masses[i]; info.m_defragged_vertex_map.push_back( Vec2st(i,j) ); // Now rewire the triangles containting vertex i // copy this, since we'll be changing the original as we go std::vector<size_t> inc_tris = m_mesh.m_vertex_to_triangle_map[i]; for ( size_t t = 0; t < inc_tris.size(); ++t ) { Vec3st triangle = m_mesh.get_triangle( inc_tris[t] ); assert( triangle[0] == i || triangle[1] == i || triangle[2] == i ); if ( triangle[0] == i ) { triangle[0] = j; } if ( triangle[1] == i ) { triangle[1] = j; } if ( triangle[2] == i ) { triangle[2] = j; } remove_triangle(inc_tris[t]); // mark the triangle deleted add_triangle(triangle); // add the updated triangle } ++j; } } pm_positions.resize(j); pm_newpositions.resize(j); m_masses.resize(j); } // // Now clear deleted triangles from the mesh // m_mesh.set_num_vertices( get_num_vertices() ); m_mesh.clear_deleted_triangles( &info.m_defragged_triangle_map ); // // Update data carried on the edges // info.m_defragged_edge_map.clear(); info.m_defragged_edge_map.resize( old_edges.size(), UNINITIALIZED_SIZE_T ); // First update the set of edges to point to new vertex indices for ( size_t i = 0; i < old_edges.size(); ++i ) { for ( int v = 0; v < 2; ++v ) { const size_t old_v = old_edges[i][v]; size_t new_v = old_v; for ( size_t j = 0; j < info.m_defragged_vertex_map.size(); ++j ) { if ( info.m_defragged_vertex_map[j][0] == old_v ) { new_v = info.m_defragged_vertex_map[j][1]; assert( !m_mesh.vertex_is_deleted(new_v) ); break; } } old_edges[i][v] = new_v; } } // Now use this modified set of edges to find where the edge data maps to for ( unsigned int i = 0; i < old_edges.size(); ++i ) { if ( old_edges[i][0] == old_edges[i][1] ) { continue; } size_t new_edge_index = m_mesh.get_edge_index( old_edges[i][0], old_edges[i][1] ); // This edge has disappeared from the mesh. This can occur when trimming non-manifold flaps. if ( new_edge_index == m_mesh.m_edges.size() ) { continue; } info.m_defragged_edge_map[i] = new_edge_index; assert( new_edge_index < m_mesh.m_edges.size() ); // If the internal storage of the edge flipped, flip it back to original if ( old_edges[i][0] != m_mesh.m_edges[new_edge_index][0] ) { assert( old_edges[i][1] == m_mesh.m_edges[new_edge_index][0] ); assert( old_edges[i][0] == m_mesh.m_edges[new_edge_index][1] ); swap( m_mesh.m_edges[new_edge_index][0], m_mesh.m_edges[new_edge_index][1] ); assert( old_edges[i][0] == m_mesh.m_edges[new_edge_index][0] ); assert( old_edges[i][1] == m_mesh.m_edges[new_edge_index][1] ); } } for ( size_t i = 0; i < m_observers.size(); ++i ) { m_observers[i]->operationOccurred(*this, info); } if ( m_collision_safety ) { rebuild_continuous_broad_phase(); } }