diff options
-rw-r--r-- | source/blender/blenkernel/intern/curve_to_mesh_convert.cc | 9 | ||||
-rw-r--r-- | source/blender/nodes/geometry/nodes/node_geo_dual_mesh.cc | 25 |
2 files changed, 24 insertions, 10 deletions
diff --git a/source/blender/blenkernel/intern/curve_to_mesh_convert.cc b/source/blender/blenkernel/intern/curve_to_mesh_convert.cc index 51edf4a6591..e62733e36ef 100644 --- a/source/blender/blenkernel/intern/curve_to_mesh_convert.cc +++ b/source/blender/blenkernel/intern/curve_to_mesh_convert.cc @@ -172,7 +172,8 @@ static void spline_extrude_to_mesh_data(const ResultInfo &info, } } - if (fill_caps && profile.is_cyclic()) { + const bool has_caps = fill_caps && profile.is_cyclic() && !spline.is_cyclic(); + if (has_caps) { const int poly_size = info.spline_edge_len * info.profile_edge_len; const int cap_loop_offset = info.loop_offset + poly_size * 4; const int cap_poly_offset = info.poly_offset + poly_size; @@ -256,7 +257,8 @@ static inline int spline_extrude_loop_size(const Spline &curve, const bool fill_caps) { const int tube = curve.evaluated_edges_size() * profile.evaluated_edges_size() * 4; - const int caps = (fill_caps && profile.is_cyclic()) ? profile.evaluated_edges_size() * 2 : 0; + const bool has_caps = fill_caps && profile.is_cyclic() && !curve.is_cyclic(); + const int caps = has_caps ? profile.evaluated_edges_size() * 2 : 0; return tube + caps; } @@ -265,7 +267,8 @@ static inline int spline_extrude_poly_size(const Spline &curve, const bool fill_caps) { const int tube = curve.evaluated_edges_size() * profile.evaluated_edges_size(); - const int caps = (fill_caps && profile.is_cyclic()) ? 2 : 0; + const bool has_caps = fill_caps && profile.is_cyclic() && !curve.is_cyclic(); + const int caps = has_caps ? 2 : 0; return tube + caps; } diff --git a/source/blender/nodes/geometry/nodes/node_geo_dual_mesh.cc b/source/blender/nodes/geometry/nodes/node_geo_dual_mesh.cc index a526f4f9e65..f50c2ed5322 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_dual_mesh.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_dual_mesh.cc @@ -272,7 +272,7 @@ static void create_vertex_poly_map(const Mesh &mesh, * boundary vertex, the first and last polygon have a boundary edge connected to the vertex. The * `r_shared_edges` array at index i is set to the index of the shared edge between the i-th and * `(i+1)-th` sorted polygon. Similarly the `r_sorted_corners` array at index i is set to the - * corner in the i-th sorted polygon. + * corner in the i-th sorted polygon. If the polygons couldn't be sorted, `false` is returned. * * How the faces are sorted (see diagrams below): * (For this explanation we'll assume all faces are oriented clockwise) @@ -321,7 +321,7 @@ static void create_vertex_poly_map(const Mesh &mesh, * - Finally if we are in the normal case we also need to add the last "shared edge" to close the * loop. */ -static void sort_vertex_polys(const Mesh &mesh, +static bool sort_vertex_polys(const Mesh &mesh, const int vertex_index, const bool boundary_vertex, const Span<EdgeType> edge_types, @@ -330,7 +330,7 @@ static void sort_vertex_polys(const Mesh &mesh, MutableSpan<int> r_sorted_corners) { if (connected_polygons.size() <= 2 && (!boundary_vertex || connected_polygons.size() == 0)) { - return; + return true; } /* For each polygon store the two corners whose edge contains the vertex. */ @@ -434,8 +434,11 @@ static void sort_vertex_polys(const Mesh &mesh, break; } } - - BLI_assert(j != connected_polygons.size()); + if (j == connected_polygons.size()) { + /* The vertex is not manifold because the polygons around the vertex don't form a loop, and + * hence can't be sorted. */ + return false; + } std::swap(connected_polygons[i + 1], connected_polygons[j]); std::swap(poly_vertex_corners[i + 1], poly_vertex_corners[j]); @@ -445,6 +448,7 @@ static void sort_vertex_polys(const Mesh &mesh, /* Shared edge between first and last polygon. */ r_shared_edges.last() = shared_edge_i; } + return true; } /** @@ -637,18 +641,25 @@ static void calc_dual_mesh(GeometrySet &geometry_set, } MutableSpan<int> loop_indices = vertex_poly_indices[i]; Array<int> sorted_corners(loop_indices.size()); + bool vertex_ok = true; if (vertex_types[i] == VertexType::Normal) { Array<int> shared_edges(loop_indices.size()); - sort_vertex_polys( + vertex_ok = sort_vertex_polys( mesh_in, i, false, edge_types, loop_indices, shared_edges, sorted_corners); vertex_shared_edges[i] = shared_edges; } else { Array<int> shared_edges(loop_indices.size() - 1); - sort_vertex_polys( + vertex_ok = sort_vertex_polys( mesh_in, i, true, edge_types, loop_indices, shared_edges, sorted_corners); vertex_shared_edges[i] = shared_edges; } + if (!vertex_ok) { + /* The sorting failed which means that the vertex is non-manifold and should be ignored + * further on. */ + vertex_types[i] = VertexType::NonManifold; + continue; + } vertex_corners[i] = sorted_corners; } }); |