Ejemplo n.º 1
0
int MeshGeometry::project_out_zero_dim() {
    if (m_dim == 2) return -1;
    assert(m_dim == 3);
    const size_t num_vertices = get_num_vertices();
    MatrixFr vertices(num_vertices, m_dim);
    std::copy(m_vertices.data(), m_vertices.data() + m_vertices.size(),
            vertices.data());
    Vector3F max_coord = vertices.colwise().maxCoeff();
    Vector3F min_coord = vertices.colwise().minCoeff();

    int zero_dim = -1;
    for (size_t i=0; i<3; i++) {
        if (max_coord[i] == min_coord[i]) {
            zero_dim = i;
            break;
        }
    }

    if (zero_dim == -1) return -1;
    m_dim = 2;
    m_vertices.resize(num_vertices * 2);
    if (zero_dim == 0) {
        // Drop X
        //std::cout << "Removing X component" << std::endl;
        for (size_t i=0; i<num_vertices; i++) {
            m_vertices[i*2  ] = vertices.row(i)[1];
            m_vertices[i*2+1] = vertices.row(i)[2];
        }
    } else if (zero_dim == 2) {
        // Drop Z
        //std::cout << "Removing Z component" << std::endl;
        for (size_t i=0; i<num_vertices; i++) {
            m_vertices[i*2  ] = vertices.row(i)[0];
            m_vertices[i*2+1] = vertices.row(i)[1];
        }
    } else {
        // Drop Y
        //std::cout << "Removing Y component" << std::endl;
        for (size_t i=0; i<num_vertices; i++) {
            m_vertices[i*2  ] = vertices.row(i)[0];
            m_vertices[i*2+1] = vertices.row(i)[2];
        }
    }
    return zero_dim;
}
Ejemplo n.º 2
0
size_t SurfTrack::add_vertex( const Vec3d& new_vertex_position, double new_vertex_mass )
{
    size_t new_vertex_index = m_mesh.nondestructive_add_vertex( );
    
    if( new_vertex_index > get_num_vertices() - 1 )
    {
        pm_positions.resize( new_vertex_index  + 1 );
        pm_newpositions.resize( new_vertex_index  + 1 );
        m_masses.resize( new_vertex_index  + 1 );
    }
    
    pm_positions[new_vertex_index] = new_vertex_position;
    pm_newpositions[new_vertex_index] = new_vertex_position;
    m_masses[new_vertex_index] = new_vertex_mass;
    
    if ( m_collision_safety )
    {
        m_broad_phase->add_vertex( new_vertex_index, get_position(new_vertex_index), get_position(new_vertex_index), vertex_is_solid(new_vertex_index) );       
    }
    
    return new_vertex_index;
}
Ejemplo n.º 3
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();
    }
    
}
Ejemplo n.º 4
0
// Johnson's
std::vector<std::vector<std::vector<std::pair<unsigned long, double>>>>
 Algorithms::Johnsons(Graph& graph){
  auto graphx = std::vector<std::vector<std::pair<unsigned long, double>>>();
  auto num = graph.get_num_vertices();
  auto vert = std::vector<std::pair<unsigned long, double>>();
  for(auto& lis: graph.list){
    graphx.push_back(lis);
  }
  for(int i = 0; i< num; i++){
    vert.push_back(std::pair<unsigned long, double>(i,0));
  }
  graphx.push_back(vert);
  
  auto tempg = Graph(graphx);
  unsigned long start_index = num;

  num = num + 1;
  std::vector<double> distance = std::vector<double>(num);
  std::vector<unsigned long> predecessor = std::vector<unsigned long>(num);
  //initalize values
  for(int i = 0; i< num; i++) {
    distance[i] = std::numeric_limits<double>::infinity();
    predecessor[i] = 0; // 
    
    }

  distance[start_index] = 0;
  //compute optimal path
  for(int index = 0; index < num; index++) {
    for(int i = 0; i< num; i++) {
    std::vector<std::pair<unsigned long, double>> row = tempg.list[i]; 
      for(auto& pair: row) {
        if(distance[i] + pair.second < distance[pair.first]) {
          distance[pair.first] = distance[i] + pair.second;
          predecessor[pair.first] = i;
        }
      }
    }
  }
  //check for negative cycles
  for(int i = 0; i < num; i++){
    std::vector<std::pair<unsigned long, double>> rows = tempg.list[i];
    for(auto& pairs: rows) {
      if(distance[i] + pairs.second < distance[pairs.first]) {
        throw Algorithms_Exception("Contains Negative Cycles");
      }
    }
  }

  auto h = std::vector<double>(num);
  //compute h[] distances
  h[num-1] = 0;
  for(int i = 0 ; i < num-1 ; i++){
    std::vector<std::pair<unsigned long, double>> path;
    unsigned long current = i;
    path.push_back(std::pair<unsigned long, double>(current, distance[current]));
    do {
      current = predecessor[current];
      auto newpair = std::pair<unsigned long, double>(current, distance[current]);
      path.push_back(newpair);
    } while(current != num-1);

    std::reverse(path.begin(), path.end());
    double total = 0;
    for(auto& edge: path){
      total += edge.second;
    }
    h[i] = total;
  }

  //construct graph with with new weights
  auto newgraph = graph.list;
  for(int i = 0 ; i< newgraph.size(); i++){
    auto temp = newgraph[i];
    auto newedges = std::vector<std::pair<unsigned long, double>>(); 
    for(int j = 0; j < temp.size(); j++){
      std::pair<unsigned long, double> temppair = temp[j];
      double value = (temppair.second + h[i] - h[temppair.first]);
      newedges.push_back(std::pair<unsigned long, double>(temppair.first,value));
    }
    newgraph[i] = newedges;
  }

  auto finalgraph = Graph(newgraph);
  auto length = finalgraph.get_num_vertices();
  auto final_weight = std::vector<std::vector<std::vector<std::pair<unsigned
    long, double>>>>(length);
  for(int i = 0; i < length ; i++){
    final_weight[i] = std::vector<std::vector<std::pair<unsigned long,
      double>>>(length);
  }

  //compute paths between all nodes
  for(int i = 0; i< length; i++){
    for(int j = 0 ; j< length; j++){
      if(i == j){
        auto tem = std::vector<std::pair<unsigned long, double>>();
        tem.push_back(std::pair<unsigned long, double>(0,0));
        final_weight[i][j] = tem;
      }else if(i>j){
        
        auto xyz = final_weight[j][i];
        std::reverse(xyz.begin(), xyz.end());
        final_weight[i][j] = xyz;

      }else{
        try{
          final_weight[i][j] = Dijkstras(finalgraph,i,j);
        }catch(Algorithms_Exception){
          final_weight[i][j] = std::vector<std::pair<unsigned long, double>>();
        }
      }
    }
  }

  return final_weight;
}
Ejemplo n.º 5
0
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();
    }

}
Ejemplo n.º 6
0
	void operator ()(VcacheMesh &vcache_mesh, submesh_id_t const &submesh_id, ProgressCallback & progress_callback, bool const reorder_vertices = true)
	{
		//////// prerequisites
		//////////////////////

		has_best_triangle = false;
		best_triangle = 0;

		optimized_tris.clear();
		lru_cache.clear();

		vtx_data.resize(get_num_vertices(vcache_mesh, submesh_id));
		tri_data.resize(get_num_triangles(vcache_mesh, submesh_id));

		// fetch the triangle data and put it in the internal vector
		// also fill the tri_indices_using vectors in the process
		{
			for (triangle_index_t tri_index = 0; tri_index < get_num_triangles(vcache_mesh, submesh_id); ++tri_index)
			{
				triangle_t triangle = get_triangle(vcache_mesh, submesh_id, tri_index);

				for (int i = 0; i < 3; ++i)
				{
					tri_data[tri_index].indices[i] = triangle[i];
					vtx_data[triangle[i]].tri_indices_using.insert(tri_index);
				}
			}
		}


		//////// optimize triangles
		///////////////////////////

		// calculate vertex and triangle scores
		{
			for (vertex_index_t vtx_index = 0; vtx_index < get_num_vertices(vcache_mesh, submesh_id); ++vtx_index)
			{
				vertex_data &vtx = vtx_data[vtx_index];
				vtx.score = find_vertex_score(vtx); // calculate the vertex score

				for (typename tri_indices_using_t::const_iterator tri_idx_iter = vtx.tri_indices_using.begin(); tri_idx_iter != vtx.tri_indices_using.end(); ++tri_idx_iter)
					tri_data[*tri_idx_iter].score += vtx.score; // add the vertex score to the triangles using this vertex
			}
		}

		// tell the progress callback the maximum progress value
		set_maximum_optimizing_triangles_progress(progress_callback, tri_data.size());

		/*
		the actual optimization step; reorder triangles by repeatedly finding a "best" triangle
		(= look at all the vertices in the LRU cache, and from all the triangles using these vertices,
		find the one with the highest score, remove this one from the vertices and put it in
		optimized_tris, and then find the next best triangle etc.)
		*/
		{
			size_t progress_counter = 0;
			while (optimized_tris.size() < tri_data.size())
			{
				push_best_triangle();
				++progress_counter;
				set_current_optimizing_triangles_progress(progress_callback, progress_counter);
			}
		}


		//////// reoder vertices
		////////////////////////

		if (reorder_vertices)
		{
			// even though *vertices* are reordered, reordering happens across *triangles*
			set_maximum_reordering_vertices_progress(progress_callback, tri_data.size());

			// get the vertices from the mesh
			std::vector < vertex_t > src_vertices;
			src_vertices.resize(vtx_data.size());
			for (vertex_index_t vtx_index = 0; vtx_index < vtx_data.size(); ++vtx_index)
				src_vertices[vtx_index] = get_vertex(vcache_mesh, submesh_id, vtx_index);

			// create and initialize the permutation sequence;
			// this sequence will be used for updating the triangle vertex indices later
			std::vector < std::pair < bool, vertex_index_t > > permutation;
			permutation.resize(vtx_data.size());
			std::fill(permutation.begin(), permutation.end(), std::pair < bool, vertex_index_t > (false, 0));

			/*
			reordering is done according to the order of access
			"access" refers to the triangles; for example, it makes no sense when the first
			triangle's vertices are at the end of the list of vertices, the second triangle's
			are in the middle etc.
			Instead, the first triangle's vertices should be at the beginning, the second triangle's
			should be right after these etc.
			*/
			size_t progress_counter = 0;
			vertex_index_t mesh_vertex_index = 0;
			for (triangle_index_t tri_index = 0; tri_index < optimized_tris.size(); ++tri_index)
			{
				triangle_data const &tri = tri_data[tri_index];

				// go through all 3 indices of each triangle,
				// and if it wasn't reordered, do so
				for (int i = 0; i < 3; ++i)
				{
					vertex_index_t vtx_index = tri.indices[i];
					if (!permutation[vtx_index].first) // first false -> was not reordered yet
					{
						// check for overflow; it should never happen, since
						// each vertex is reordered only once
						assert(mesh_vertex_index < src_vertices.size());

						// mark the vertex as reordered and store its new index
						permutation[vtx_index].first = true;
						permutation[vtx_index].second = mesh_vertex_index;

						// write the vertex at its new position in the mesh
						set_vertex(vcache_mesh, submesh_id, mesh_vertex_index, src_vertices[vtx_index]);
						++mesh_vertex_index;
					}
				}

				++progress_counter;
				set_current_reordering_vertices_progress(progress_callback, progress_counter);
			}

			// After the vertices have been reodered, the triangle vertex indices need to be updated
			for (triangle_index_t tri_index = 0; tri_index < optimized_tris.size(); ++tri_index)
			{
				triangle_data &tri = optimized_tris[tri_index];
				for (int i = 0; i < 3; ++i)
					tri.indices[i] = permutation[tri.indices[i]].second;
			}
		}

		// finally, store the contents of optimized_tris in the mesh
		{
			for (triangle_index_t tri_index = 0; tri_index < optimized_tris.size(); ++tri_index)
			{
				triangle_data const &tri = optimized_tris[tri_index];
				triangle_t new_triangle = create_new_triangle(
					vcache_mesh,
					tri.indices[0],
					tri.indices[1],
					tri.indices[2]
				);

				set_triangle(vcache_mesh, submesh_id, tri_index, new_triangle);
			}
		}
	}