From 8da54139c463a09ec899a9df6bccae16802dccdf Mon Sep 17 00:00:00 2001 From: bubnikv Date: Tue, 4 Jun 2019 22:06:42 +0200 Subject: [PATCH] WIP: Admesh - replacement of C memory allocation with std vectors --- CMakeLists.txt | 2 +- src/admesh/connect.cpp | 401 ++++++++----------- src/admesh/normals.cpp | 26 +- src/admesh/shared.cpp | 37 +- src/admesh/stl.h | 187 +++++---- src/admesh/stl_io.cpp | 30 +- src/admesh/stlinit.cpp | 104 ++--- src/admesh/util.cpp | 104 +++-- src/libslic3r/Format/3mf.cpp | 2 +- src/libslic3r/Format/AMF.cpp | 2 +- src/libslic3r/Format/PRUS.cpp | 6 +- src/libslic3r/Model.cpp | 18 +- src/libslic3r/SLA/SLASupportTreeIGL.cpp | 17 +- src/libslic3r/SlicingAdaptive.cpp | 4 +- src/libslic3r/TriangleMesh.cpp | 83 ++-- src/libslic3r/TriangleMesh.hpp | 4 +- src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp | 8 +- 17 files changed, 450 insertions(+), 585 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 719bdd04e..3d7157d5e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -60,7 +60,7 @@ if (MSVC) # /bigobj (Increase Number of Sections in .Obj file) # error C3859: virtual memory range for PCH exceeded; please recompile with a command line option of '-Zm90' or greater # Generate symbols at every build target, even for the release. - add_compile_options(-bigobj -Zm316 /Zi) + add_compile_options(-bigobj -Zm520 /Zi) endif () # Display and check CMAKE_PREFIX_PATH diff --git a/src/admesh/connect.cpp b/src/admesh/connect.cpp index 3069251d3..b99f93f3d 100644 --- a/src/admesh/connect.cpp +++ b/src/admesh/connect.cpp @@ -97,18 +97,10 @@ void stl_check_facets_exact(stl_file *stl) stl->stats.freed = 0; stl->stats.collisions = 0; stl->M = (int)hash_size_from_nr_faces(stl->stats.number_of_facets); - for (uint32_t i = 0; i < stl->stats.number_of_facets; ++ i) { - // initialize neighbors list to -1 to mark unconnected edges - stl->neighbors_start[i].neighbor[0] = -1; - stl->neighbors_start[i].neighbor[1] = -1; - stl->neighbors_start[i].neighbor[2] = -1; - } - stl->heads = (stl_hash_edge**)calloc(stl->M, sizeof(*stl->heads)); - if (stl->heads == NULL) - perror("stl_initialize_facet_check_exact"); - stl->tail = (stl_hash_edge*)malloc(sizeof(stl_hash_edge)); - if (stl->tail == NULL) - perror("stl_initialize_facet_check_exact"); + for (auto &neighbor : stl->neighbors_start) + neighbor.reset(); + stl->heads.assign(stl->M, nullptr); + stl->tail = new stl_hash_edge; stl->tail->next = stl->tail; for (int i = 0; i < stl->M; ++ i) stl->heads[i] = stl->tail; @@ -180,7 +172,7 @@ static void insert_hash_edge(stl_file *stl, stl_hash_edge edge, stl_hash_edge *temp; if(link == stl->tail) { /* This list doesn't have any edges currently in it. Add this one. */ - new_edge = (stl_hash_edge*)malloc(sizeof(stl_hash_edge)); + new_edge = new stl_hash_edge; if(new_edge == NULL) perror("insert_hash_edge"); stl->stats.malloced++; *new_edge = edge; @@ -192,7 +184,7 @@ static void insert_hash_edge(stl_file *stl, stl_hash_edge edge, match_neighbors(stl, &edge, link); /* Delete the matched edge from the list. */ stl->heads[chain_number] = link->next; - free(link); + delete link; stl->stats.freed++; return; } else { @@ -200,7 +192,7 @@ static void insert_hash_edge(stl_file *stl, stl_hash_edge edge, for(;;) { if(link->next == stl->tail) { /* This is the last item in the list. Insert a new edge. */ - new_edge = (stl_hash_edge*)malloc(sizeof(stl_hash_edge)); + new_edge = new stl_hash_edge; if(new_edge == NULL) perror("insert_hash_edge"); stl->stats.malloced++; *new_edge = edge; @@ -215,7 +207,7 @@ static void insert_hash_edge(stl_file *stl, stl_hash_edge edge, /* Delete the matched edge from the list. */ temp = link->next; link->next = link->next->next; - free(temp); + delete temp; stl->stats.freed++; return; } else { @@ -307,48 +299,38 @@ static void stl_free_edges(stl_file *stl) for (int i = 0; i < stl->M; i++) { for (stl_hash_edge *temp = stl->heads[i]; stl->heads[i] != stl->tail; temp = stl->heads[i]) { stl->heads[i] = stl->heads[i]->next; - free(temp); + delete temp; ++ stl->stats.freed; } } } - free(stl->heads); - stl->heads = nullptr; - free(stl->tail); + stl->heads.clear(); + delete stl->tail; stl->tail = nullptr; } static void stl_initialize_facet_check_nearby(stl_file *stl) { - int i; + if (stl->error) + return; - if (stl->error) return; + stl->stats.malloced = 0; + stl->stats.freed = 0; + stl->stats.collisions = 0; - stl->stats.malloced = 0; - stl->stats.freed = 0; - stl->stats.collisions = 0; + /* tolerance = STL_MAX(stl->stats.shortest_edge, tolerance);*/ + /* tolerance = STL_MAX((stl->stats.bounding_diameter / 500000.0), tolerance);*/ + /* tolerance *= 0.5;*/ + stl->M = (int)hash_size_from_nr_faces(stl->stats.number_of_facets); - /* tolerance = STL_MAX(stl->stats.shortest_edge, tolerance);*/ - /* tolerance = STL_MAX((stl->stats.bounding_diameter / 500000.0), tolerance);*/ - /* tolerance *= 0.5;*/ + stl->heads.assign(stl->M, nullptr); + stl->tail = new stl_hash_edge; + stl->tail->next = stl->tail; - stl->M = (int)hash_size_from_nr_faces(stl->stats.number_of_facets); - - stl->heads = (stl_hash_edge**)calloc(stl->M, sizeof(*stl->heads)); - if(stl->heads == NULL) perror("stl_initialize_facet_check_nearby"); - - stl->tail = (stl_hash_edge*)malloc(sizeof(stl_hash_edge)); - if(stl->tail == NULL) perror("stl_initialize_facet_check_nearby"); - - stl->tail->next = stl->tail; - - for(i = 0; i < stl->M; i++) { - stl->heads[i] = stl->tail; - } + for (int i = 0; i < stl->M; ++ i) + stl->heads[i] = stl->tail; } - - static void stl_record_neighbors(stl_file *stl, stl_hash_edge *edge_a, stl_hash_edge *edge_b) { @@ -358,29 +340,19 @@ stl_record_neighbors(stl_file *stl, if (stl->error) return; /* Facet a's neighbor is facet b */ - stl->neighbors_start[edge_a->facet_number].neighbor[edge_a->which_edge % 3] = - edge_b->facet_number; /* sets the .neighbor part */ - - stl->neighbors_start[edge_a->facet_number]. - which_vertex_not[edge_a->which_edge % 3] = - (edge_b->which_edge + 2) % 3; /* sets the .which_vertex_not part */ + stl->neighbors_start[edge_a->facet_number].neighbor[edge_a->which_edge % 3] = edge_b->facet_number; /* sets the .neighbor part */ + stl->neighbors_start[edge_a->facet_number].which_vertex_not[edge_a->which_edge % 3] = (edge_b->which_edge + 2) % 3; /* sets the .which_vertex_not part */ /* Facet b's neighbor is facet a */ - stl->neighbors_start[edge_b->facet_number].neighbor[edge_b->which_edge % 3] = - edge_a->facet_number; /* sets the .neighbor part */ - - stl->neighbors_start[edge_b->facet_number]. - which_vertex_not[edge_b->which_edge % 3] = - (edge_a->which_edge + 2) % 3; /* sets the .which_vertex_not part */ + stl->neighbors_start[edge_b->facet_number].neighbor[edge_b->which_edge % 3] = edge_a->facet_number; /* sets the .neighbor part */ + stl->neighbors_start[edge_b->facet_number].which_vertex_not[edge_b->which_edge % 3] = (edge_a->which_edge + 2) % 3; /* sets the .which_vertex_not part */ if( ((edge_a->which_edge < 3) && (edge_b->which_edge < 3)) || ((edge_a->which_edge > 2) && (edge_b->which_edge > 2))) { /* these facets are oriented in opposite directions. */ /* their normals are probably messed up. */ - stl->neighbors_start[edge_a->facet_number]. - which_vertex_not[edge_a->which_edge % 3] += 3; - stl->neighbors_start[edge_b->facet_number]. - which_vertex_not[edge_b->which_edge % 3] += 3; + stl->neighbors_start[edge_a->facet_number].which_vertex_not[edge_a->which_edge % 3] += 3; + stl->neighbors_start[edge_b->facet_number].which_vertex_not[edge_b->which_edge % 3] += 3; } @@ -561,8 +533,7 @@ stl_which_vertices_to_change(stl_file *stl, stl_hash_edge *edge_a, *facet1 = -1; } else { if( (stl->neighbors_start[edge_a->facet_number].neighbor[v1a] == -1) - && (stl->neighbors_start[edge_a->facet_number]. - neighbor[(v1a + 2) % 3] == -1)) { + && (stl->neighbors_start[edge_a->facet_number].neighbor[(v1a + 2) % 3] == -1)) { /* This vertex has no neighbors. This is a good one to change */ *facet1 = edge_a->facet_number; *vertex1 = v1a; @@ -581,8 +552,7 @@ stl_which_vertices_to_change(stl_file *stl, stl_hash_edge *edge_a, *facet2 = -1; } else { if( (stl->neighbors_start[edge_a->facet_number].neighbor[v2a] == -1) - && (stl->neighbors_start[edge_a->facet_number]. - neighbor[(v2a + 2) % 3] == -1)) { + && (stl->neighbors_start[edge_a->facet_number].neighbor[(v2a + 2) % 3] == -1)) { /* This vertex has no neighbors. This is a good one to change */ *facet2 = edge_a->facet_number; *vertex2 = v2a; @@ -595,140 +565,6 @@ stl_which_vertices_to_change(stl_file *stl, stl_hash_edge *edge_a, } } -static void remove_facet(stl_file *stl, int facet_number) -{ - assert(! stl->error); - ++ stl->stats.facets_removed; - /* Update list of connected edges */ - stl_neighbors &neighbors = stl->neighbors_start[facet_number]; - // Update statistics on unconnected triangle edges. - switch ((neighbors.neighbor[0] == -1) + (neighbors.neighbor[1] == -1) + (neighbors.neighbor[2] == -1)) { - case 0: // Facet has 3 neighbors - -- stl->stats.connected_facets_3_edge; - -- stl->stats.connected_facets_2_edge; - -- stl->stats.connected_facets_1_edge; - break; - case 1: // Facet has 2 neighbors - -- stl->stats.connected_facets_2_edge; - -- stl->stats.connected_facets_1_edge; - break; - case 2: // Facet has 1 neighbor - -- stl->stats.connected_facets_1_edge; - case 3: // Facet has 0 neighbors - break; - default: - assert(false); - } - - if (facet_number == -- stl->stats.number_of_facets) - // Removing the last face is easy, just forget the last face. - return; - - // Copy the face and neighborship from the last face to facet_number. - stl->facet_start[facet_number] = stl->facet_start[stl->stats.number_of_facets]; - neighbors = stl->neighbors_start[stl->stats.number_of_facets]; - // Update neighborship of faces, which used to point to the last face, now moved to facet_number. - for (int i = 0; i < 3; ++ i) - if (neighbors.neighbor[i] != -1) { - int &other_face_idx = stl->neighbors_start[neighbors.neighbor[i]].neighbor[(neighbors.which_vertex_not[i] + 1) % 3]; - if (other_face_idx != stl->stats.number_of_facets) { - printf("in remove_facet: neighbor = %d numfacets = %d this is wrong\n", other_face_idx, stl->stats.number_of_facets); - return; - } - other_face_idx = facet_number; - } -} - -static void remove_degenerate(stl_file *stl, int facet) -{ - assert(! stl->error); - - // Update statistics on face connectivity. - auto stl_update_connects_remove_1 = [stl](int facet_num) { - assert(! stl->error); - //FIXME when decreasing 3_edge, should I increase 2_edge etc? - switch ((stl->neighbors_start[facet_num].neighbor[0] == -1) + (stl->neighbors_start[facet_num].neighbor[1] == -1) + (stl->neighbors_start[facet_num].neighbor[2] == -1)) { - case 0: // Facet has 3 neighbors - -- stl->stats.connected_facets_3_edge; break; - case 1: // Facet has 2 neighbors - -- stl->stats.connected_facets_2_edge; break; - case 2: // Facet has 1 neighbor - -- stl->stats.connected_facets_1_edge; break; - case 3: // Facet has 0 neighbors - break; - default: - assert(false); - } - }; - - int edge_to_collapse = 0; - if (stl->facet_start[facet].vertex[0] == stl->facet_start[facet].vertex[1]) { - if (stl->facet_start[facet].vertex[1] == stl->facet_start[facet].vertex[2]) { - // All 3 vertices are equal. Collapse the edge with no neighbor if it exists. - const int *nbr = stl->neighbors_start[facet].neighbor; - edge_to_collapse = (nbr[0] == -1) ? 0 : (nbr[1] == -1) ? 1 : 2; - } else { - edge_to_collapse = 0; - } - } else if (stl->facet_start[facet].vertex[1] == stl->facet_start[facet].vertex[2]) { - edge_to_collapse = 1; - } else if (stl->facet_start[facet].vertex[2] == stl->facet_start[facet].vertex[0]) { - edge_to_collapse = 2; - } else { - // No degenerate. Function shouldn't have been called. - return; - } - - int edge[3] = { (edge_to_collapse + 1) % 3, (edge_to_collapse + 2) % 3, edge_to_collapse }; - int neighbor[] = { - stl->neighbors_start[facet].neighbor[edge[0]], - stl->neighbors_start[facet].neighbor[edge[1]], - stl->neighbors_start[facet].neighbor[edge[2]] - }; - int vnot[] = { - stl->neighbors_start[facet].which_vertex_not[edge[0]], - stl->neighbors_start[facet].which_vertex_not[edge[1]], - stl->neighbors_start[facet].which_vertex_not[edge[2]] - }; - // Update statistics on edge connectivity. - if (neighbor[0] == -1) - stl_update_connects_remove_1(neighbor[1]); - if (neighbor[1] == -1) - stl_update_connects_remove_1(neighbor[0]); - - if (neighbor[0] >= 0) { - if (neighbor[1] >= 0) { - // Adjust the "flip" flag for the which_vertex_not values. - if (vnot[0] > 2) { - if (vnot[1] > 2) { - // The face to be removed has its normal flipped compared to the left & right neighbors, therefore after removing this face - // the two remaining neighbors will be oriented correctly. - vnot[0] -= 3; - vnot[1] -= 3; - } else - // One neighbor has its normal inverted compared to the face to be removed, the other is oriented equally. - // After removal, the two neighbors will have their normals flipped. - vnot[1] += 3; - } else if (vnot[1] > 2) - // One neighbor has its normal inverted compared to the face to be removed, the other is oriented equally. - // After removal, the two neighbors will have their normals flipped. - vnot[0] += 3; - } - stl->neighbors_start[neighbor[0]].neighbor[(vnot[0] + 1) % 3] = (neighbor[0] == neighbor[1]) ? -1 : neighbor[1]; - stl->neighbors_start[neighbor[0]].which_vertex_not[(vnot[0] + 1) % 3] = vnot[1]; - } - if (neighbor[1] >= 0) { - stl->neighbors_start[neighbor[1]].neighbor[(vnot[1] + 1) % 3] = (neighbor[0] == neighbor[1]) ? -1 : neighbor[0]; - stl->neighbors_start[neighbor[1]].which_vertex_not[(vnot[1] + 1) % 3] = vnot[0]; - } - if (neighbor[2] >= 0) { - stl_update_connects_remove_1(neighbor[2]); - stl->neighbors_start[neighbor[2]].neighbor[(vnot[2] + 1) % 3] = -1; - } - - remove_facet(stl, facet); -} - void stl_remove_unconnected_facets(stl_file *stl) { // A couple of things need to be done here. One is to remove any completely unconnected facets (0 edges connected) since these are @@ -737,12 +573,143 @@ void stl_remove_unconnected_facets(stl_file *stl) if (stl->error) return; + auto remove_facet = [stl](int facet_number) + { + ++ stl->stats.facets_removed; + /* Update list of connected edges */ + stl_neighbors &neighbors = stl->neighbors_start[facet_number]; + // Update statistics on unconnected triangle edges. + switch ((neighbors.neighbor[0] == -1) + (neighbors.neighbor[1] == -1) + (neighbors.neighbor[2] == -1)) { + case 0: // Facet has 3 neighbors + -- stl->stats.connected_facets_3_edge; + -- stl->stats.connected_facets_2_edge; + -- stl->stats.connected_facets_1_edge; + break; + case 1: // Facet has 2 neighbors + -- stl->stats.connected_facets_2_edge; + -- stl->stats.connected_facets_1_edge; + break; + case 2: // Facet has 1 neighbor + -- stl->stats.connected_facets_1_edge; + case 3: // Facet has 0 neighbors + break; + default: + assert(false); + } + + if (facet_number == -- stl->stats.number_of_facets) + // Removing the last face is easy, just forget the last face. + return; + + // Copy the face and neighborship from the last face to facet_number. + stl->facet_start[facet_number] = stl->facet_start[stl->stats.number_of_facets]; + neighbors = stl->neighbors_start[stl->stats.number_of_facets]; + // Update neighborship of faces, which used to point to the last face, now moved to facet_number. + for (int i = 0; i < 3; ++ i) + if (neighbors.neighbor[i] != -1) { + int &other_face_idx = stl->neighbors_start[neighbors.neighbor[i]].neighbor[(neighbors.which_vertex_not[i] + 1) % 3]; + if (other_face_idx != stl->stats.number_of_facets) { + printf("in remove_facet: neighbor = %d numfacets = %d this is wrong\n", other_face_idx, stl->stats.number_of_facets); + return; + } + other_face_idx = facet_number; + } + }; + + auto remove_degenerate = [stl, remove_facet](int facet) + { + // Update statistics on face connectivity. + auto stl_update_connects_remove_1 = [stl](int facet_num) { + assert(! stl->error); + //FIXME when decreasing 3_edge, should I increase 2_edge etc? + switch ((stl->neighbors_start[facet_num].neighbor[0] == -1) + (stl->neighbors_start[facet_num].neighbor[1] == -1) + (stl->neighbors_start[facet_num].neighbor[2] == -1)) { + case 0: // Facet has 3 neighbors + -- stl->stats.connected_facets_3_edge; break; + case 1: // Facet has 2 neighbors + -- stl->stats.connected_facets_2_edge; break; + case 2: // Facet has 1 neighbor + -- stl->stats.connected_facets_1_edge; break; + case 3: // Facet has 0 neighbors + break; + default: + assert(false); + } + }; + + int edge_to_collapse = 0; + if (stl->facet_start[facet].vertex[0] == stl->facet_start[facet].vertex[1]) { + if (stl->facet_start[facet].vertex[1] == stl->facet_start[facet].vertex[2]) { + // All 3 vertices are equal. Collapse the edge with no neighbor if it exists. + const int *nbr = stl->neighbors_start[facet].neighbor; + edge_to_collapse = (nbr[0] == -1) ? 0 : (nbr[1] == -1) ? 1 : 2; + } else { + edge_to_collapse = 0; + } + } else if (stl->facet_start[facet].vertex[1] == stl->facet_start[facet].vertex[2]) { + edge_to_collapse = 1; + } else if (stl->facet_start[facet].vertex[2] == stl->facet_start[facet].vertex[0]) { + edge_to_collapse = 2; + } else { + // No degenerate. Function shouldn't have been called. + return; + } + + int edge[3] = { (edge_to_collapse + 1) % 3, (edge_to_collapse + 2) % 3, edge_to_collapse }; + int neighbor[] = { + stl->neighbors_start[facet].neighbor[edge[0]], + stl->neighbors_start[facet].neighbor[edge[1]], + stl->neighbors_start[facet].neighbor[edge[2]] + }; + int vnot[] = { + stl->neighbors_start[facet].which_vertex_not[edge[0]], + stl->neighbors_start[facet].which_vertex_not[edge[1]], + stl->neighbors_start[facet].which_vertex_not[edge[2]] + }; + // Update statistics on edge connectivity. + if (neighbor[0] == -1) + stl_update_connects_remove_1(neighbor[1]); + if (neighbor[1] == -1) + stl_update_connects_remove_1(neighbor[0]); + + if (neighbor[0] >= 0) { + if (neighbor[1] >= 0) { + // Adjust the "flip" flag for the which_vertex_not values. + if (vnot[0] > 2) { + if (vnot[1] > 2) { + // The face to be removed has its normal flipped compared to the left & right neighbors, therefore after removing this face + // the two remaining neighbors will be oriented correctly. + vnot[0] -= 3; + vnot[1] -= 3; + } else + // One neighbor has its normal inverted compared to the face to be removed, the other is oriented equally. + // After removal, the two neighbors will have their normals flipped. + vnot[1] += 3; + } else if (vnot[1] > 2) + // One neighbor has its normal inverted compared to the face to be removed, the other is oriented equally. + // After removal, the two neighbors will have their normals flipped. + vnot[0] += 3; + } + stl->neighbors_start[neighbor[0]].neighbor[(vnot[0] + 1) % 3] = (neighbor[0] == neighbor[1]) ? -1 : neighbor[1]; + stl->neighbors_start[neighbor[0]].which_vertex_not[(vnot[0] + 1) % 3] = vnot[1]; + } + if (neighbor[1] >= 0) { + stl->neighbors_start[neighbor[1]].neighbor[(vnot[1] + 1) % 3] = (neighbor[0] == neighbor[1]) ? -1 : neighbor[0]; + stl->neighbors_start[neighbor[1]].which_vertex_not[(vnot[1] + 1) % 3] = vnot[0]; + } + if (neighbor[2] >= 0) { + stl_update_connects_remove_1(neighbor[2]); + stl->neighbors_start[neighbor[2]].neighbor[(vnot[2] + 1) % 3] = -1; + } + + remove_facet(facet); + }; + // remove degenerate facets for (uint32_t i = 0; i < stl->stats.number_of_facets;) if (stl->facet_start[i].vertex[0] == stl->facet_start[i].vertex[1] || stl->facet_start[i].vertex[0] == stl->facet_start[i].vertex[2] || stl->facet_start[i].vertex[1] == stl->facet_start[i].vertex[2]) { - remove_degenerate(stl, i); + remove_degenerate(i); // assert(stl_validate(stl)); } else ++ i; @@ -754,7 +721,7 @@ void stl_remove_unconnected_facets(stl_file *stl) stl->neighbors_start[i].neighbor[1] == -1 && stl->neighbors_start[i].neighbor[2] == -1) { // This facet is completely unconnected. Remove it. - remove_facet(stl, i); + remove_facet(i); assert(stl_validate(stl)); } else ++ i; @@ -850,8 +817,7 @@ stl_fill_holes(stl_file *stl) { } break; } else { - vnot = stl->neighbors_start[facet_num]. - which_vertex_not[next_edge]; + vnot = stl->neighbors_start[facet_num].which_vertex_not[next_edge]; facet_num = next_facet; } @@ -867,27 +833,14 @@ Try using a smaller tolerance or don't do a nearby check\n"); } } -void -stl_add_facet(stl_file *stl, stl_facet *new_facet) { - if (stl->error) return; - - stl->stats.facets_added += 1; - if(stl->stats.facets_malloced < (int)stl->stats.number_of_facets + 1) { - stl->facet_start = (stl_facet*)realloc(stl->facet_start, - (sizeof(stl_facet) * (stl->stats.facets_malloced + 256))); - if(stl->facet_start == NULL) perror("stl_add_facet"); - stl->neighbors_start = (stl_neighbors*)realloc(stl->neighbors_start, - (sizeof(stl_neighbors) * (stl->stats.facets_malloced + 256))); - if(stl->neighbors_start == NULL) perror("stl_add_facet"); - stl->stats.facets_malloced += 256; - } - stl->facet_start[stl->stats.number_of_facets] = *new_facet; - - /* note that the normal vector is not set here, just initialized to 0 */ - stl->facet_start[stl->stats.number_of_facets].normal = stl_normal::Zero(); - - stl->neighbors_start[stl->stats.number_of_facets].neighbor[0] = -1; - stl->neighbors_start[stl->stats.number_of_facets].neighbor[1] = -1; - stl->neighbors_start[stl->stats.number_of_facets].neighbor[2] = -1; - stl->stats.number_of_facets += 1; +void stl_add_facet(stl_file *stl, const stl_facet *new_facet) +{ + if (stl->error) + return; + ++ stl->stats.facets_added; + ++ stl->stats.number_of_facets; + stl->facet_start.emplace_back(*new_facet); + // note that the normal vector is not set here, just initialized to 0. + stl->facet_start[stl->stats.number_of_facets].normal = stl_normal::Zero(); + stl->neighbors_start.emplace_back(); } diff --git a/src/admesh/normals.cpp b/src/admesh/normals.cpp index ecf08b59c..e11f1a3c1 100644 --- a/src/admesh/normals.cpp +++ b/src/admesh/normals.cpp @@ -84,7 +84,6 @@ stl_reverse_facet(stl_file *stl, int facet_num) { void stl_fix_normal_directions(stl_file *stl) { - char *norm_sw; /* int edge_num;*/ /* int vnot;*/ int checked = 0; @@ -101,7 +100,6 @@ stl_fix_normal_directions(stl_file *stl) { struct stl_normal *newn; struct stl_normal *temp; - int* reversed_ids; int reversed_count = 0; int id; int force_exit = 0; @@ -112,20 +110,15 @@ stl_fix_normal_directions(stl_file *stl) { if (stl->stats.number_of_facets == 0) return; /* Initialize linked list. */ - head = (struct stl_normal*)malloc(sizeof(struct stl_normal)); - if(head == NULL) perror("stl_fix_normal_directions"); - tail = (struct stl_normal*)malloc(sizeof(struct stl_normal)); - if(tail == NULL) perror("stl_fix_normal_directions"); + head = new stl_normal; + tail = new stl_normal; head->next = tail; tail->next = tail; /* Initialize list that keeps track of already fixed facets. */ - norm_sw = (char*)calloc(stl->stats.number_of_facets, sizeof(char)); - if(norm_sw == NULL) perror("stl_fix_normal_directions"); - + std::vector norm_sw(stl->stats.number_of_facets, 0); /* Initialize list that keeps track of reversed facets. */ - reversed_ids = (int*)calloc(stl->stats.number_of_facets, sizeof(int)); - if (reversed_ids == NULL) perror("stl_fix_normal_directions reversed_ids"); + std::vector reversed_ids(stl->stats.number_of_facets, 0); facet_num = 0; /* If normal vector is not within tolerance and backwards: @@ -166,8 +159,7 @@ stl_fix_normal_directions(stl_file *stl) { /* If we haven't fixed this facet yet, add it to the list: */ if(norm_sw[stl->neighbors_start[facet_num].neighbor[j]] != 1) { /* Add node to beginning of list. */ - newn = (struct stl_normal*)malloc(sizeof(struct stl_normal)); - if(newn == NULL) perror("stl_fix_normal_directions"); + newn = new stl_normal; newn->facet_num = stl->neighbors_start[facet_num].neighbor[j]; newn->next = head->next; head->next = newn; @@ -187,7 +179,7 @@ stl_fix_normal_directions(stl_file *stl) { } temp = head->next; /* Delete this facet from the list. */ head->next = head->next->next; - free(temp); + delete temp; } else { /* if we ran out of facets to fix: */ /* All of the facets in this part have been fixed. */ stl->stats.number_of_parts += 1; @@ -213,10 +205,8 @@ stl_fix_normal_directions(stl_file *stl) { } } } - free(head); - free(tail); - free(reversed_ids); - free(norm_sw); + delete head; + delete tail; } static int stl_check_normal_vector(stl_file *stl, int facet_num, int normal_fix_flag) { diff --git a/src/admesh/shared.cpp b/src/admesh/shared.cpp index 2ad270903..8162c6a8d 100644 --- a/src/admesh/shared.cpp +++ b/src/admesh/shared.cpp @@ -31,17 +31,8 @@ void stl_invalidate_shared_vertices(stl_file *stl) { - if (stl->error) - return; - - if (stl->v_indices != nullptr) { - free(stl->v_indices); - stl->v_indices = nullptr; - } - if (stl->v_shared != nullptr) { - free(stl->v_shared); - stl->v_shared = nullptr; - } + stl->v_indices.clear(); + stl->v_shared.clear(); } void stl_generate_shared_vertices(stl_file *stl) @@ -53,23 +44,11 @@ void stl_generate_shared_vertices(stl_file *stl) stl_invalidate_shared_vertices(stl); // 3 indices to vertex per face - stl->v_indices = (v_indices_struct*)calloc(stl->stats.number_of_facets, sizeof(v_indices_struct)); - if (stl->v_indices == nullptr) - perror("stl_generate_shared_vertices"); + stl->v_indices.assign(stl->stats.number_of_facets, v_indices_struct()); // Shared vertices (3D coordinates) - stl->v_shared = (stl_vertex*)calloc((stl->stats.number_of_facets / 2), sizeof(stl_vertex)); - if (stl->v_shared == nullptr) - perror("stl_generate_shared_vertices"); - stl->stats.shared_malloced = stl->stats.number_of_facets / 2; + stl->v_shared.assign(stl->stats.number_of_facets / 2, stl_vertex()); stl->stats.shared_vertices = 0; - for (uint32_t i = 0; i < stl->stats.number_of_facets; ++ i) { - // vertex index -1 means no shared vertex was assigned yet. - stl->v_indices[i].vertex[0] = -1; - stl->v_indices[i].vertex[1] = -1; - stl->v_indices[i].vertex[2] = -1; - } - // A degenerate mesh may contain loops: Traversing a fan will end up in an endless loop // while never reaching the starting face. To avoid these endless loops, traversed faces at each fan traversal // are marked with a unique fan_traversal_stamp. @@ -82,13 +61,7 @@ void stl_generate_shared_vertices(stl_file *stl) // Shared vertex was already assigned. continue; // Create a new shared vertex. - if (stl->stats.shared_vertices == stl->stats.shared_malloced) { - stl->stats.shared_malloced += 1024; - stl->v_shared = (stl_vertex*)realloc(stl->v_shared, stl->stats.shared_malloced * sizeof(stl_vertex)); - if(stl->v_shared == nullptr) - perror("stl_generate_shared_vertices"); - } - stl->v_shared[stl->stats.shared_vertices] = stl->facet_start[facet_idx].vertex[j]; + stl->v_shared.emplace_back(stl->facet_start[facet_idx].vertex[j]); // Traverse the fan around the j-th vertex of the i-th face, assign the newly created shared vertex index to all the neighboring triangles in the triangle fan. int facet_in_fan_idx = facet_idx; bool edge_direction = false; diff --git a/src/admesh/stl.h b/src/admesh/stl.h index 5ecd94bd1..345951121 100644 --- a/src/admesh/stl.h +++ b/src/admesh/stl.h @@ -27,6 +27,7 @@ #include #include +#include #include // Size of the binary STL header, free form. @@ -44,18 +45,18 @@ static_assert(sizeof(stl_vertex) == 12, "size of stl_vertex incorrect"); static_assert(sizeof(stl_normal) == 12, "size of stl_normal incorrect"); struct stl_facet { - stl_normal normal; - stl_vertex vertex[3]; - char extra[2]; + stl_normal normal; + stl_vertex vertex[3]; + char extra[2]; - stl_facet rotated(const Eigen::Quaternion &rot) { - stl_facet out; - out.normal = rot * this->normal; - out.vertex[0] = rot * this->vertex[0]; - out.vertex[1] = rot * this->vertex[1]; - out.vertex[2] = rot * this->vertex[2]; - return out; - } + stl_facet rotated(const Eigen::Quaternion &rot) const { + stl_facet out; + out.normal = rot * this->normal; + out.vertex[0] = rot * this->vertex[0]; + out.vertex[1] = rot * this->vertex[1]; + out.vertex[2] = rot * this->vertex[2]; + return out; + } }; #define SIZEOF_STL_FACET 50 @@ -67,86 +68,100 @@ static_assert(sizeof(stl_facet) >= SIZEOF_STL_FACET, "size of stl_facet incorrec typedef enum {binary, ascii, inmemory} stl_type; -typedef struct { - stl_vertex p1; - stl_vertex p2; - int facet_number; -} stl_edge; +struct stl_edge { + stl_vertex p1; + stl_vertex p2; + int facet_number; +}; -typedef struct stl_hash_edge { - // Key of a hash edge: sorted vertices of the edge. - uint32_t key[6]; - // Compare two keys. - bool operator==(const stl_hash_edge &rhs) { return memcmp(key, rhs.key, sizeof(key)) == 0; } - bool operator!=(const stl_hash_edge &rhs) { return ! (*this == rhs); } - int hash(int M) const { return ((key[0] / 11 + key[1] / 7 + key[2] / 3) ^ (key[3] / 11 + key[4] / 7 + key[5] / 3)) % M; } - // Index of a facet owning this edge. - int facet_number; - // Index of this edge inside the facet with an index of facet_number. - // If this edge is stored backwards, which_edge is increased by 3. - int which_edge; - struct stl_hash_edge *next; -} stl_hash_edge; +struct stl_hash_edge { + // Key of a hash edge: sorted vertices of the edge. + uint32_t key[6]; + // Compare two keys. + bool operator==(const stl_hash_edge &rhs) { return memcmp(key, rhs.key, sizeof(key)) == 0; } + bool operator!=(const stl_hash_edge &rhs) { return ! (*this == rhs); } + int hash(int M) const { return ((key[0] / 11 + key[1] / 7 + key[2] / 3) ^ (key[3] / 11 + key[4] / 7 + key[5] / 3)) % M; } + // Index of a facet owning this edge. + int facet_number; + // Index of this edge inside the facet with an index of facet_number. + // If this edge is stored backwards, which_edge is increased by 3. + int which_edge; + struct stl_hash_edge *next; +}; -typedef struct { - // Index of a neighbor facet. - int neighbor[3]; - // Index of an opposite vertex at the neighbor face. - char which_vertex_not[3]; -} stl_neighbors; +struct stl_neighbors { + stl_neighbors() { reset(); } + void reset() { + neighbor[0] = -1; + neighbor[1] = -1; + neighbor[2] = -1; + which_vertex_not[0] = -1; + which_vertex_not[1] = -1; + which_vertex_not[2] = -1; + } -typedef struct { - int vertex[3]; -} v_indices_struct; + // Index of a neighbor facet. + int neighbor[3]; + // Index of an opposite vertex at the neighbor face. + char which_vertex_not[3]; +}; -typedef struct { - char header[81]; - stl_type type; - uint32_t number_of_facets; - stl_vertex max; - stl_vertex min; - stl_vertex size; - float bounding_diameter; - float shortest_edge; - float volume; - unsigned number_of_blocks; - int connected_edges; - int connected_facets_1_edge; - int connected_facets_2_edge; - int connected_facets_3_edge; - int facets_w_1_bad_edge; - int facets_w_2_bad_edge; - int facets_w_3_bad_edge; - int original_num_facets; - int edges_fixed; - int degenerate_facets; - int facets_removed; - int facets_added; - int facets_reversed; - int backwards_edges; - int normals_fixed; - int number_of_parts; - int malloced; - int freed; - int facets_malloced; - int collisions; - int shared_vertices; - int shared_malloced; -} stl_stats; +struct v_indices_struct { + // -1 means no vertex index has been assigned yet + v_indices_struct() { vertex[0] = -1; vertex[1] = -1; vertex[2] = -1; } + int vertex[3]; +}; -typedef struct { - FILE *fp; - stl_facet *facet_start; - stl_hash_edge **heads; - stl_hash_edge *tail; - int M; - stl_neighbors *neighbors_start; - v_indices_struct *v_indices; - stl_vertex *v_shared; - stl_stats stats; - char error; -} stl_file; +struct stl_stats { + char header[81]; + stl_type type; + uint32_t number_of_facets; + stl_vertex max; + stl_vertex min; + stl_vertex size; + float bounding_diameter; + float shortest_edge; + float volume; + unsigned number_of_blocks; + int connected_edges; + int connected_facets_1_edge; + int connected_facets_2_edge; + int connected_facets_3_edge; + int facets_w_1_bad_edge; + int facets_w_2_bad_edge; + int facets_w_3_bad_edge; + int original_num_facets; + int edges_fixed; + int degenerate_facets; + int facets_removed; + int facets_added; + int facets_reversed; + int backwards_edges; + int normals_fixed; + int number_of_parts; + int shared_vertices; + // hash table statistics + int malloced; + int freed; + int collisions; +}; + +struct stl_file { + FILE *fp; + std::vector facet_start; + std::vector neighbors_start; + // Hash table on edges + std::vector heads; + stl_hash_edge* tail; + int M; + // Indexed face set + std::vector v_indices; + std::vector v_shared; + // Statistics + stl_stats stats; + char error; +}; extern void stl_open(stl_file *stl, const char *file); extern void stl_close(stl_file *stl); @@ -272,7 +287,7 @@ extern void stl_allocate(stl_file *stl); extern void stl_read(stl_file *stl, int first_facet, bool first); extern void stl_facet_stats(stl_file *stl, stl_facet facet, bool &first); extern void stl_reallocate(stl_file *stl); -extern void stl_add_facet(stl_file *stl, stl_facet *new_facet); +extern void stl_add_facet(stl_file *stl, const stl_facet *new_facet); extern void stl_clear_error(stl_file *stl); extern int stl_get_error(stl_file *stl); diff --git a/src/admesh/stl_io.cpp b/src/admesh/stl_io.cpp index 85f66785b..81060c0a3 100644 --- a/src/admesh/stl_io.cpp +++ b/src/admesh/stl_io.cpp @@ -109,7 +109,6 @@ Normals fixed : %5d\n", stl->stats.normals_fixed); void stl_write_ascii(stl_file *stl, const char *file, const char *label) { - int i; char *error_msg; if (stl->error) return; @@ -129,7 +128,7 @@ stl_write_ascii(stl_file *stl, const char *file, const char *label) { fprintf(fp, "solid %s\n", label); - for(i = 0; i < stl->stats.number_of_facets; i++) { + for (uint32_t i = 0; i < stl->stats.number_of_facets; ++ i) { fprintf(fp, " facet normal % .8E % .8E % .8E\n", stl->facet_start[i].normal(0), stl->facet_start[i].normal(1), stl->facet_start[i].normal(2)); @@ -154,7 +153,6 @@ stl_write_ascii(stl_file *stl, const char *file, const char *label) { void stl_print_neighbors(stl_file *stl, char *file) { - int i; FILE *fp; char *error_msg; @@ -173,7 +171,7 @@ stl_print_neighbors(stl_file *stl, char *file) { return; } - for(i = 0; i < stl->stats.number_of_facets; i++) { + for (uint32_t i = 0; i < stl->stats.number_of_facets; i++) { fprintf(fp, "%d, %d,%d, %d,%d, %d,%d\n", i, stl->neighbors_start[i].neighbor[0], @@ -200,7 +198,6 @@ void stl_internal_reverse_quads(char *buf, size_t cnt) void stl_write_binary(stl_file *stl, const char *file, const char *label) { FILE *fp; - int i; char *error_msg; if (stl->error) return; @@ -219,13 +216,13 @@ stl_write_binary(stl_file *stl, const char *file, const char *label) { } fprintf(fp, "%s", label); - for(i = strlen(label); i < LABEL_SIZE; i++) putc(0, fp); + for(size_t i = strlen(label); i < LABEL_SIZE; i++) putc(0, fp); fseek(fp, LABEL_SIZE, SEEK_SET); #ifdef BOOST_LITTLE_ENDIAN fwrite(&stl->stats.number_of_facets, 4, 1, fp); - for (i = 0; i < stl->stats.number_of_facets; ++ i) - fwrite(stl->facet_start + i, SIZEOF_STL_FACET, 1, fp); + for (const stl_facet &facet : stl->facet_start) + fwrite(&facet, SIZEOF_STL_FACET, 1, fp); #else /* BOOST_LITTLE_ENDIAN */ char buffer[50]; // Convert the number of facets to little endian. @@ -288,8 +285,6 @@ stl_write_neighbor(stl_file *stl, int facet) { void stl_write_quad_object(stl_file *stl, char *file) { FILE *fp; - int i; - int j; char *error_msg; stl_vertex connect_color = stl_vertex::Zero(); stl_vertex uncon_1_color = stl_vertex::Zero(); @@ -313,10 +308,10 @@ stl_write_quad_object(stl_file *stl, char *file) { } fprintf(fp, "CQUAD\n"); - for(i = 0; i < stl->stats.number_of_facets; i++) { - j = ((stl->neighbors_start[i].neighbor[0] == -1) + - (stl->neighbors_start[i].neighbor[1] == -1) + - (stl->neighbors_start[i].neighbor[2] == -1)); + for (uint32_t i = 0; i < stl->stats.number_of_facets; i++) { + int j = ((stl->neighbors_start[i].neighbor[0] == -1) + + (stl->neighbors_start[i].neighbor[1] == -1) + + (stl->neighbors_start[i].neighbor[2] == -1)); if(j == 0) { color = connect_color; } else if(j == 1) { @@ -346,9 +341,8 @@ stl_write_quad_object(stl_file *stl, char *file) { fclose(fp); } -void -stl_write_dxf(stl_file *stl, const char *file, char *label) { - int i; +void stl_write_dxf(stl_file *stl, const char *file, char *label) +{ FILE *fp; char *error_msg; @@ -375,7 +369,7 @@ stl_write_dxf(stl_file *stl, const char *file, char *label) { fprintf(fp, "0\nSECTION\n2\nENTITIES\n"); - for(i = 0; i < stl->stats.number_of_facets; i++) { + for (uint32_t i = 0; i < stl->stats.number_of_facets; i++) { fprintf(fp, "0\n3DFACE\n8\n0\n"); fprintf(fp, "10\n%f\n20\n%f\n30\n%f\n", stl->facet_start[i].vertex[0](0), stl->facet_start[i].vertex[0](1), diff --git a/src/admesh/stlinit.cpp b/src/admesh/stlinit.cpp index 911f4f5e8..81b7914c3 100644 --- a/src/admesh/stlinit.cpp +++ b/src/admesh/stlinit.cpp @@ -35,22 +35,38 @@ #error "SEEK_SET not defined" #endif -void -stl_open(stl_file *stl, const char *file) { - stl_initialize(stl); - stl_count_facets(stl, file); - stl_allocate(stl); - stl_read(stl, 0, true); - if (stl->fp != nullptr) { - fclose(stl->fp); - stl->fp = nullptr; - } +void stl_open(stl_file *stl, const char *file) +{ + stl_initialize(stl); + stl_count_facets(stl, file); + stl_allocate(stl); + stl_read(stl, 0, true); + if (stl->fp != nullptr) { + fclose(stl->fp); + stl->fp = nullptr; + } } -void -stl_initialize(stl_file *stl) { - memset(stl, 0, sizeof(stl_file)); - stl->stats.volume = -1.0; +void stl_initialize(stl_file *stl) +{ + stl->fp = nullptr; + stl->tail = nullptr; + stl->M = 0; + stl->error = 0; + stl->facet_start.clear(); + stl->neighbors_start.clear(); + stl->v_indices.clear(); + stl->v_shared.clear(); + memset(&stl->stats, 0, sizeof(stl_stats)); + stl->stats.volume = -1.0; +} + +void stl_close(stl_file *stl) +{ + assert(stl->fp == nullptr); + assert(stl->heads.empty()); + assert(stl->tail == nullptr); + stl_initialize(stl); } #ifndef BOOST_LITTLE_ENDIAN @@ -175,20 +191,14 @@ stl_count_facets(stl_file *stl, const char *file) { stl->stats.original_num_facets = stl->stats.number_of_facets; } -void -stl_allocate(stl_file *stl) { - if (stl->error) return; - - /* Allocate memory for the entire .STL file */ - stl->facet_start = (stl_facet*)calloc(stl->stats.number_of_facets, - sizeof(stl_facet)); - if(stl->facet_start == NULL) perror("stl_initialize"); - stl->stats.facets_malloced = stl->stats.number_of_facets; - - /* Allocate memory for the neighbors list */ - stl->neighbors_start = (stl_neighbors*) - calloc(stl->stats.number_of_facets, sizeof(stl_neighbors)); - if(stl->facet_start == NULL) perror("stl_initialize"); +void stl_allocate(stl_file *stl) +{ + if (stl->error) + return; + // Allocate memory for the entire .STL file. + stl->facet_start.assign(stl->stats.number_of_facets, stl_facet()); + // Allocate memory for the neighbors list. + stl->neighbors_start.assign(stl->stats.number_of_facets, stl_neighbors()); } void @@ -237,23 +247,14 @@ stl_open_merge(stl_file *stl, char *file_to_merge) { stl->fp=origFp; } -extern void -stl_reallocate(stl_file *stl) { - if (stl->error) return; - /* Reallocate more memory for the .STL file(s) */ - stl->facet_start = (stl_facet*)realloc(stl->facet_start, stl->stats.number_of_facets * - sizeof(stl_facet)); - if(stl->facet_start == NULL) perror("stl_initialize"); - stl->stats.facets_malloced = stl->stats.number_of_facets; - - /* Reallocate more memory for the neighbors list */ - stl->neighbors_start = (stl_neighbors*) - realloc(stl->neighbors_start, stl->stats.number_of_facets * - sizeof(stl_neighbors)); - if(stl->facet_start == NULL) perror("stl_initialize"); +void stl_reallocate(stl_file *stl) +{ + if (stl->error) + return; + stl->facet_start.resize(stl->stats.number_of_facets); + stl->neighbors_start.resize(stl->stats.number_of_facets); } - /* Reads the contents of the file pointed to by stl->fp into the stl structure, starting at facet first_facet. The second argument says if it's our first time running this for the stl and therefore we should reset our max and min stats. */ @@ -366,20 +367,3 @@ void stl_facet_stats(stl_file *stl, stl_facet facet, bool &first) stl->stats.max = stl->stats.max.cwiseMax(facet.vertex[i]); } } - -void stl_close(stl_file *stl) -{ - assert(stl->fp == nullptr); - assert(stl->heads == nullptr); - assert(stl->tail == nullptr); - - if (stl->facet_start != NULL) - free(stl->facet_start); - if (stl->neighbors_start != NULL) - free(stl->neighbors_start); - if (stl->v_indices != NULL) - free(stl->v_indices); - if (stl->v_shared != NULL) - free(stl->v_shared); - memset(stl, 0, sizeof(stl_file)); -} diff --git a/src/admesh/util.cpp b/src/admesh/util.cpp index c2d2c2726..61e0d11e7 100644 --- a/src/admesh/util.cpp +++ b/src/admesh/util.cpp @@ -32,45 +32,39 @@ static float get_area(stl_facet *facet); static float get_volume(stl_file *stl); -void -stl_verify_neighbors(stl_file *stl) { - int i; - int j; - stl_edge edge_a; - stl_edge edge_b; - int neighbor; - int vnot; +void stl_verify_neighbors(stl_file *stl) +{ + if (stl->error) + return; - if (stl->error) return; + stl->stats.backwards_edges = 0; - stl->stats.backwards_edges = 0; - - for(i = 0; i < stl->stats.number_of_facets; i++) { - for(j = 0; j < 3; j++) { - edge_a.p1 = stl->facet_start[i].vertex[j]; - edge_a.p2 = stl->facet_start[i].vertex[(j + 1) % 3]; - neighbor = stl->neighbors_start[i].neighbor[j]; - vnot = stl->neighbors_start[i].which_vertex_not[j]; - - if(neighbor == -1) - continue; /* this edge has no neighbor... Continue. */ - if(vnot < 3) { - edge_b.p1 = stl->facet_start[neighbor].vertex[(vnot + 2) % 3]; - edge_b.p2 = stl->facet_start[neighbor].vertex[(vnot + 1) % 3]; - } else { - stl->stats.backwards_edges += 1; - edge_b.p1 = stl->facet_start[neighbor].vertex[(vnot + 1) % 3]; - edge_b.p2 = stl->facet_start[neighbor].vertex[(vnot + 2) % 3]; - } - if (edge_a.p1 != edge_b.p1 || edge_a.p2 != edge_b.p2) { - /* These edges should match but they don't. Print results. */ - printf("edge %d of facet %d doesn't match edge %d of facet %d\n", - j, i, vnot + 1, neighbor); - stl_write_facet(stl, (char*)"first facet", i); - stl_write_facet(stl, (char*)"second facet", neighbor); - } - } - } + for (uint32_t i = 0; i < stl->stats.number_of_facets; ++ i) { + for (int j = 0; j < 3; ++ j) { + stl_edge edge_a; + edge_a.p1 = stl->facet_start[i].vertex[j]; + edge_a.p2 = stl->facet_start[i].vertex[(j + 1) % 3]; + int neighbor = stl->neighbors_start[i].neighbor[j]; + if (neighbor == -1) + continue; // this edge has no neighbor... Continue. + int vnot = stl->neighbors_start[i].which_vertex_not[j]; + stl_edge edge_b; + if (vnot < 3) { + edge_b.p1 = stl->facet_start[neighbor].vertex[(vnot + 2) % 3]; + edge_b.p2 = stl->facet_start[neighbor].vertex[(vnot + 1) % 3]; + } else { + stl->stats.backwards_edges += 1; + edge_b.p1 = stl->facet_start[neighbor].vertex[(vnot + 1) % 3]; + edge_b.p2 = stl->facet_start[neighbor].vertex[(vnot + 2) % 3]; + } + if (edge_a.p1 != edge_b.p1 || edge_a.p2 != edge_b.p2) { + // These edges should match but they don't. Print results. + printf("edge %d of facet %d doesn't match edge %d of facet %d\n", j, i, vnot + 1, neighbor); + stl_write_facet(stl, (char*)"first facet", i); + stl_write_facet(stl, (char*)"second facet", neighbor); + } + } + } } void stl_translate(stl_file *stl, float x, float y, float z) @@ -263,21 +257,19 @@ void stl_mirror_yz(stl_file *stl) void stl_mirror_xz(stl_file *stl) { - if (stl->error) - return; + if (stl->error) + return; - for (int i = 0; i < stl->stats.number_of_facets; i++) { - for (int j = 0; j < 3; j++) { - stl->facet_start[i].vertex[j](1) *= -1.0; - } - } - float temp_size = stl->stats.min(1); - stl->stats.min(1) = stl->stats.max(1); - stl->stats.max(1) = temp_size; - stl->stats.min(1) *= -1.0; - stl->stats.max(1) *= -1.0; - stl_reverse_all_facets(stl); - stl->stats.facets_reversed -= stl->stats.number_of_facets; /* for not altering stats */ + for (uint32_t i = 0; i < stl->stats.number_of_facets; ++ i) + for (int j = 0; j < 3; ++ j) + stl->facet_start[i].vertex[j](1) *= -1.0; + float temp_size = stl->stats.min(1); + stl->stats.min(1) = stl->stats.max(1); + stl->stats.max(1) = temp_size; + stl->stats.min(1) *= -1.0; + stl->stats.max(1) *= -1.0; + stl_reverse_all_facets(stl); + stl->stats.facets_reversed -= stl->stats.number_of_facets; // for not altering stats } static float get_volume(stl_file *stl) @@ -463,18 +455,18 @@ bool stl_validate(stl_file *stl) { assert(! stl->error); assert(stl->fp == nullptr); - assert(stl->facet_start != nullptr); - assert(stl->heads == nullptr); + assert(! stl->facet_start.empty()); + assert(stl->heads.empty()); assert(stl->tail == nullptr); - assert(stl->neighbors_start != nullptr); - assert((stl->v_indices == nullptr) == (stl->v_shared == nullptr)); + assert(! stl->neighbors_start.empty()); + assert((stl->v_indices.empty()) == (stl->v_shared.empty())); assert(stl->stats.number_of_facets > 0); #ifdef _DEBUG // Verify validity of neighborship data. for (int facet_idx = 0; facet_idx < (int)stl->stats.number_of_facets; ++ facet_idx) { const stl_neighbors &nbr = stl->neighbors_start[facet_idx]; - const int *vertices = (stl->v_indices == nullptr) ? nullptr : stl->v_indices[facet_idx].vertex; + const int *vertices = (stl->v_indices.empty()) ? nullptr : stl->v_indices[facet_idx].vertex; for (int nbr_idx = 0; nbr_idx < 3; ++ nbr_idx) { int nbr_face = stl->neighbors_start[facet_idx].neighbor[nbr_idx]; assert(nbr_face < (int)stl->stats.number_of_facets); diff --git a/src/libslic3r/Format/3mf.cpp b/src/libslic3r/Format/3mf.cpp index 38b34c462..c3916a14e 100644 --- a/src/libslic3r/Format/3mf.cpp +++ b/src/libslic3r/Format/3mf.cpp @@ -1885,7 +1885,7 @@ namespace Slic3r { volume->mesh.repair(); stl_file& stl = volume->mesh.stl; - if (stl.v_shared == nullptr) + if (stl.v_shared.empty()) stl_generate_shared_vertices(&stl); if (stl.stats.shared_vertices == 0) diff --git a/src/libslic3r/Format/AMF.cpp b/src/libslic3r/Format/AMF.cpp index d26b5f3ed..f48b5b58c 100644 --- a/src/libslic3r/Format/AMF.cpp +++ b/src/libslic3r/Format/AMF.cpp @@ -926,7 +926,7 @@ bool store_amf(const char *path, Model *model, const DynamicPrintConfig *config) if (! volume->mesh.repaired) throw std::runtime_error("store_amf() requires repair()"); auto &stl = volume->mesh.stl; - if (stl.v_shared == nullptr) + if (stl.v_shared.empty()) stl_generate_shared_vertices(&stl); const Transform3d& matrix = volume->get_matrix(); for (size_t i = 0; i < stl.stats.shared_vertices; ++i) { diff --git a/src/libslic3r/Format/PRUS.cpp b/src/libslic3r/Format/PRUS.cpp index 502cac6e9..d983b1098 100644 --- a/src/libslic3r/Format/PRUS.cpp +++ b/src/libslic3r/Format/PRUS.cpp @@ -167,10 +167,10 @@ static void extract_model_from_archive( stl.stats.original_num_facets = header.nTriangles; stl_allocate(&stl); if (header.nTriangles > 0 && data.size() == 50 * header.nTriangles + sizeof(StlHeader)) { - memcpy((char*)stl.facet_start, data.data() + sizeof(StlHeader), 50 * header.nTriangles); + memcpy((char*)stl.facet_start.data(), data.data() + sizeof(StlHeader), 50 * header.nTriangles); if (sizeof(stl_facet) > SIZEOF_STL_FACET) { // The stl.facet_start is not packed tightly. Unpack the array of stl_facets. - unsigned char *data = (unsigned char*)stl.facet_start; + unsigned char *data = (unsigned char*)stl.facet_start.data(); for (size_t i = header.nTriangles - 1; i > 0; -- i) memmove(data + i * sizeof(stl_facet), data + i * SIZEOF_STL_FACET, SIZEOF_STL_FACET); } @@ -257,7 +257,7 @@ static void extract_model_from_archive( stl.stats.number_of_facets = (uint32_t)facets.size(); stl.stats.original_num_facets = (int)facets.size(); stl_allocate(&stl); - memcpy((void*)stl.facet_start, facets.data(), facets.size() * 50); + memcpy((void*)stl.facet_start.data(), facets.data(), facets.size() * 50); stl_get_size(&stl); mesh.repair(); // Add a mesh to a model. diff --git a/src/libslic3r/Model.cpp b/src/libslic3r/Model.cpp index 3b1bd5df2..64fbb9a2a 100644 --- a/src/libslic3r/Model.cpp +++ b/src/libslic3r/Model.cpp @@ -910,18 +910,16 @@ Polygon ModelObject::convex_hull_2d(const Transform3d &trafo_instance) const if (v->is_model_part()) { const stl_file &stl = v->mesh.stl; Transform3d trafo = trafo_instance * v->get_matrix(); - if (stl.v_shared == nullptr) { + if (stl.v_shared.empty()) { // Using the STL faces. - for (unsigned int i = 0; i < stl.stats.number_of_facets; ++ i) { - const stl_facet &facet = stl.facet_start[i]; + for (const stl_facet &facet : stl.facet_start) for (size_t j = 0; j < 3; ++ j) { Vec3d p = trafo * facet.vertex[j].cast(); pts.emplace_back(coord_t(scale_(p.x())), coord_t(scale_(p.y()))); } - } } else { // Using the shared vertices should be a bit quicker than using the STL faces. - for (int i = 0; i < stl.stats.shared_vertices; ++ i) { + for (int i = 0; i < stl.stats.shared_vertices; ++ i) { Vec3d p = trafo * stl.v_shared[i].cast(); pts.emplace_back(coord_t(scale_(p.x())), coord_t(scale_(p.y()))); } @@ -1347,13 +1345,9 @@ double ModelObject::get_instance_min_z(size_t instance_idx) const Transform3d mv = mi * v->get_matrix(); const TriangleMesh& hull = v->get_convex_hull(); - for (uint32_t f = 0; f < hull.stl.stats.number_of_facets; ++f) - { - const stl_facet* facet = hull.stl.facet_start + f; - min_z = std::min(min_z, Vec3d::UnitZ().dot(mv * facet->vertex[0].cast())); - min_z = std::min(min_z, Vec3d::UnitZ().dot(mv * facet->vertex[1].cast())); - min_z = std::min(min_z, Vec3d::UnitZ().dot(mv * facet->vertex[2].cast())); - } + for (const stl_facet &facet : hull.stl.facet_start) + for (int i = 0; i < 3; ++ i) + min_z = std::min(min_z, (mv * facet.vertex[i].cast()).z()); } return min_z + inst->get_offset(Z); diff --git a/src/libslic3r/SLA/SLASupportTreeIGL.cpp b/src/libslic3r/SLA/SLASupportTreeIGL.cpp index c368b8604..1609b9ac4 100644 --- a/src/libslic3r/SLA/SLASupportTreeIGL.cpp +++ b/src/libslic3r/SLA/SLASupportTreeIGL.cpp @@ -121,19 +121,10 @@ EigenMesh3D::EigenMesh3D(const TriangleMesh& tmesh): m_aabb(new AABBImpl()) { V.resize(3*stl.stats.number_of_facets, 3); F.resize(stl.stats.number_of_facets, 3); for (unsigned int i = 0; i < stl.stats.number_of_facets; ++i) { - const stl_facet* facet = stl.facet_start+i; - V(3*i+0, 0) = double(facet->vertex[0](0)); - V(3*i+0, 1) = double(facet->vertex[0](1)); - V(3*i+0, 2) = double(facet->vertex[0](2)); - - V(3*i+1, 0) = double(facet->vertex[1](0)); - V(3*i+1, 1) = double(facet->vertex[1](1)); - V(3*i+1, 2) = double(facet->vertex[1](2)); - - V(3*i+2, 0) = double(facet->vertex[2](0)); - V(3*i+2, 1) = double(facet->vertex[2](1)); - V(3*i+2, 2) = double(facet->vertex[2](2)); - + const stl_facet &facet = stl.facet_start[i]; + V.block<1, 3>(3 * i + 0, 0) = facet.vertex[0].cast(); + V.block<1, 3>(3 * i + 1, 0) = facet.vertex[1].cast(); + V.block<1, 3>(3 * i + 2, 0) = facet.vertex[2].cast(); F(i, 0) = int(3*i+0); F(i, 1) = int(3*i+1); F(i, 2) = int(3*i+2); diff --git a/src/libslic3r/SlicingAdaptive.cpp b/src/libslic3r/SlicingAdaptive.cpp index 2ef4aec8c..ad03b550b 100644 --- a/src/libslic3r/SlicingAdaptive.cpp +++ b/src/libslic3r/SlicingAdaptive.cpp @@ -27,8 +27,8 @@ void SlicingAdaptive::prepare() nfaces_total += (*it_mesh)->stl.stats.number_of_facets; m_faces.reserve(nfaces_total); for (std::vector::const_iterator it_mesh = m_meshes.begin(); it_mesh != m_meshes.end(); ++ it_mesh) - for (int i = 0; i < (*it_mesh)->stl.stats.number_of_facets; ++ i) - m_faces.push_back((*it_mesh)->stl.facet_start + i); + for (const stl_facet &face : (*it_mesh)->stl.facet_start) + m_faces.emplace_back(&face); // 2) Sort faces lexicographically by their Z span. std::sort(m_faces.begin(), m_faces.end(), [](const stl_facet *f1, const stl_facet *f2) { diff --git a/src/libslic3r/TriangleMesh.cpp b/src/libslic3r/TriangleMesh.cpp index b7c6c07a7..ac23abd26 100644 --- a/src/libslic3r/TriangleMesh.cpp +++ b/src/libslic3r/TriangleMesh.cpp @@ -51,7 +51,7 @@ TriangleMesh::TriangleMesh(const Pointf3s &points, const std::vector& f stl.stats.type = inmemory; // count facets and allocate memory - stl.stats.number_of_facets = facets.size(); + stl.stats.number_of_facets = (uint32_t)facets.size(); stl.stats.original_num_facets = stl.stats.number_of_facets; stl_allocate(&stl); @@ -78,25 +78,14 @@ TriangleMesh& TriangleMesh::operator=(const TriangleMesh &other) stl_close(&this->stl); this->stl = other.stl; this->repaired = other.repaired; - this->stl.heads = nullptr; + this->stl.heads.clear(); this->stl.tail = nullptr; this->stl.error = other.stl.error; - if (other.stl.facet_start != nullptr) { - this->stl.facet_start = (stl_facet*)calloc(other.stl.stats.number_of_facets, sizeof(stl_facet)); - std::copy(other.stl.facet_start, other.stl.facet_start + other.stl.stats.number_of_facets, this->stl.facet_start); - } - if (other.stl.neighbors_start != nullptr) { - this->stl.neighbors_start = (stl_neighbors*)calloc(other.stl.stats.number_of_facets, sizeof(stl_neighbors)); - std::copy(other.stl.neighbors_start, other.stl.neighbors_start + other.stl.stats.number_of_facets, this->stl.neighbors_start); - } - if (other.stl.v_indices != nullptr) { - this->stl.v_indices = (v_indices_struct*)calloc(other.stl.stats.number_of_facets, sizeof(v_indices_struct)); - std::copy(other.stl.v_indices, other.stl.v_indices + other.stl.stats.number_of_facets, this->stl.v_indices); - } - if (other.stl.v_shared != nullptr) { - this->stl.v_shared = (stl_vertex*)calloc(other.stl.stats.shared_vertices, sizeof(stl_vertex)); - std::copy(other.stl.v_shared, other.stl.v_shared + other.stl.stats.shared_vertices, this->stl.v_shared); - } + this->stl.facet_start = other.stl.facet_start; + this->stl.neighbors_start = other.stl.neighbors_start; + this->stl.v_indices = other.stl.v_indices; + this->stl.v_shared = other.stl.v_shared; + this->stl.stats = other.stl.stats; return *this; } @@ -125,8 +114,8 @@ void TriangleMesh::repair() // checking nearby //int last_edges_fixed = 0; - float tolerance = stl.stats.shortest_edge; - float increment = stl.stats.bounding_diameter / 10000.0; + float tolerance = (float)stl.stats.shortest_edge; + float increment = (float)stl.stats.bounding_diameter / 10000.0f; int iterations = 2; if (stl.stats.connected_facets_3_edge < (int)stl.stats.number_of_facets) { for (int i = 0; i < iterations; i++) { @@ -444,7 +433,7 @@ TriangleMeshPtrs TriangleMesh::split() const TriangleMesh* mesh = new TriangleMesh; meshes.emplace_back(mesh); mesh->stl.stats.type = inmemory; - mesh->stl.stats.number_of_facets = facets.size(); + mesh->stl.stats.number_of_facets = (uint32_t)facets.size(); mesh->stl.stats.original_num_facets = mesh->stl.stats.number_of_facets; stl_clear_error(&mesh->stl); stl_allocate(&mesh->stl); @@ -486,13 +475,12 @@ ExPolygons TriangleMesh::horizontal_projection() const { Polygons pp; pp.reserve(this->stl.stats.number_of_facets); - for (uint32_t i = 0; i < this->stl.stats.number_of_facets; ++ i) { - stl_facet* facet = &this->stl.facet_start[i]; + for (const stl_facet &facet : this->stl.facet_start) { Polygon p; p.points.resize(3); - p.points[0] = Point::new_scale(facet->vertex[0](0), facet->vertex[0](1)); - p.points[1] = Point::new_scale(facet->vertex[1](0), facet->vertex[1](1)); - p.points[2] = Point::new_scale(facet->vertex[2](0), facet->vertex[2](1)); + p.points[0] = Point::new_scale(facet.vertex[0](0), facet.vertex[0](1)); + p.points[1] = Point::new_scale(facet.vertex[1](0), facet.vertex[1](1)); + p.points[2] = Point::new_scale(facet.vertex[2](0), facet.vertex[2](1)); p.make_counter_clockwise(); // do this after scaling, as winding order might change while doing that pp.emplace_back(p); } @@ -526,17 +514,15 @@ BoundingBoxf3 TriangleMesh::bounding_box() const BoundingBoxf3 TriangleMesh::transformed_bounding_box(const Transform3d &trafo) const { BoundingBoxf3 bbox; - if (stl.v_shared == nullptr) { + if (stl.v_shared.empty()) { // Using the STL faces. - for (size_t i = 0; i < this->facets_count(); ++ i) { - const stl_facet &facet = this->stl.facet_start[i]; + for (const stl_facet &facet : this->stl.facet_start) for (size_t j = 0; j < 3; ++ j) bbox.merge(trafo * facet.vertex[j].cast()); - } } else { // Using the shared vertices should be a bit quicker than using the STL faces. - for (int i = 0; i < stl.stats.shared_vertices; ++ i) - bbox.merge(trafo * this->stl.v_shared[i].cast()); + for (const stl_vertex &v : this->stl.v_shared) + bbox.merge(trafo * v.cast()); } return bbox; } @@ -551,18 +537,12 @@ TriangleMesh TriangleMesh::convex_hull_3d() const std::vector src_vertices; // We will now fill the vector with input points for computation: - stl_facet* facet_ptr = stl.facet_start; - while (facet_ptr < stl.facet_start + stl.stats.number_of_facets) - { - for (int i = 0; i < 3; ++i) - { - const stl_vertex& v = facet_ptr->vertex[i]; + for (const stl_facet &facet : stl.facet_start) + for (int i = 0; i < 3; ++ i) { + const stl_vertex& v = facet.vertex[i]; src_vertices.emplace_back(v(0), v(1), v(2)); } - facet_ptr += 1; - } - // The qhull call: orgQhull::Qhull qhull; qhull.disableOutputStream(); // we want qhull to be quiet @@ -606,7 +586,7 @@ void TriangleMesh::require_shared_vertices() assert(stl_validate(&this->stl)); if (! this->repaired) this->repair(); - if (this->stl.v_shared == nullptr) { + if (this->stl.v_shared.empty()) { BOOST_LOG_TRIVIAL(trace) << "TriangleMeshSlicer::require_shared_vertices - stl_generate_shared_vertices"; stl_generate_shared_vertices(&(this->stl)); } @@ -622,10 +602,9 @@ void TriangleMeshSlicer::init(const TriangleMesh *_mesh, throw_on_cancel_callbac throw_on_cancel(); facets_edges.assign(_mesh->stl.stats.number_of_facets * 3, -1); - v_scaled_shared.assign(_mesh->stl.v_shared, _mesh->stl.v_shared + _mesh->stl.stats.shared_vertices); - // Scale the copied vertices. - for (int i = 0; i < this->mesh->stl.stats.shared_vertices; ++ i) - this->v_scaled_shared[i] *= float(1. / SCALING_FACTOR); + v_scaled_shared.assign(_mesh->stl.v_shared.size(), stl_vertex()); + for (size_t i = 0; i < v_scaled_shared.size(); ++ i) + this->v_scaled_shared[i] = _mesh->stl.v_shared[i] / float(SCALING_FACTOR); // Create a mapping from triangle edge into face. struct EdgeToFace { @@ -814,7 +793,7 @@ void TriangleMeshSlicer::slice(const std::vector &z, std::vector* lines, boost::mutex* lines_mutex, const std::vector &z) const { - const stl_facet &facet = m_use_quaternion ? this->mesh->stl.facet_start[facet_idx].rotated(m_quaternion) : this->mesh->stl.facet_start[facet_idx]; + const stl_facet &facet = m_use_quaternion ? (this->mesh->stl.facet_start.data() + facet_idx)->rotated(m_quaternion) : *(this->mesh->stl.facet_start.data() + facet_idx); // find facet extents const float min_z = fminf(facet.vertex[0](2), fminf(facet.vertex[1](2), facet.vertex[2](2))); @@ -1710,7 +1689,7 @@ void TriangleMeshSlicer::cut(float z, TriangleMesh* upper, TriangleMesh* lower) BOOST_LOG_TRIVIAL(trace) << "TriangleMeshSlicer::cut - slicing object"; float scaled_z = scale_(z); for (uint32_t facet_idx = 0; facet_idx < this->mesh->stl.stats.number_of_facets; ++ facet_idx) { - stl_facet* facet = &this->mesh->stl.facet_start[facet_idx]; + const stl_facet* facet = &this->mesh->stl.facet_start[facet_idx]; // find facet extents float min_z = std::min(facet->vertex[0](2), std::min(facet->vertex[1](2), facet->vertex[2](2))); @@ -1901,10 +1880,10 @@ TriangleMesh make_cylinder(double r, double h, double fa) //FIXME better to discretize an Icosahedron recursively http://www.songho.ca/opengl/gl_sphere.html TriangleMesh make_sphere(double radius, double fa) { - int sectorCount = ceil(2. * M_PI / fa); - int stackCount = ceil(M_PI / fa); - float sectorStep = 2. * M_PI / sectorCount; - float stackStep = M_PI / stackCount; + int sectorCount = int(ceil(2. * M_PI / fa)); + int stackCount = int(ceil(M_PI / fa)); + float sectorStep = float(2. * M_PI / sectorCount); + float stackStep = float(M_PI / stackCount); Pointf3s vertices; vertices.reserve((stackCount - 1) * sectorCount + 2); diff --git a/src/libslic3r/TriangleMesh.hpp b/src/libslic3r/TriangleMesh.hpp index c284f6482..4de1f5989 100644 --- a/src/libslic3r/TriangleMesh.hpp +++ b/src/libslic3r/TriangleMesh.hpp @@ -58,7 +58,7 @@ public: TriangleMeshPtrs split() const; void merge(const TriangleMesh &mesh); ExPolygons horizontal_projection() const; - const float* first_vertex() const { return this->stl.facet_start ? &this->stl.facet_start->vertex[0](0) : nullptr; } + const float* first_vertex() const { return this->stl.facet_start.empty() ? nullptr : &this->stl.facet_start.front().vertex[0](0); } // 2D convex hull of a 3D mesh projected into the Z=0 plane. Polygon convex_hull(); BoundingBoxf3 bounding_box() const; @@ -69,7 +69,7 @@ public: void reset_repair_stats(); bool needed_repair() const; void require_shared_vertices(); - bool has_shared_vertices() const { return stl.v_shared != NULL; } + bool has_shared_vertices() const { return ! stl.v_shared.empty(); } size_t facets_count() const { return this->stl.stats.number_of_facets; } bool empty() const { return this->facets_count() == 0; } bool is_splittable() const; diff --git a/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp b/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp index d118a6877..ae017f7d1 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp @@ -396,10 +396,10 @@ void GLGizmoSlaSupports::update_mesh() V.resize(3 * stl.stats.number_of_facets, 3); F.resize(stl.stats.number_of_facets, 3); for (unsigned int i=0; ivertex[0](0); V(3*i+0, 1) = facet->vertex[0](1); V(3*i+0, 2) = facet->vertex[0](2); - V(3*i+1, 0) = facet->vertex[1](0); V(3*i+1, 1) = facet->vertex[1](1); V(3*i+1, 2) = facet->vertex[1](2); - V(3*i+2, 0) = facet->vertex[2](0); V(3*i+2, 1) = facet->vertex[2](1); V(3*i+2, 2) = facet->vertex[2](2); + const stl_facet &facet = stl.facet_start[i]; + V.block<1, 3>(3 * i + 0, 0) = facet.vertex[0]; + V.block<1, 3>(3 * i + 1, 0) = facet.vertex[1]; + V.block<1, 3>(3 * i + 2, 0) = facet.vertex[2]; F(i, 0) = 3*i+0; F(i, 1) = 3*i+1; F(i, 2) = 3*i+2;