From bc2f4dd8b408eee35353c18a44ce0dc5b51394a9 Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Mon, 25 Oct 2021 09:10:44 -0500 Subject: Geometry Nodes: Add "Fill Caps" option to curve to mesh node This adds an option to fill the ends of the generated mesh for each spline combination with an N-gon. The resulting mesh is manifold, so it can be used for operations like Boolean. Differential Revision: https://developer.blender.org/D12982 --- source/blender/blenkernel/BKE_curve_to_mesh.hh | 2 +- .../blenkernel/intern/curve_to_mesh_convert.cc | 62 ++++++++++++++++++---- 2 files changed, 53 insertions(+), 11 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/BKE_curve_to_mesh.hh b/source/blender/blenkernel/BKE_curve_to_mesh.hh index 87bec6203a9..fb077425336 100644 --- a/source/blender/blenkernel/BKE_curve_to_mesh.hh +++ b/source/blender/blenkernel/BKE_curve_to_mesh.hh @@ -25,7 +25,7 @@ struct CurveEval; namespace blender::bke { -Mesh *curve_to_mesh_sweep(const CurveEval &curve, const CurveEval &profile); +Mesh *curve_to_mesh_sweep(const CurveEval &curve, const CurveEval &profile, bool fill_caps); Mesh *curve_to_wire_mesh(const CurveEval &curve); } // namespace blender::bke diff --git a/source/blender/blenkernel/intern/curve_to_mesh_convert.cc b/source/blender/blenkernel/intern/curve_to_mesh_convert.cc index 5f2f945192c..b3957e57920 100644 --- a/source/blender/blenkernel/intern/curve_to_mesh_convert.cc +++ b/source/blender/blenkernel/intern/curve_to_mesh_convert.cc @@ -88,6 +88,7 @@ static void mark_edges_sharp(MutableSpan edges) } static void spline_extrude_to_mesh_data(const ResultInfo &info, + const bool fill_caps, MutableSpan r_verts, MutableSpan r_edges, MutableSpan r_loops, @@ -180,6 +181,36 @@ static void spline_extrude_to_mesh_data(const ResultInfo &info, } } + if (fill_caps && profile.is_cyclic()) { + 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; + + MPoly &poly_start = r_polys[cap_poly_offset]; + poly_start.loopstart = cap_loop_offset; + poly_start.totloop = info.profile_edge_len; + MPoly &poly_end = r_polys[cap_poly_offset + 1]; + poly_end.loopstart = cap_loop_offset + info.profile_edge_len; + poly_end.totloop = info.profile_edge_len; + + const int last_ring_index = info.spline_vert_len - 1; + const int last_ring_vert_offset = info.vert_offset + info.profile_vert_len * last_ring_index; + const int last_ring_edge_offset = profile_edges_start + + info.profile_edge_len * last_ring_index; + + for (const int i : IndexRange(info.profile_edge_len)) { + MLoop &loop_start = r_loops[cap_loop_offset + i]; + loop_start.v = info.vert_offset + i; + loop_start.e = profile_edges_start + i; + MLoop &loop_end = r_loops[cap_loop_offset + info.profile_edge_len + i]; + loop_end.v = last_ring_vert_offset + i; + loop_end.e = last_ring_edge_offset + i; + } + + mark_edges_sharp(r_edges.slice(profile_edges_start, info.profile_edge_len)); + mark_edges_sharp(r_edges.slice(last_ring_edge_offset, info.profile_edge_len)); + } + /* Calculate the positions of each profile ring profile along the spline. */ Span positions = spline.evaluated_positions(); Span tangents = spline.evaluated_tangents(); @@ -226,14 +257,22 @@ static inline int spline_extrude_edge_size(const Spline &curve, const Spline &pr curve.evaluated_edges_size() * profile.evaluated_points_size(); } -static inline int spline_extrude_loop_size(const Spline &curve, const Spline &profile) +static inline int spline_extrude_loop_size(const Spline &curve, + const Spline &profile, + const bool fill_caps) { - return curve.evaluated_edges_size() * profile.evaluated_edges_size() * 4; + 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; + return tube + caps; } -static inline int spline_extrude_poly_size(const Spline &curve, const Spline &profile) +static inline int spline_extrude_poly_size(const Spline &curve, + const Spline &profile, + const bool fill_caps) { - return curve.evaluated_edges_size() * profile.evaluated_edges_size(); + const int tube = curve.evaluated_edges_size() * profile.evaluated_edges_size(); + const int caps = (fill_caps && profile.is_cyclic()) ? 2 : 0; + return tube + caps; } struct ResultOffsets { @@ -242,7 +281,9 @@ struct ResultOffsets { Array loop; Array poly; }; -static ResultOffsets calculate_result_offsets(Span profiles, Span curves) +static ResultOffsets calculate_result_offsets(Span profiles, + Span curves, + const bool fill_caps) { const int total = profiles.size() * curves.size(); Array vert(total + 1); @@ -263,8 +304,8 @@ static ResultOffsets calculate_result_offsets(Span profiles, Span profiles = profile.splines(); Span curves = curve.splines(); - const ResultOffsets offsets = calculate_result_offsets(profiles, curves); + const ResultOffsets offsets = calculate_result_offsets(profiles, curves, fill_caps); if (offsets.vert.last() == 0) { return nullptr; } @@ -696,6 +737,7 @@ Mesh *curve_to_mesh_sweep(const CurveEval &curve, const CurveEval &profile) }; spline_extrude_to_mesh_data(info, + fill_caps, {mesh->mvert, mesh->totvert}, {mesh->medge, mesh->totedge}, {mesh->mloop, mesh->totloop}, @@ -733,7 +775,7 @@ static CurveEval get_curve_single_vert() Mesh *curve_to_wire_mesh(const CurveEval &curve) { static const CurveEval vert_curve = get_curve_single_vert(); - return curve_to_mesh_sweep(curve, vert_curve); + return curve_to_mesh_sweep(curve, vert_curve, false); } } // namespace blender::bke -- cgit v1.2.3