mirror of
				https://github.com/SoftFever/OrcaSlicer.git
				synced 2025-10-31 04:31:15 -06:00 
			
		
		
		
	Improvements of admesh robustness when loading and fixing STLs.
https://github.com/prusa3d/Slic3r/issues/33
This commit is contained in:
		
							parent
							
								
									d1d6e907c5
								
							
						
					
					
						commit
						52de3940fe
					
				
					 3 changed files with 94 additions and 97 deletions
				
			
		|  | @ -106,53 +106,42 @@ stl_check_facets_exact(stl_file *stl) { | |||
|     } | ||||
|   } | ||||
|   stl_free_edges(stl); | ||||
| 
 | ||||
| #if 0 | ||||
|   printf("Number of faces: %d, number of manifold edges: %d, number of connected edges: %d, number of unconnected edges: %d\r\n",  | ||||
|     stl->stats.number_of_facets, stl->stats.number_of_facets * 3,  | ||||
|     stl->stats.connected_edges, stl->stats.number_of_facets * 3 - stl->stats.connected_edges); | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| stl_load_edge_exact(stl_file *stl, stl_hash_edge *edge, | ||||
|                     stl_vertex *a, stl_vertex *b) { | ||||
| 
 | ||||
|   float diff_x; | ||||
|   float diff_y; | ||||
|   float diff_z; | ||||
|   float max_diff; | ||||
| 
 | ||||
|   if (stl->error) return; | ||||
| 
 | ||||
|   diff_x = ABS(a->x - b->x); | ||||
|   diff_y = ABS(a->y - b->y); | ||||
|   diff_z = ABS(a->z - b->z); | ||||
|   max_diff = STL_MAX(diff_x, diff_y); | ||||
|   max_diff = STL_MAX(diff_z, max_diff); | ||||
|   stl->stats.shortest_edge = STL_MIN(max_diff, stl->stats.shortest_edge); | ||||
|   { | ||||
|     float diff_x = ABS(a->x - b->x); | ||||
|     float diff_y = ABS(a->y - b->y); | ||||
|     float diff_z = ABS(a->z - b->z); | ||||
|     float max_diff = STL_MAX(diff_x, diff_y); | ||||
|     max_diff = STL_MAX(diff_z, max_diff); | ||||
|     stl->stats.shortest_edge = STL_MIN(max_diff, stl->stats.shortest_edge); | ||||
|   } | ||||
| 
 | ||||
|   if(diff_x == max_diff) { | ||||
|     if(a->x > b->x) { | ||||
|       memcpy(&edge->key[0], a, sizeof(stl_vertex)); | ||||
|       memcpy(&edge->key[3], b, sizeof(stl_vertex)); | ||||
|     } else { | ||||
|       memcpy(&edge->key[0], b, sizeof(stl_vertex)); | ||||
|       memcpy(&edge->key[3], a, sizeof(stl_vertex)); | ||||
|       edge->which_edge += 3; /* this edge is loaded backwards */ | ||||
|     } | ||||
|   } else if(diff_y == max_diff) { | ||||
|     if(a->y > b->y) { | ||||
|       memcpy(&edge->key[0], a, sizeof(stl_vertex)); | ||||
|       memcpy(&edge->key[3], b, sizeof(stl_vertex)); | ||||
|     } else { | ||||
|       memcpy(&edge->key[0], b, sizeof(stl_vertex)); | ||||
|       memcpy(&edge->key[3], a, sizeof(stl_vertex)); | ||||
|       edge->which_edge += 3; /* this edge is loaded backwards */ | ||||
|     } | ||||
|   // Ensure identical vertex ordering of equal edges.
 | ||||
|   // This method is numerically robust.
 | ||||
|   if ((a->x != b->x) ?  | ||||
|         (a->x < b->x) :  | ||||
|         ((a->y != b->y) ?  | ||||
|             (a->y < b->y) :  | ||||
|             (a->z < b->z))) { | ||||
|     memcpy(&edge->key[0], a, sizeof(stl_vertex)); | ||||
|     memcpy(&edge->key[3], b, sizeof(stl_vertex)); | ||||
|   } else { | ||||
|     if(a->z > b->z) { | ||||
|       memcpy(&edge->key[0], a, sizeof(stl_vertex)); | ||||
|       memcpy(&edge->key[3], b, sizeof(stl_vertex)); | ||||
|     } else { | ||||
|       memcpy(&edge->key[0], b, sizeof(stl_vertex)); | ||||
|       memcpy(&edge->key[3], a, sizeof(stl_vertex)); | ||||
|       edge->which_edge += 3; /* this edge is loaded backwards */ | ||||
|     } | ||||
|     memcpy(&edge->key[0], b, sizeof(stl_vertex)); | ||||
|     memcpy(&edge->key[3], a, sizeof(stl_vertex)); | ||||
|     edge->which_edge += 3; /* this edge is loaded backwards */ | ||||
|   } | ||||
| } | ||||
| 
 | ||||
|  | @ -309,26 +298,17 @@ stl_check_facets_nearby(stl_file *stl, float tolerance) { | |||
| static int | ||||
| stl_load_edge_nearby(stl_file *stl, stl_hash_edge *edge, | ||||
|                      stl_vertex *a, stl_vertex *b, float tolerance) { | ||||
|   float diff_x; | ||||
|   float diff_y; | ||||
|   float diff_z; | ||||
|   float max_diff; | ||||
|   unsigned vertex1[3]; | ||||
|   unsigned vertex2[3]; | ||||
| 
 | ||||
| 
 | ||||
|   diff_x = ABS(a->x - b->x); | ||||
|   diff_y = ABS(a->y - b->y); | ||||
|   diff_z = ABS(a->z - b->z); | ||||
|   max_diff = STL_MAX(diff_x, diff_y); | ||||
|   max_diff = STL_MAX(diff_z, max_diff); | ||||
| 
 | ||||
|   vertex1[0] = (unsigned)((a->x - stl->stats.min.x) / tolerance); | ||||
|   vertex1[1] = (unsigned)((a->y - stl->stats.min.y) / tolerance); | ||||
|   vertex1[2] = (unsigned)((a->z - stl->stats.min.z) / tolerance); | ||||
|   vertex2[0] = (unsigned)((b->x - stl->stats.min.x) / tolerance); | ||||
|   vertex2[1] = (unsigned)((b->y - stl->stats.min.y) / tolerance); | ||||
|   vertex2[2] = (unsigned)((b->z - stl->stats.min.z) / tolerance); | ||||
|   // Index of a grid cell spaced by tolerance.
 | ||||
|   uint32_t vertex1[3] = { | ||||
|     (uint32_t)((a->x - stl->stats.min.x) / tolerance), | ||||
|     (uint32_t)((a->y - stl->stats.min.y) / tolerance), | ||||
|     (uint32_t)((a->z - stl->stats.min.z) / tolerance) | ||||
|   }; | ||||
|   uint32_t vertex2[3] = { | ||||
|     (uint32_t)((b->x - stl->stats.min.x) / tolerance), | ||||
|     (uint32_t)((b->y - stl->stats.min.y) / tolerance), | ||||
|     (uint32_t)((b->z - stl->stats.min.z) / tolerance) | ||||
|   }; | ||||
| 
 | ||||
|   if(   (vertex1[0] == vertex2[0]) | ||||
|         && (vertex1[1] == vertex2[1]) | ||||
|  | @ -337,33 +317,19 @@ stl_load_edge_nearby(stl_file *stl, stl_hash_edge *edge, | |||
|     return 0; | ||||
|   } | ||||
| 
 | ||||
|   if(diff_x == max_diff) { | ||||
|     if(a->x > b->x) { | ||||
|       memcpy(&edge->key[0], vertex1, sizeof(stl_vertex)); | ||||
|       memcpy(&edge->key[3], vertex2, sizeof(stl_vertex)); | ||||
|     } else { | ||||
|       memcpy(&edge->key[0], vertex2, sizeof(stl_vertex)); | ||||
|       memcpy(&edge->key[3], vertex1, sizeof(stl_vertex)); | ||||
|       edge->which_edge += 3; /* this edge is loaded backwards */ | ||||
|     } | ||||
|   } else if(diff_y == max_diff) { | ||||
|     if(a->y > b->y) { | ||||
|       memcpy(&edge->key[0], vertex1, sizeof(stl_vertex)); | ||||
|       memcpy(&edge->key[3], vertex2, sizeof(stl_vertex)); | ||||
|     } else { | ||||
|       memcpy(&edge->key[0], vertex2, sizeof(stl_vertex)); | ||||
|       memcpy(&edge->key[3], vertex1, sizeof(stl_vertex)); | ||||
|       edge->which_edge += 3; /* this edge is loaded backwards */ | ||||
|     } | ||||
|   // Ensure identical vertex ordering of edges, which vertices land into equal grid cells.
 | ||||
|   // This method is numerically robust.
 | ||||
|   if ((vertex1[0] != vertex2[0]) ?  | ||||
|         (vertex1[0] < vertex2[0]) :  | ||||
|         ((vertex1[1] != vertex2[1]) ?  | ||||
|             (vertex1[1] < vertex2[1]) :  | ||||
|             (vertex1[2] < vertex2[2]))) { | ||||
|     memcpy(&edge->key[0], vertex1, sizeof(stl_vertex)); | ||||
|     memcpy(&edge->key[3], vertex2, sizeof(stl_vertex)); | ||||
|   } else { | ||||
|     if(a->z > b->z) { | ||||
|       memcpy(&edge->key[0], vertex1, sizeof(stl_vertex)); | ||||
|       memcpy(&edge->key[3], vertex2, sizeof(stl_vertex)); | ||||
|     } else { | ||||
|       memcpy(&edge->key[0], vertex2, sizeof(stl_vertex)); | ||||
|       memcpy(&edge->key[3], vertex1, sizeof(stl_vertex)); | ||||
|       edge->which_edge += 3; /* this edge is loaded backwards */ | ||||
|     } | ||||
|     memcpy(&edge->key[0], vertex2, sizeof(stl_vertex)); | ||||
|     memcpy(&edge->key[3], vertex1, sizeof(stl_vertex)); | ||||
|     edge->which_edge += 3; /* this edge is loaded backwards */ | ||||
|   } | ||||
|   return 1; | ||||
| } | ||||
|  | @ -564,6 +530,33 @@ stl_change_vertices(stl_file *stl, int facet_num, int vnot, | |||
|         next_edge = pivot_vertex; | ||||
|       } | ||||
|     } | ||||
| #if 0 | ||||
|     if (stl->facet_start[facet_num].vertex[pivot_vertex].x == new_vertex.x && | ||||
|         stl->facet_start[facet_num].vertex[pivot_vertex].y == new_vertex.y && | ||||
|         stl->facet_start[facet_num].vertex[pivot_vertex].z == new_vertex.z) | ||||
|       printf("Changing vertex %f,%f,%f: Same !!!\r\n",  | ||||
|         new_vertex.x, new_vertex.y, new_vertex.z); | ||||
|     else { | ||||
|       if (stl->facet_start[facet_num].vertex[pivot_vertex].x != new_vertex.x) | ||||
|         printf("Changing coordinate x, vertex %e (0x%08x) to %e(0x%08x)\r\n",  | ||||
|           stl->facet_start[facet_num].vertex[pivot_vertex].x, | ||||
|           *reinterpret_cast<const int*>(&stl->facet_start[facet_num].vertex[pivot_vertex].x), | ||||
|           new_vertex.x, | ||||
|           *reinterpret_cast<const int*>(&new_vertex.x)); | ||||
|       if (stl->facet_start[facet_num].vertex[pivot_vertex].y != new_vertex.y) | ||||
|         printf("Changing coordinate x, vertex %e (0x%08x) to %e(0x%08x)\r\n",  | ||||
|           stl->facet_start[facet_num].vertex[pivot_vertex].y, | ||||
|           *reinterpret_cast<const int*>(&stl->facet_start[facet_num].vertex[pivot_vertex].y), | ||||
|           new_vertex.y, | ||||
|           *reinterpret_cast<const int*>(&new_vertex.y)); | ||||
|       if (stl->facet_start[facet_num].vertex[pivot_vertex].z != new_vertex.z) | ||||
|         printf("Changing coordinate x, vertex %e (0x%08x) to %e(0x%08x)\r\n",  | ||||
|           stl->facet_start[facet_num].vertex[pivot_vertex].z, | ||||
|           *reinterpret_cast<const int*>(&stl->facet_start[facet_num].vertex[pivot_vertex].z), | ||||
|           new_vertex.z, | ||||
|           *reinterpret_cast<const int*>(&new_vertex.z)); | ||||
|     } | ||||
| #endif | ||||
|     stl->facet_start[facet_num].vertex[pivot_vertex] = new_vertex; | ||||
|     vnot = stl->neighbors_start[facet_num].which_vertex_not[next_edge]; | ||||
|     facet_num = stl->neighbors_start[facet_num].neighbor[next_edge]; | ||||
|  |  | |||
|  | @ -77,7 +77,10 @@ typedef struct { | |||
| typedef struct stl_hash_edge { | ||||
|   // Key of a hash edge: 2x binary copy of a floating point vertex.
 | ||||
|   uint32_t       key[6]; | ||||
|   // 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; | ||||
|  |  | |||
|  | @ -284,20 +284,6 @@ stl_read(stl_file *stl, int first_facet, int first) { | |||
|         stl->error = 1; | ||||
|         return; | ||||
|       } | ||||
| #if 0 | ||||
|       // Report close to zero vertex coordinates. Due to the nature of the floating point numbers,
 | ||||
|       // close to zero values may be represented with singificantly higher precision than the rest of the vertices.
 | ||||
|       // It may be worth to round these numbers to zero during loading to reduce the number of errors reported
 | ||||
|       // during the STL import.
 | ||||
|       for (size_t j = 0; j < 3; ++ j) { | ||||
|         if (facet.vertex[j].x > -1e-12f && facet.vertex[j].x < 1e-12f) | ||||
|             printf("stl_read: facet %d.x = %e\r\n", j, facet.vertex[j].x); | ||||
|         if (facet.vertex[j].y > -1e-12f && facet.vertex[j].y < 1e-12f) | ||||
|             printf("stl_read: facet %d.y = %e\r\n", j, facet.vertex[j].y); | ||||
|         if (facet.vertex[j].z > -1e-12f && facet.vertex[j].z < 1e-12f) | ||||
|             printf("stl_read: facet %d.z = %e\r\n", j, facet.vertex[j].z); | ||||
|       } | ||||
| #endif | ||||
|     } else | ||||
|       /* Read a single facet from an ASCII .STL file */ | ||||
|     { | ||||
|  | @ -319,6 +305,21 @@ stl_read(stl_file *stl, int first_facet, int first) { | |||
|       } | ||||
|     } | ||||
| 
 | ||||
| #if 0 | ||||
|       // Report close to zero vertex coordinates. Due to the nature of the floating point numbers,
 | ||||
|       // close to zero values may be represented with singificantly higher precision than the rest of the vertices.
 | ||||
|       // It may be worth to round these numbers to zero during loading to reduce the number of errors reported
 | ||||
|       // during the STL import.
 | ||||
|       for (size_t j = 0; j < 3; ++ j) { | ||||
|         if (facet.vertex[j].x > -1e-12f && facet.vertex[j].x < 1e-12f) | ||||
|             printf("stl_read: facet %d.x = %e\r\n", j, facet.vertex[j].x); | ||||
|         if (facet.vertex[j].y > -1e-12f && facet.vertex[j].y < 1e-12f) | ||||
|             printf("stl_read: facet %d.y = %e\r\n", j, facet.vertex[j].y); | ||||
|         if (facet.vertex[j].z > -1e-12f && facet.vertex[j].z < 1e-12f) | ||||
|             printf("stl_read: facet %d.z = %e\r\n", j, facet.vertex[j].z); | ||||
|       } | ||||
| #endif | ||||
| 
 | ||||
| #if 1 | ||||
|     { | ||||
|       // Positive and negative zeros are possible in the floats, which are considered equal by the FP unit.
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 bubnikv
						bubnikv