mirror of
				https://github.com/SoftFever/OrcaSlicer.git
				synced 2025-10-31 20:51:12 -06:00 
			
		
		
		
	This commit is contained in:
		
							parent
							
								
									d7dc04eb57
								
							
						
					
					
						commit
						3bedcf4413
					
				
					 1 changed files with 106 additions and 72 deletions
				
			
		|  | @ -788,15 +788,14 @@ static void thick_lines_to_indexed_vertex_array( | |||
| #define TOP     2 | ||||
| #define BOTTOM  3 | ||||
| 
 | ||||
|     Line prev_line; | ||||
|     // right, left, top, bottom
 | ||||
|     int     idx_prev[4]      = { -1, -1, -1, -1 }; | ||||
|     double  bottom_z_prev    = 0.; | ||||
|     Pointf  b1_prev; | ||||
|     Pointf  b2_prev; | ||||
|     Vectorf v_prev; | ||||
|     int     idx_initial[4]   = { -1, -1, -1, -1 }; | ||||
|     double  width_initial    = 0.; | ||||
|     double  bottom_z_initial = 0.0; | ||||
| 
 | ||||
|     // loop once more in case of closed loops
 | ||||
|     size_t lines_end = closed ? (lines.size() + 1) : lines.size(); | ||||
|  | @ -804,13 +803,18 @@ static void thick_lines_to_indexed_vertex_array( | |||
|         size_t i = (ii == lines.size()) ? 0 : ii; | ||||
|         const Line &line = lines[i]; | ||||
|         double len = unscale(line.length()); | ||||
|         double inv_len = 1.0 / len; | ||||
|         double bottom_z = top_z - heights[i]; | ||||
|         double middle_z = (top_z + bottom_z) / 2.; | ||||
|         double middle_z = 0.5 * (top_z + bottom_z); | ||||
|         double width = widths[i]; | ||||
|          | ||||
| 
 | ||||
|         bool is_first = (ii == 0); | ||||
|         bool is_last = (ii == lines_end - 1); | ||||
|         bool is_closing = closed && is_last; | ||||
| 
 | ||||
|         Vectorf v = Vectorf::new_unscale(line.vector()); | ||||
|         v.scale(1. / len); | ||||
|          | ||||
|         v.scale(inv_len); | ||||
| 
 | ||||
|         Pointf a = Pointf::new_unscale(line.a); | ||||
|         Pointf b = Pointf::new_unscale(line.b); | ||||
|         Pointf a1 = a; | ||||
|  | @ -818,17 +822,19 @@ static void thick_lines_to_indexed_vertex_array( | |||
|         Pointf b1 = b; | ||||
|         Pointf b2 = b; | ||||
|         { | ||||
|             double dist = width / 2.;  // scaled
 | ||||
|             a1.translate(+dist*v.y, -dist*v.x); | ||||
|             a2.translate(-dist*v.y, +dist*v.x); | ||||
|             b1.translate(+dist*v.y, -dist*v.x); | ||||
|             b2.translate(-dist*v.y, +dist*v.x); | ||||
|             double dist = 0.5 * width;  // scaled
 | ||||
|             double dx = dist * v.x; | ||||
|             double dy = dist * v.y; | ||||
|             a1.translate(+dy, -dx); | ||||
|             a2.translate(-dy, +dx); | ||||
|             b1.translate(+dy, -dx); | ||||
|             b2.translate(-dy, +dx); | ||||
|         } | ||||
| 
 | ||||
|         // calculate new XY normals
 | ||||
|         Vector n = line.normal(); | ||||
|         Vectorf3 xy_right_normal = Vectorf3::new_unscale(n.x, n.y, 0); | ||||
|         xy_right_normal.scale(1.f / len); | ||||
|         xy_right_normal.scale(inv_len); | ||||
| 
 | ||||
|         int idx_a[4]; | ||||
|         int idx_b[4]; | ||||
|  | @ -837,14 +843,21 @@ static void thick_lines_to_indexed_vertex_array( | |||
|         bool bottom_z_different = bottom_z_prev != bottom_z; | ||||
|         bottom_z_prev = bottom_z; | ||||
| 
 | ||||
|         if (!is_first && bottom_z_different) | ||||
|         { | ||||
|             // Found a change of the layer thickness -> Add a cap at the end of the previous segment.
 | ||||
|             volume.push_quad(idx_b[BOTTOM], idx_b[LEFT], idx_b[TOP], idx_b[RIGHT]); | ||||
|         } | ||||
| 
 | ||||
|         // Share top / bottom vertices if possible.
 | ||||
|         if (ii == 0) { | ||||
|             idx_a[TOP] = idx_last ++; | ||||
|         if (is_first) { | ||||
|             idx_a[TOP] = idx_last++; | ||||
|             volume.push_geometry(a.x, a.y, top_z   , 0., 0.,  1.);  | ||||
|         } else { | ||||
|             idx_a[TOP] = idx_prev[TOP]; | ||||
|         } | ||||
|         if (ii == 0 || bottom_z_different) { | ||||
| 
 | ||||
|         if (is_first || bottom_z_different) { | ||||
|             // Start of the 1st line segment or a change of the layer thickness while maintaining the print_z.
 | ||||
|             idx_a[BOTTOM] = idx_last ++; | ||||
|             volume.push_geometry(a.x, a.y, bottom_z, 0., 0., -1.); | ||||
|  | @ -852,13 +865,15 @@ static void thick_lines_to_indexed_vertex_array( | |||
|             volume.push_geometry(a2.x, a2.y, middle_z, -xy_right_normal.x, -xy_right_normal.y, -xy_right_normal.z); | ||||
|             idx_a[RIGHT] = idx_last ++; | ||||
|             volume.push_geometry(a1.x, a1.y, middle_z, xy_right_normal.x, xy_right_normal.y, xy_right_normal.z); | ||||
|         } else { | ||||
|         } | ||||
|         else { | ||||
|             idx_a[BOTTOM] = idx_prev[BOTTOM]; | ||||
|         } | ||||
| 
 | ||||
|         if (ii == 0) { | ||||
|         if (is_first) { | ||||
|             // Start of the 1st line segment.
 | ||||
|             width_initial    = width; | ||||
|             bottom_z_initial = bottom_z; | ||||
|             memcpy(idx_initial, idx_a, sizeof(int) * 4); | ||||
|         } else { | ||||
|             // Continuing a previous segment.
 | ||||
|  | @ -866,43 +881,54 @@ static void thick_lines_to_indexed_vertex_array( | |||
| 			double v_dot    = dot(v_prev, v); | ||||
|             bool   sharp    = v_dot < 0.707; // sin(45 degrees)
 | ||||
|             if (sharp) { | ||||
|                 // Allocate new left / right points for the start of this segment as these points will receive their own normals to indicate a sharp turn.
 | ||||
|                 idx_a[RIGHT] = idx_last ++; | ||||
|                 volume.push_geometry(a1.x, a1.y, middle_z, xy_right_normal.x, xy_right_normal.y, xy_right_normal.z); | ||||
|                 idx_a[LEFT ] = idx_last ++; | ||||
|                 volume.push_geometry(a2.x, a2.y, middle_z, -xy_right_normal.x, -xy_right_normal.y, -xy_right_normal.z); | ||||
|                 if (!bottom_z_different) | ||||
|                 { | ||||
|                     // Allocate new left / right points for the start of this segment as these points will receive their own normals to indicate a sharp turn.
 | ||||
|                     idx_a[RIGHT] = idx_last++; | ||||
|                     volume.push_geometry(a1.x, a1.y, middle_z, xy_right_normal.x, xy_right_normal.y, xy_right_normal.z); | ||||
|                     idx_a[LEFT] = idx_last++; | ||||
|                     volume.push_geometry(a2.x, a2.y, middle_z, -xy_right_normal.x, -xy_right_normal.y, -xy_right_normal.z); | ||||
|                 } | ||||
|             } | ||||
|             if (v_dot > 0.9) { | ||||
|                 // The two successive segments are nearly collinear.
 | ||||
|                 idx_a[LEFT ] = idx_prev[LEFT]; | ||||
|                 idx_a[RIGHT] = idx_prev[RIGHT]; | ||||
|             } else if (! sharp) { | ||||
|                 // Create a sharp corner with an overshot and average the left / right normals.
 | ||||
|                 // At the crease angle of 45 degrees, the overshot at the corner will be less than (1-1/cos(PI/8)) = 8.2% over an arc.
 | ||||
|                 Pointf intersection; | ||||
|                 Geometry::ray_ray_intersection(b1_prev, v_prev, a1, v, intersection); | ||||
|                 a1 = intersection; | ||||
|                 a2 = 2. * a - intersection; | ||||
|                 assert(length(a1.vector_to(a)) < width); | ||||
|                 assert(length(a2.vector_to(a)) < width); | ||||
|                 float *n_left_prev  = volume.vertices_and_normals_interleaved.data() + idx_prev[LEFT ] * 6; | ||||
|                 float *p_left_prev  = n_left_prev  + 3; | ||||
|                 float *n_right_prev = volume.vertices_and_normals_interleaved.data() + idx_prev[RIGHT] * 6; | ||||
|                 float *p_right_prev = n_right_prev + 3; | ||||
|                 p_left_prev [0] = float(a2.x); | ||||
|                 p_left_prev [1] = float(a2.y); | ||||
|                 p_right_prev[0] = float(a1.x); | ||||
|                 p_right_prev[1] = float(a1.y); | ||||
|                 xy_right_normal.x += n_right_prev[0]; | ||||
|                 xy_right_normal.y += n_right_prev[1]; | ||||
|                 xy_right_normal.scale(1. / length(xy_right_normal)); | ||||
|                 n_left_prev [0] = float(-xy_right_normal.x); | ||||
|                 n_left_prev [1] = float(-xy_right_normal.y); | ||||
|                 n_right_prev[0] = float( xy_right_normal.x); | ||||
|                 n_right_prev[1] = float( xy_right_normal.y); | ||||
|                 idx_a[LEFT ] = idx_prev[LEFT ]; | ||||
|                 idx_a[RIGHT] = idx_prev[RIGHT]; | ||||
|             } else if (cross(v_prev, v) > 0.) { | ||||
|                 if (!bottom_z_different) | ||||
|                 { | ||||
|                     // The two successive segments are nearly collinear.
 | ||||
|                     idx_a[LEFT ] = idx_prev[LEFT]; | ||||
|                     idx_a[RIGHT] = idx_prev[RIGHT]; | ||||
|                 } | ||||
|             } | ||||
|             else if (!sharp) { | ||||
|                 if (!bottom_z_different) | ||||
|                 { | ||||
|                     // Create a sharp corner with an overshot and average the left / right normals.
 | ||||
|                     // At the crease angle of 45 degrees, the overshot at the corner will be less than (1-1/cos(PI/8)) = 8.2% over an arc.
 | ||||
|                     Pointf intersection; | ||||
|                     Geometry::ray_ray_intersection(b1_prev, v_prev, a1, v, intersection); | ||||
|                     a1 = intersection; | ||||
|                     a2 = 2. * a - intersection; | ||||
|                     assert(length(a1.vector_to(a)) < width); | ||||
|                     assert(length(a2.vector_to(a)) < width); | ||||
|                     float *n_left_prev  = volume.vertices_and_normals_interleaved.data() + idx_prev[LEFT ] * 6; | ||||
|                     float *p_left_prev  = n_left_prev  + 3; | ||||
|                     float *n_right_prev = volume.vertices_and_normals_interleaved.data() + idx_prev[RIGHT] * 6; | ||||
|                     float *p_right_prev = n_right_prev + 3; | ||||
|                     p_left_prev [0] = float(a2.x); | ||||
|                     p_left_prev [1] = float(a2.y); | ||||
|                     p_right_prev[0] = float(a1.x); | ||||
|                     p_right_prev[1] = float(a1.y); | ||||
|                     xy_right_normal.x += n_right_prev[0]; | ||||
|                     xy_right_normal.y += n_right_prev[1]; | ||||
|                     xy_right_normal.scale(1. / length(xy_right_normal)); | ||||
|                     n_left_prev [0] = float(-xy_right_normal.x); | ||||
|                     n_left_prev [1] = float(-xy_right_normal.y); | ||||
|                     n_right_prev[0] = float( xy_right_normal.x); | ||||
|                     n_right_prev[1] = float( xy_right_normal.y); | ||||
|                     idx_a[LEFT ] = idx_prev[LEFT ]; | ||||
|                     idx_a[RIGHT] = idx_prev[RIGHT]; | ||||
|                 } | ||||
|             } | ||||
|             else if (cross(v_prev, v) > 0.) { | ||||
|                 // Right turn. Fill in the right turn wedge.
 | ||||
|                 volume.push_triangle(idx_prev[RIGHT], idx_a   [RIGHT],  idx_prev[TOP]   ); | ||||
|                 volume.push_triangle(idx_prev[RIGHT], idx_prev[BOTTOM], idx_a   [RIGHT] ); | ||||
|  | @ -911,18 +937,21 @@ static void thick_lines_to_indexed_vertex_array( | |||
|                 volume.push_triangle(idx_prev[LEFT],  idx_prev[TOP],    idx_a   [LEFT]  ); | ||||
|                 volume.push_triangle(idx_prev[LEFT],  idx_a   [LEFT],   idx_prev[BOTTOM]); | ||||
|             } | ||||
|             if (ii == lines.size()) { | ||||
|                 if (! sharp) { | ||||
|                     // Closing a loop with smooth transition. Unify the closing left / right vertices.
 | ||||
|                     memcpy(volume.vertices_and_normals_interleaved.data() + idx_initial[LEFT ] * 6, volume.vertices_and_normals_interleaved.data() + idx_prev[LEFT ] * 6, sizeof(float) * 6); | ||||
|                     memcpy(volume.vertices_and_normals_interleaved.data() + idx_initial[RIGHT] * 6, volume.vertices_and_normals_interleaved.data() + idx_prev[RIGHT] * 6, sizeof(float) * 6); | ||||
|                     volume.vertices_and_normals_interleaved.erase(volume.vertices_and_normals_interleaved.end() - 12, volume.vertices_and_normals_interleaved.end()); | ||||
|                     // Replace the left / right vertex indices to point to the start of the loop. 
 | ||||
|                     for (size_t u = volume.quad_indices.size() - 16; u < volume.quad_indices.size(); ++ u) { | ||||
|                         if (volume.quad_indices[u] == idx_prev[LEFT]) | ||||
|                             volume.quad_indices[u] = idx_initial[LEFT]; | ||||
|                         else if (volume.quad_indices[u] == idx_prev[RIGHT]) | ||||
|                             volume.quad_indices[u] = idx_initial[RIGHT]; | ||||
|             if (is_closing) { | ||||
|                 if (!sharp) { | ||||
|                     if (!bottom_z_different) | ||||
|                     { | ||||
|                         // Closing a loop with smooth transition. Unify the closing left / right vertices.
 | ||||
|                         memcpy(volume.vertices_and_normals_interleaved.data() + idx_initial[LEFT ] * 6, volume.vertices_and_normals_interleaved.data() + idx_prev[LEFT ] * 6, sizeof(float) * 6); | ||||
|                         memcpy(volume.vertices_and_normals_interleaved.data() + idx_initial[RIGHT] * 6, volume.vertices_and_normals_interleaved.data() + idx_prev[RIGHT] * 6, sizeof(float) * 6); | ||||
|                         volume.vertices_and_normals_interleaved.erase(volume.vertices_and_normals_interleaved.end() - 12, volume.vertices_and_normals_interleaved.end()); | ||||
|                         // Replace the left / right vertex indices to point to the start of the loop. 
 | ||||
|                         for (size_t u = volume.quad_indices.size() - 16; u < volume.quad_indices.size(); ++ u) { | ||||
|                             if (volume.quad_indices[u] == idx_prev[LEFT]) | ||||
|                                 volume.quad_indices[u] = idx_initial[LEFT]; | ||||
|                             else if (volume.quad_indices[u] == idx_prev[RIGHT]) | ||||
|                                 volume.quad_indices[u] = idx_initial[RIGHT]; | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|                 // This is the last iteration, only required to solve the transition.
 | ||||
|  | @ -931,13 +960,14 @@ static void thick_lines_to_indexed_vertex_array( | |||
|         } | ||||
| 
 | ||||
|         // Only new allocate top / bottom vertices, if not closing a loop.
 | ||||
|         if (closed && ii + 1 == lines.size()) { | ||||
|         if (is_closing) { | ||||
|             idx_b[TOP] = idx_initial[TOP]; | ||||
|         } else { | ||||
|             idx_b[TOP] = idx_last ++; | ||||
|             volume.push_geometry(b.x, b.y, top_z   , 0., 0.,  1.); | ||||
|         } | ||||
|         if (closed && ii + 1 == lines.size() && width == width_initial) { | ||||
| 
 | ||||
|         if (is_closing && (width == width_initial) && (bottom_z == bottom_z_initial)) { | ||||
|             idx_b[BOTTOM] = idx_initial[BOTTOM]; | ||||
|         } else { | ||||
|             idx_b[BOTTOM] = idx_last ++; | ||||
|  | @ -949,22 +979,26 @@ static void thick_lines_to_indexed_vertex_array( | |||
|         idx_b[RIGHT ] = idx_last ++; | ||||
|         volume.push_geometry(b1.x, b1.y, middle_z, xy_right_normal.x, xy_right_normal.y, xy_right_normal.z); | ||||
| 
 | ||||
|         prev_line = line; | ||||
|         memcpy(idx_prev, idx_b, 4 * sizeof(int)); | ||||
|         bottom_z_prev = bottom_z; | ||||
|         b1_prev = b1; | ||||
|         b2_prev = b2; | ||||
|         v_prev  = v; | ||||
|         v_prev = v; | ||||
| 
 | ||||
|         if (bottom_z_different) | ||||
|         { | ||||
|             // Found a change of the layer thickness -> Add a cap at the beginning of this segment.
 | ||||
|             volume.push_quad(idx_a[BOTTOM], idx_a[RIGHT], idx_a[TOP], idx_a[LEFT]); | ||||
|         } | ||||
| 
 | ||||
|         if (! closed) { | ||||
|             // Terminate open paths with caps.
 | ||||
|             if (i == 0) | ||||
|             if (is_first && !bottom_z_different) | ||||
|                 volume.push_quad(idx_a[BOTTOM], idx_a[RIGHT], idx_a[TOP], idx_a[LEFT]); | ||||
|             // We don't use 'else' because both cases are true if we have only one line.
 | ||||
|             if (i + 1 == lines.size()) | ||||
|             if (is_last && !bottom_z_different) | ||||
|                 volume.push_quad(idx_b[BOTTOM], idx_b[LEFT], idx_b[TOP], idx_b[RIGHT]); | ||||
|         } | ||||
|          | ||||
| 
 | ||||
|         // Add quads for a straight hollow tube-like segment.
 | ||||
|         // bottom-right face
 | ||||
|         volume.push_quad(idx_a[BOTTOM], idx_b[BOTTOM], idx_b[RIGHT], idx_a[RIGHT]); | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Enrico Turri
						Enrico Turri