void create_circle( std::vector<Vec3d>& verts, std::vector<Vec3st>& tris, std::vector<double>& masses, const Vec3d& centre, double radius, size_t nx ) { Vec3d low = centre - Vec3d( radius, 0.0, radius ); double dx = 2.0 * radius / (double)nx; Array2<Vec3d> grid_points; grid_points.resize(nx, nx); for ( size_t i = 0; i < nx; ++i ) { for ( size_t j = 0; j < nx; ++j ) { grid_points(i,j) = low + dx * Vec3d( i, 0, j ); verts.push_back( low + dx * Vec3d( i, 0, j ) ); } } // cells for ( size_t i = 0; i < nx-1; ++i ) { for ( size_t j = 0; j < nx-1; ++j ) { size_t a = i + nx*j; size_t b = i+1 + nx*j; size_t c = i+1 + nx*(j+1); size_t d = i + nx*(j+1); if ( ( dist( verts[a], centre ) < radius ) && ( dist( verts[b], centre ) < radius ) && ( dist( verts[d], centre ) < radius ) ) { tris.push_back( Vec3st( a, b, d ) ); } if ( ( dist( verts[b], centre ) < radius ) && ( dist( verts[c], centre ) < radius ) && ( dist( verts[d], centre ) < radius ) ) { tris.push_back( Vec3st( b, c, d ) ); } } } masses.clear(); masses.resize( verts.size(), 1.0 ); NonDestructiveTriMesh temp_tri_mesh; temp_tri_mesh.set_num_vertices( verts.size() ); for ( size_t i = 0; i < tris.size(); ++i ) { temp_tri_mesh.add_triangle( tris[i] ); } }
void create_sheet( std::vector<Vec3d>& verts, std::vector<Vec3st>& tris, const Vec3d& low_corner, double dx, size_t nx, size_t ny ) { for(size_t i = 0; i < ny; i++) { for(size_t j = 0; j < nx; j++) { // plane normal is pointing in +y direction Vec3d offset; offset[0] = dx*j; //width*((double)j/nx); offset[1] = 0.0; offset[2] = dx*i; //width*((double)i/ny); verts.push_back( low_corner + offset ); rest_vertices.push_back( Vec2d(offset[0], offset[2]) ); } } for(size_t i = 0; i < ny-1; i++) { for(size_t j = 0; j < nx-1; j++) { size_t idx = i*(nx)+j; tris.push_back(Vec3st(idx, idx+(nx), idx+1)); tris.push_back(Vec3st(idx+1, idx+(nx), idx+(nx)+1)); } } }
void AccelerationGrid::add_element(size_t idx, const Vec3d& xmin, const Vec3d& xmax) { if(m_elementidxs.size() <= idx) { m_elementidxs.resize(idx+1); m_elementxmins.resize(idx+1); m_elementxmaxs.resize(idx+1); m_elementquery.resize(idx+1); } m_elementxmins[idx] = xmin; m_elementxmaxs[idx] = xmax; m_elementquery[idx] = 0; Vec3i xmini, xmaxi; boundstoindices(xmin, xmax, xmini, xmaxi); for(int i = xmini[0]; i <= xmaxi[0]; i++) { for(int j = xmini[1]; j <= xmaxi[1]; j++) { for(int k = xmini[2]; k <= xmaxi[2]; k++) { std::vector<size_t>*& cell = m_cells(i, j, k); if(!cell) cell = new std::vector<size_t>(); cell->push_back(idx); m_elementidxs[idx].push_back(Vec3st(i, j, k)); } } } }
void append_mesh( std::vector<Vec3st>& tris, std::vector<Vec3d>& verts, std::vector<double>& masses, const std::vector<Vec3st>& new_tris, const std::vector<Vec3d>& new_verts, const std::vector<double>& new_masses ) { size_t old_num_verts = verts.size(); for ( size_t i = 0; i < new_verts.size(); ++i ) { verts.push_back( new_verts[i] ); } for ( size_t i = 0; i < new_tris.size(); ++i ) { tris.push_back( new_tris[i] + Vec3st(old_num_verts) ); } for ( size_t i = 0; i < new_masses.size(); ++i ) { masses.push_back( new_masses[i] ); } }
void create_curved_sheet( std::vector<Vec3d>& verts, std::vector<Vec3st>& tris, const Vec3d& low_corner, double dx, size_t nx, size_t ny ) { std::cout << "sheet: " << low_corner << ", " << dx << std::endl; std::cout << "resolution: " << nx << "x" << ny << std::endl; std::cout << "dimensions: " << dx*nx << "x" << dx*ny << std::endl; unsigned int num_curves = 4; double amplitude = dx*nx / 20.0; for(size_t i = 0; i < ny; i++) { for(size_t j = 0; j < nx; j++) { double theta = 2.0 * M_PI * (double)j / (double)nx * (double)num_curves; // plane normal is pointing in +y direction double x = dx*j; //width*((double)j/nx); double z = dx*i; //width*((double)i/ny); double y = 1e-3*z + amplitude * sin( theta ); verts.push_back(Vec3d(x,y,z) + low_corner); } } for(size_t i = 0; i < ny-1; i++) { for(size_t j = 0; j < nx-1; j++) { size_t idx = i*(nx)+j; tris.push_back(Vec3st(idx, idx+(nx), idx+1)); tris.push_back(Vec3st(idx+1, idx+(nx), idx+(nx)+1)); } } }
bool read_objfile(NonDestructiveTriMesh &mesh, std::vector<Vec3d> &x, const char *filename_format, ...) { #ifdef _MSC_VER va_list ap; va_start(ap, filename_format); int len=_vscprintf(filename_format, ap) // _vscprintf doesn't count +1; // terminating '\0' char *filename=new char[len]; vsprintf(filename, filename_format, ap); std::ifstream input(filename, std::ifstream::binary); delete[] filename; va_end(ap); #else va_list ap; va_start(ap, filename_format); char *filename; vasprintf(&filename, filename_format, ap); std::ifstream input(filename, std::ifstream::binary); std::free(filename); va_end(ap); #endif if(!input.good()) return false; x.clear(); mesh.clear(); char line[LINESIZE]; std::vector<int> vertex_list; while(input.good()){ input.getline(line, LINESIZE); switch(line[0]){ case 'v': // vertex data if(line[1]==' '){ Vec3d new_vertex; std::sscanf(line+2, "%lf %lf %lf", &new_vertex[0], &new_vertex[1], &new_vertex[2]); x.push_back(new_vertex); } break; case 'f': // face data if(line[1]==' '){ read_face_list(line+2, vertex_list); for(int j=0; j<(int)vertex_list.size()-2; ++j) mesh.add_triangle( Vec3st(vertex_list[0], vertex_list[j+1], vertex_list[j+2]) ); } break; } } return true; }
bool read_binary_file( NonDestructiveTriMesh &mesh, std::vector<Vec3d> &x, std::vector<double> &masses, double& curr_t, const char *filename_format, ...) { va_list ap; va_start(ap, filename_format); bifstream infile( filename_format, ap ); va_end(ap); assert( infile.good() ); infile.read_endianity(); infile >> curr_t; unsigned int nverts; infile >> nverts; x.resize( nverts ); for ( unsigned int i = 0; i < nverts; ++i ) { infile >> x[i][0]; infile >> x[i][1]; infile >> x[i][2]; mesh.add_vertex(); } masses.resize( nverts ); for ( unsigned int i = 0; i < nverts; ++i ) { infile >> masses[i]; } unsigned int ntris; infile >> ntris; for ( unsigned int t = 0; t < ntris; ++t ) { Vec3ui tri; infile >> tri[0]; infile >> tri[1]; infile >> tri[2]; mesh.add_triangle( Vec3st(tri) ); } infile.close(); return infile.good(); }
void Driver::SurfAppendMesh(SurfTrack* g_surf,ObjModel& obj) { int oldVNum=g_surf->get_num_vertices(); for (int i = 0; i < obj.vertexNum; i++) { Vector3d& p=obj.vertex[i]; g_surf->add_vertex(Vec3d(p(0),p(1),p(2)),1.0f); } for (int i = 0; i < obj.faceNum; i++) { Face& f=obj.face[i]; int first=oldVNum+f.first-1; int second=oldVNum+f.second-1; int third=oldVNum+f.third-1; g_surf->add_triangle(Vec3st(first,second,third)); } }
void create_sphere( const Vec3d& sphere_centre, double sphere_radius, double dx, std::vector<Vec3d>& verts, std::vector<Vec3st>& tris ) { const Vec3d domain_low = sphere_centre - Vec3d(sphere_radius + 3*dx); const Vec3d domain_high = sphere_centre + Vec3d(sphere_radius + 3*dx); Array3d phi; create_sphere_signed_distance( sphere_centre, sphere_radius, dx, domain_low, domain_high, phi ); MarchingTilesHiRes marching_tiles( domain_low, dx, phi ); marching_tiles.contour(); marching_tiles.improve_mesh(); std::vector<Vec3d> new_verts( marching_tiles.x.size() ); for ( size_t i = 0; i < new_verts.size(); ++i ) { new_verts[i] = marching_tiles.x[i]; } std::vector<Vec3st> new_tris( marching_tiles.tri.size() ); for ( size_t i = 0; i < new_tris.size(); ++i ) { new_tris[i] = Vec3st( marching_tiles.tri[i] ); } project_to_exact_sphere( new_verts, sphere_centre, sphere_radius ); Vec3st offset( verts.size() ); for ( size_t i = 0; i < new_verts.size(); ++i ) { verts.push_back( new_verts[i] ); } for ( size_t i = 0; i < new_tris.size(); ++i ) { tris.push_back( new_tris[i] + offset ); } }
void contour_phi( const Vec3d& domain_low, double domain_dx, Array3d& phi, std::vector<Vec3st>& tris, std::vector<Vec3d>& verts ) { MarchingTilesHiRes tiles( domain_low, domain_dx, phi ); std::cout << "Contouring..." << std::endl; tiles.contour(); std::cout << "Improving..." << std::endl; tiles.improve_mesh(); std::cout << "Copying..." << std::endl; for ( size_t i = 0; i < tiles.tri.size(); ++i ) { tris.push_back( Vec3st( tiles.tri[i] ) ); } for ( size_t i = 0; i < tiles.x.size(); ++i ) { verts.push_back( tiles.x[i] ); } std::cout << "done" << std::endl; }
void SurfTrack::remove_triangle(size_t t) { m_mesh.nondestructive_remove_triangle( t ); if ( m_collision_safety ) { m_broad_phase->remove_triangle( t ); } m_triangle_change_history.push_back( TriangleUpdateEvent( TriangleUpdateEvent::TRIANGLE_REMOVE, t, Vec3st(0) ) ); }
//void improvemesh(SurfaceMesh msh,ElTopoParameters elparameters,SurfaceMesh * outmsh) extern "C" void improvemesh ( double * inmsh_verticies, int inmsh_Nverticies, int * inmsh_triangles, int inmsh_Ntriangles, double * outmsh_verticies, int * outmsh_Nverticies, int * outmsh_triangles, int * outmsh_Ntriangles, double m_proximity_epsilon, double m_friction_coefficient, double m_min_triangle_area, double m_improve_collision_epsilon, bool m_use_fraction, double m_min_edge_length, double m_max_edge_length, double m_max_volume_change, double m_min_triangle_angle, double m_max_triangle_angle, bool m_use_curvature_when_splitting, bool m_use_curvature_when_collapsing, double m_min_curvature_multiplier, double m_max_curvature_multiplier, bool m_allow_vertex_movement, double m_edge_flip_min_length_change, double m_merge_proximity_epsilon, bool m_collision_safety, bool m_allow_topology_changes, bool m_allow_non_manifold, bool m_perform_improvement, bool m_verbose ) { std::vector<Vec3d> vs; std::vector<double> masses; for ( int i = 0; i < inmsh_Nverticies; ++i ) { vs.push_back( Vec3d( inmsh_verticies[3*i], inmsh_verticies[3*i + 1], inmsh_verticies[3*i + 2] ) ); masses.push_back( 0.5 ); } std::vector<Vec3st> ts; for ( int i = 0; i < inmsh_Ntriangles; ++i ) { ts.push_back( Vec3st( inmsh_triangles[3*i], inmsh_triangles[3*i + 1], inmsh_triangles[3*i + 2] ) ); printf("%d %d %d\n", inmsh_triangles[3*i], inmsh_triangles[3*i + 1], inmsh_triangles[3*i + 2] ); } SurfTrackInitializationParameters parameters; parameters.m_proximity_epsilon = m_proximity_epsilon; parameters.m_friction_coefficient = m_friction_coefficient; parameters.m_min_triangle_area = m_min_triangle_area; parameters.m_improve_collision_epsilon = m_improve_collision_epsilon; parameters.m_use_fraction = m_use_fraction; parameters.m_min_edge_length = m_min_edge_length; parameters.m_max_edge_length = m_max_edge_length; parameters.m_max_volume_change = m_max_volume_change; parameters.m_min_triangle_angle = m_min_triangle_angle; parameters.m_max_triangle_angle = m_max_triangle_angle; parameters.m_use_curvature_when_splitting = m_use_curvature_when_splitting; parameters.m_use_curvature_when_collapsing = m_use_curvature_when_collapsing; parameters.m_min_curvature_multiplier = m_min_curvature_multiplier; parameters.m_max_curvature_multiplier = m_max_curvature_multiplier; parameters.m_allow_vertex_movement = m_allow_vertex_movement; parameters.m_edge_flip_min_length_change = m_edge_flip_min_length_change; parameters.m_merge_proximity_epsilon = m_merge_proximity_epsilon; parameters.m_collision_safety = m_collision_safety; parameters.m_allow_topology_changes = m_allow_topology_changes; parameters.m_allow_non_manifold = m_allow_non_manifold; parameters.m_perform_improvement = m_perform_improvement; parameters.m_subdivision_scheme = new ButterflyScheme(); SurfTrack surface_tracker( vs, ts, masses, parameters ); surface_tracker.m_verbose = m_verbose; printf("Hello again \n"); surface_tracker.improve_mesh(); surface_tracker.topology_changes(); surface_tracker.defrag_mesh(); // Creating usual array objects *outmsh_Nverticies = surface_tracker.get_num_vertices(); //double verticies_out[Nverticies_out*3]; for ( int i = 0; i < *outmsh_Nverticies; ++i ) { outmsh_verticies[3*i+0] = surface_tracker.get_position(i)[0]; outmsh_verticies[3*i+1] = surface_tracker.get_position(i)[1]; outmsh_verticies[3*i+2] = surface_tracker.get_position(i)[2]; } *outmsh_Ntriangles = surface_tracker.m_mesh.num_triangles(); // int triangles_out[Ntriangles_out*3]; for ( int i = 0; i < *outmsh_Ntriangles; ++i ) { const Vec3st& curr_tri = surface_tracker.m_mesh.get_triangle(i); outmsh_triangles[3*i + 0] = curr_tri[0]; outmsh_triangles[3*i + 1] = curr_tri[1]; outmsh_triangles[3*i + 2] = curr_tri[2]; } printf("Nverticies=%d Ntriangles=%d volume=%f \n",*outmsh_Nverticies,*outmsh_Ntriangles,surface_tracker.get_volume()); // printmesh(102,Nverticies_out,Ntriangles_out,verticies_out,triangles_out); // outmsh->verticies = verticies_out; //outmsh->Nverticies = Nverticies_out; // outmsh->triangles = triangles_out; // outmsh->Ntriangles = Ntriangles_out; }
void el_topo_static_operations( const ElTopoMesh* inputs, const struct ElTopoGeneralOptions* general_options, const struct ElTopoStaticOperationsOptions* options, struct ElTopoDefragInformation* defrag_info, struct ElTopoMesh* outputs ) { // // data wrangling // std::vector<Vec3d> vs; std::vector<double> masses; for ( int i = 0; i < inputs->num_vertices; ++i ) { vs.push_back( Vec3d( inputs->vertex_locations[3*i], inputs->vertex_locations[3*i + 1], inputs->vertex_locations[3*i + 2] ) ); masses.push_back( inputs->vertex_masses[i] ); } std::vector<Vec3st> ts; for ( int i = 0; i < inputs->num_triangles; ++i ) { ts.push_back( Vec3st( inputs->triangles[3*i], inputs->triangles[3*i + 1], inputs->triangles[3*i + 2] ) ); } // ================================================================================= // // do the actual operations // // build a SurfTrack SurfTrackInitializationParameters construction_parameters; construction_parameters.m_proximity_epsilon = general_options->m_proximity_epsilon; construction_parameters.m_use_fraction = false; construction_parameters.m_min_edge_length = options->m_min_edge_length; construction_parameters.m_max_edge_length = options->m_max_edge_length; construction_parameters.m_max_volume_change = options->m_max_volume_change; construction_parameters.m_min_triangle_angle = options->m_min_triangle_angle; construction_parameters.m_max_triangle_angle = options->m_max_triangle_angle; construction_parameters.m_use_curvature_when_splitting = options->m_use_curvature_when_splitting; construction_parameters.m_use_curvature_when_collapsing = options->m_use_curvature_when_collapsing; construction_parameters.m_min_curvature_multiplier = options->m_min_curvature_multiplier; construction_parameters.m_max_curvature_multiplier = options->m_max_curvature_multiplier; construction_parameters.m_allow_vertex_movement = options->m_allow_vertex_movement; construction_parameters.m_edge_flip_min_length_change = options->m_edge_flip_min_length_change; construction_parameters.m_merge_proximity_epsilon = options->m_merge_proximity_epsilon; construction_parameters.m_collision_safety = general_options->m_collision_safety; construction_parameters.m_allow_topology_changes = options->m_allow_topology_changes; construction_parameters.m_perform_improvement = options->m_perform_improvement; construction_parameters.m_subdivision_scheme = (SubdivisionScheme*) options->m_subdivision_scheme; SurfTrack surface_tracker( vs, ts, masses, construction_parameters ); surface_tracker.improve_mesh(); // do merging surface_tracker.topology_changes(); surface_tracker.defrag_mesh(); // ================================================================================= defrag_info->num_vertex_changes = to_int(surface_tracker.m_vertex_change_history.size()); defrag_info->vertex_is_remove = (int*) malloc( defrag_info->num_vertex_changes * sizeof(int) ); defrag_info->vertex_index = (int*) malloc( defrag_info->num_vertex_changes * sizeof(int) ); defrag_info->split_edge = (int*) malloc( 2 * defrag_info->num_vertex_changes * sizeof(int) ); for ( int i = 0; i < defrag_info->num_vertex_changes; ++i ) { defrag_info->vertex_is_remove[i] = surface_tracker.m_vertex_change_history[i].m_is_remove ? 1 : 0; defrag_info->vertex_index[i] = to_int(surface_tracker.m_vertex_change_history[i].m_vertex_index); defrag_info->split_edge[2*i+0] = to_int(surface_tracker.m_vertex_change_history[i].m_split_edge[0]); defrag_info->split_edge[2*i+1] = to_int(surface_tracker.m_vertex_change_history[i].m_split_edge[1]); } defrag_info->num_triangle_changes = to_int(surface_tracker.m_triangle_change_history.size()); defrag_info->triangle_is_remove = (int*) malloc( defrag_info->num_triangle_changes * sizeof(int) ); defrag_info->triangle_index = (int*) malloc( defrag_info->num_triangle_changes * sizeof(int) ); defrag_info->new_tri = (int*) malloc( 3 * defrag_info->num_triangle_changes * sizeof(int) ); for ( int i = 0; i < defrag_info->num_triangle_changes; ++i ) { defrag_info->triangle_is_remove[i] = surface_tracker.m_triangle_change_history[i].m_is_remove ? 1 : 0; defrag_info->triangle_index[i] = to_int(surface_tracker.m_triangle_change_history[i].m_triangle_index); defrag_info->new_tri[3*i+0] = to_int(surface_tracker.m_triangle_change_history[i].m_tri[0]); defrag_info->new_tri[3*i+1] = to_int(surface_tracker.m_triangle_change_history[i].m_tri[1]); defrag_info->new_tri[3*i+2] = to_int(surface_tracker.m_triangle_change_history[i].m_tri[2]); } defrag_info->defragged_triangle_map_size = to_int(surface_tracker.m_defragged_triangle_map.size()); defrag_info->defragged_triangle_map = (int*) malloc( 2 * defrag_info->defragged_triangle_map_size * sizeof(int) ); for ( int i = 0; i < defrag_info->defragged_triangle_map_size; ++i ) { defrag_info->defragged_triangle_map[2*i+0] = to_int(surface_tracker.m_defragged_triangle_map[i][0]); defrag_info->defragged_triangle_map[2*i+1] = to_int(surface_tracker.m_defragged_triangle_map[i][1]); } defrag_info->defragged_vertex_map_size = to_int(surface_tracker.m_defragged_vertex_map.size()); defrag_info->defragged_vertex_map = (int*) malloc( 2 * defrag_info->defragged_vertex_map_size * sizeof(int) ); for ( int i = 0; i < defrag_info->defragged_vertex_map_size; ++i ) { defrag_info->defragged_vertex_map[2*i+0] = to_int(surface_tracker.m_defragged_vertex_map[i][0]); defrag_info->defragged_vertex_map[2*i+1] = to_int(surface_tracker.m_defragged_vertex_map[i][1]); } // ================================================================================= // // data wrangling // outputs->num_vertices = to_int(surface_tracker.get_num_vertices()); outputs->vertex_locations = (double*) malloc( 3 * (outputs->num_vertices) * sizeof(double) ); outputs->vertex_masses = (double*) malloc( (outputs->num_vertices) * sizeof(double) ); for ( int i = 0; i < outputs->num_vertices; ++i ) { const Vec3d& pos = surface_tracker.get_position(i); outputs->vertex_locations[3*i + 0] = pos[0]; outputs->vertex_locations[3*i + 1] = pos[1]; outputs->vertex_locations[3*i + 2] = pos[2]; outputs->vertex_masses[i] = surface_tracker.m_masses[i]; } outputs->num_triangles = to_int(surface_tracker.m_mesh.num_triangles()); outputs->triangles = (int*) malloc( 3 * (outputs->num_triangles) * sizeof(int) ); for ( int i = 0; i < outputs->num_triangles; ++i ) { const Vec3st& curr_tri = surface_tracker.m_mesh.get_triangle(i); outputs->triangles[3*i + 0] = to_int(curr_tri[0]); outputs->triangles[3*i + 1] = to_int(curr_tri[1]); outputs->triangles[3*i + 2] = to_int(curr_tri[2]); } }
void el_topo_integrate( const ElTopoMesh* inputs, const double* in_vertex_new_locations, const struct ElTopoGeneralOptions* general_options, const struct ElTopoIntegrationOptions* options, double **out_vertex_locations, double *out_dt ) { // // data wrangling // std::vector<Vec3d> vs; std::vector<double> masses; for ( int i = 0; i < inputs->num_vertices; ++i ) { vs.push_back( Vec3d( inputs->vertex_locations[3*i], inputs->vertex_locations[3*i + 1], inputs->vertex_locations[3*i + 2] ) ); masses.push_back( inputs->vertex_masses[i] ); } std::vector<Vec3st> ts; for ( int i = 0; i < inputs->num_triangles; ++i ) { ts.push_back( Vec3st( inputs->triangles[3*i], inputs->triangles[3*i + 1], inputs->triangles[3*i + 2] ) ); } // ================================================================================= // // do the integration // // build a DynamicSurface DynamicSurface dynamic_surface( vs, ts, masses, general_options->m_proximity_epsilon, options->m_friction_coefficient, general_options->m_collision_safety, general_options->m_verbose ); dynamic_surface.set_all_newpositions( inputs->num_vertices, in_vertex_new_locations ); // advance by dt double actual_dt; dynamic_surface.integrate( options->m_dt, actual_dt ); // the dt used may be different than specified (if we cut the time step) *out_dt = actual_dt; // ================================================================================= // // data wrangling // *out_vertex_locations = (double*) malloc( 3 * inputs->num_vertices * sizeof(double) ); for ( int i = 0; i < inputs->num_vertices; ++i ) { const Vec3d& pos = dynamic_surface.get_position(i); (*out_vertex_locations)[3*i] = pos[0]; (*out_vertex_locations)[3*i + 1] = pos[1]; (*out_vertex_locations)[3*i + 2] = pos[2]; } }
void create_icosohedron( std::vector<Vec3d>& verts, std::vector<Vec3st>& tris ) { double t = 0.5 * ( 1. - sqrt(5.) ); double c = 1. / sqrt( 1. - t*t ); Vec3st offset( verts.size() ); verts.push_back( c * Vec3d( t, 1, 0 ) ); verts.push_back( c * Vec3d( -t, 1, 0 ) ); verts.push_back( c * Vec3d( t, -1, 0 ) ); verts.push_back( c * Vec3d( -t, -1, 0 ) ); verts.push_back( c * Vec3d( 1, 0, t ) ); verts.push_back( c * Vec3d( 1, 0, -t ) ); verts.push_back( c * Vec3d( -1, 0, t ) ); verts.push_back( c * Vec3d( -1, 0, -t ) ); verts.push_back( c * Vec3d( 0, t, 1 ) ); verts.push_back( c * Vec3d( 0, -t, 1 ) ); verts.push_back( c * Vec3d( 0, t, -1 ) ); verts.push_back( c * Vec3d( 0, -t, -1 ) ); tris.push_back( Vec3st(0,8,4) + offset ); tris.push_back( Vec3st(0,5,10) + offset ); tris.push_back( Vec3st(2,4,9) + offset ); tris.push_back( Vec3st(2,11,5) + offset ); tris.push_back( Vec3st(1,6,8) + offset ); tris.push_back( Vec3st(1,10,7) + offset ); tris.push_back( Vec3st(3,9,6) + offset ); tris.push_back( Vec3st(3,7,11) + offset ); tris.push_back( Vec3st(0,10,8) + offset ); tris.push_back( Vec3st(1,8,10) + offset ); tris.push_back( Vec3st(2,9,11) + offset ); tris.push_back( Vec3st(3,9,11) + offset ); tris.push_back( Vec3st(4,2,0) + offset ); tris.push_back( Vec3st(5,0,2) + offset ); tris.push_back( Vec3st(6,1,3) + offset ); tris.push_back( Vec3st(7,3,1) + offset ); tris.push_back( Vec3st(8,6,4) + offset ); tris.push_back( Vec3st(9,4,6) + offset ); tris.push_back( Vec3st(10,5,7) + offset ); tris.push_back( Vec3st(11,7,5) + offset ); }
bool MeshMerger::get_zipper_triangles( size_t edge_index_a, size_t edge_index_b, std::vector<Vec3st>& output_triangles ) { assert( output_triangles.size() == 8 ); const Vec2st& edge_a = m_surf.m_mesh.m_edges[edge_index_a]; const Vec2st& edge_b = m_surf.m_mesh.m_edges[edge_index_b]; size_t zipper_vertices[8]; zipper_vertices[0] = edge_a[0]; zipper_vertices[2] = edge_a[1]; zipper_vertices[4] = edge_b[0]; zipper_vertices[6] = edge_b[1]; const std::vector<size_t>& incident_triangles_a = m_surf.m_mesh.m_edge_to_triangle_map[edge_index_a]; assert( incident_triangles_a.size() == 2 ); // should be checked before calling this function const Vec3st& inc_tri_a0 = m_surf.m_mesh.get_triangle( incident_triangles_a[0] ); const Vec3st& inc_tri_a1 = m_surf.m_mesh.get_triangle( incident_triangles_a[1] ); size_t third_vertices[2]; third_vertices[0] = m_surf.m_mesh.get_third_vertex( zipper_vertices[0], zipper_vertices[2], inc_tri_a0 ); third_vertices[1] = m_surf.m_mesh.get_third_vertex( zipper_vertices[0], zipper_vertices[2], inc_tri_a1 ); if ( m_surf.m_mesh.oriented(zipper_vertices[0], zipper_vertices[2], inc_tri_a0 ) ) { zipper_vertices[1] = third_vertices[0]; zipper_vertices[3] = third_vertices[1]; } else if ( m_surf.m_mesh.oriented(zipper_vertices[0], zipper_vertices[2], inc_tri_a1) ) { zipper_vertices[3] = third_vertices[0]; zipper_vertices[1] = third_vertices[1]; } else { // Should not happen std::cout << "Orientation check failed" << std::endl; assert( false ); } const std::vector<size_t>& incident_triangles_b = m_surf.m_mesh.m_edge_to_triangle_map[edge_index_b]; assert( incident_triangles_b.size() == 2 ); // should be checked before calling this function assert( edge_index_b < m_surf.m_mesh.m_edges.size() ); const Vec2st& ce = m_surf.m_mesh.m_edges[edge_index_b]; const std::vector<size_t>& et = m_surf.m_mesh.m_edge_to_triangle_map[edge_index_b]; const Vec3st& inc_tri_b0 = m_surf.m_mesh.get_triangle( incident_triangles_b[0] ); const Vec3st& inc_tri_b1 = m_surf.m_mesh.get_triangle( incident_triangles_b[1] ); third_vertices[0] = m_surf.m_mesh.get_third_vertex( ce[0], ce[1], m_surf.m_mesh.get_triangle( et[0] ) ); third_vertices[0] = m_surf.m_mesh.get_third_vertex( zipper_vertices[4], zipper_vertices[6], inc_tri_b0 ); third_vertices[1] = m_surf.m_mesh.get_third_vertex( zipper_vertices[4], zipper_vertices[6], inc_tri_b1 ); if ( m_surf.m_mesh.oriented(zipper_vertices[4], zipper_vertices[6], inc_tri_b0) ) { zipper_vertices[5] = third_vertices[0]; zipper_vertices[7] = third_vertices[1]; } else if ( m_surf.m_mesh.oriented(zipper_vertices[4], zipper_vertices[6], inc_tri_b1) ) { zipper_vertices[7] = third_vertices[0]; zipper_vertices[5] = third_vertices[1]; } else { // Should not happen std::cout << "Orientation check failed" << std::endl; assert( false ); } // Check for degenerate case for ( unsigned int i = 0; i < 8; ++i) { for ( unsigned int j = i+1; j < 8; ++j) { if ( zipper_vertices[i] == zipper_vertices[j] ) // vertices not distinct { return false; } // Check if an edge already exists between two vertices in opposite edge neighbourhoods // (i.e. look for an edge which would be created by zippering) if ( (i < 4) && (j > 3) ) { for ( size_t ii = 0; ii < m_surf.m_mesh.m_vertex_to_edge_map[ zipper_vertices[i] ].size(); ++ii ) { for ( size_t jj = 0; jj < m_surf.m_mesh.m_vertex_to_edge_map[ zipper_vertices[j] ].size(); ++jj ) { if ( m_surf.m_mesh.m_vertex_to_edge_map[ zipper_vertices[i] ][ii] == m_surf.m_mesh.m_vertex_to_edge_map[ zipper_vertices[j] ][jj] ) { return false; } } } } } } // Twist so that vertices 0 and 4 are the pair closest together twist_vertices( zipper_vertices ); // now we can use a closed formula to construct zippering triangles output_triangles[0] = Vec3st( zipper_vertices[0], zipper_vertices[4], zipper_vertices[1] ); // a e b output_triangles[1] = Vec3st( zipper_vertices[1], zipper_vertices[4], zipper_vertices[7] ); // b e h output_triangles[2] = Vec3st( zipper_vertices[1], zipper_vertices[7], zipper_vertices[2] ); // b h c output_triangles[3] = Vec3st( zipper_vertices[2], zipper_vertices[7], zipper_vertices[6] ); // c h g output_triangles[4] = Vec3st( zipper_vertices[2], zipper_vertices[6], zipper_vertices[3] ); // c g d output_triangles[5] = Vec3st( zipper_vertices[3], zipper_vertices[6], zipper_vertices[5] ); // d g f output_triangles[6] = Vec3st( zipper_vertices[3], zipper_vertices[5], zipper_vertices[0] ); // d f a output_triangles[7] = Vec3st( zipper_vertices[0], zipper_vertices[5], zipper_vertices[4] ); // a f e return true; }