Blender V4.5
node_geo_curve_to_mesh.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
5#include "BKE_curves.hh"
6
9#include "BKE_instances.hh"
10
12#include "GEO_randomize.hh"
13
14#include "DNA_mesh_types.h"
15
16#include "node_geometry_util.hh"
17
19
21{
22 b.add_input<decl::Geometry>("Curve").supported_type(
23 {GeometryComponent::Type::Curve, GeometryComponent::Type::GreasePencil});
24 b.add_input<decl::Geometry>("Profile Curve")
25 .only_realized_data()
26 .supported_type(GeometryComponent::Type::Curve);
27 b.add_input<decl::Float>("Scale").default_value(1.0f).min(0.0f).field_on({0}).description(
28 "Scale of the profile at each point");
29 b.add_input<decl::Bool>("Fill Caps")
30 .description(
31 "If the profile spline is cyclic, fill the ends of the generated mesh with N-gons");
32 b.add_output<decl::Geometry>("Mesh").propagate_all();
33}
34
36 const GeometrySet &profile_set,
37 const fn::FieldContext &context,
38 const Field<float> &scale_field,
39 const bool fill_caps,
40 const AttributeFilter &attribute_filter)
41{
42 Mesh *mesh;
43 if (profile_set.has_curves()) {
44 const Curves *profile_curves = profile_set.get_curves();
45
46 FieldEvaluator evaluator{context, curves.points_num()};
47 evaluator.add(scale_field);
48 evaluator.evaluate();
49
50 const VArray<float> profile_scales = evaluator.get_evaluated<float>(0);
52 curves, profile_curves->geometry.wrap(), profile_scales, fill_caps, attribute_filter);
53 }
54 else {
55 mesh = bke::curve_to_wire_mesh(curves, attribute_filter);
56 }
58 return mesh;
59}
60
61static void grease_pencil_to_mesh(GeometrySet &geometry_set,
62 const GeometrySet &profile_set,
63 const Field<float> &scale_field,
64 const bool fill_caps,
65 const AttributeFilter &attribute_filter)
66{
67 using namespace blender::bke::greasepencil;
68
69 const GreasePencil &grease_pencil = *geometry_set.get_grease_pencil();
70 Array<Mesh *> mesh_by_layer(grease_pencil.layers().size(), nullptr);
71
72 for (const int layer_index : grease_pencil.layers().index_range()) {
73 const Drawing *drawing = grease_pencil.get_eval_drawing(grease_pencil.layer(layer_index));
74 if (drawing == nullptr) {
75 continue;
76 }
77 const bke::CurvesGeometry &curves = drawing->strokes();
79 grease_pencil, bke::AttrDomain::Point, layer_index};
80 mesh_by_layer[layer_index] = curve_to_mesh(
81 curves, profile_set, context, scale_field, fill_caps, attribute_filter);
82 }
83
84 if (mesh_by_layer.is_empty()) {
85 return;
86 }
87
88 bke::Instances *instances = new bke::Instances();
89 for (Mesh *mesh : mesh_by_layer) {
90 if (!mesh) {
91 /* Add an empty reference so the number of layers and instances match.
92 * This makes it easy to reconstruct the layers afterwards and keep their attributes.
93 * Although in this particular case we don't propagate the attributes. */
94 const int handle = instances->add_reference(bke::InstanceReference());
95 instances->add_instance(handle, float4x4::identity());
96 continue;
97 }
99 const int handle = instances->add_reference(bke::InstanceReference{temp_set});
100 instances->add_instance(handle, float4x4::identity());
101 }
102
103 bke::copy_attributes(geometry_set.get_grease_pencil()->attributes(),
106 attribute_filter,
107 instances->attributes_for_write());
108 InstancesComponent &dst_component = geometry_set.get_component_for_write<InstancesComponent>();
110 {GeometrySet::from_instances(dst_component.release()),
111 GeometrySet::from_instances(instances)},
112 attribute_filter);
113 dst_component.replace(new_instances.get_component_for_write<InstancesComponent>().release());
114 geometry_set.replace_grease_pencil(nullptr);
115}
116
118{
119 GeometrySet curve_set = params.extract_input<GeometrySet>("Curve");
120 GeometrySet profile_set = params.extract_input<GeometrySet>("Profile Curve");
121 const Field<float> scale_field = params.extract_input<Field<float>>("Scale");
122 const bool fill_caps = params.extract_input<bool>("Fill Caps");
123
125 const AttributeFilter &attribute_filter = params.get_attribute_filter("Mesh");
126
127 curve_set.modify_geometry_sets([&](GeometrySet &geometry_set) {
128 if (geometry_set.has_curves()) {
129 const Curves &curves = *geometry_set.get_curves();
130
133 curves.geometry.wrap(), profile_set, context, scale_field, fill_caps, attribute_filter);
134 if (mesh != nullptr) {
135 mesh->mat = static_cast<Material **>(MEM_dupallocN(curves.mat));
136 mesh->totcol = curves.totcol;
137 }
138 geometry_set.replace_mesh(mesh);
139 }
140 if (geometry_set.has_grease_pencil()) {
141 grease_pencil_to_mesh(geometry_set, profile_set, scale_field, fill_caps, attribute_filter);
142 }
144 });
145
146 params.set_output("Mesh", std::move(curve_set));
147}
148
149static void node_register()
150{
151 static blender::bke::bNodeType ntype;
152
153 geo_node_type_base(&ntype, "GeometryNodeCurveToMesh", GEO_NODE_CURVE_TO_MESH);
154 ntype.ui_name = "Curve to Mesh";
155 ntype.ui_description =
156 "Convert curves into a mesh, optionally with a custom profile shape defined by curves";
157 ntype.enum_name_legacy = "CURVE_TO_MESH";
159 ntype.declare = node_declare;
162}
164
165} // namespace blender::nodes::node_geo_curve_to_mesh_cc
Low-level operations for curves.
Low-level operations for grease pencil.
#define NODE_CLASS_GEOMETRY
Definition BKE_node.hh:447
#define GEO_NODE_CURVE_TO_MESH
#define NOD_REGISTER_NODE(REGISTER_FUNC)
bool is_empty() const
Definition BLI_array.hh:253
static void remember_deformed_positions_if_necessary(GeometrySet &geometry)
void replace(Instances *instances, GeometryOwnershipType ownership=GeometryOwnershipType::Owned)
int add_reference(const InstanceReference &reference)
Definition instances.cc:271
void add_instance(int instance_handle, const float4x4 &transform)
Definition instances.cc:203
bke::MutableAttributeAccessor attributes_for_write()
Definition instances.cc:68
const bke::CurvesGeometry & strokes() const
int add(GField field, GVArray *varray_ptr)
Definition field.cc:751
const GVArray & get_evaluated(const int field_index) const
Definition FN_field.hh:448
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
void * MEM_dupallocN(const void *vmemh)
Definition mallocn.cc:143
void node_register_type(bNodeType &ntype)
Definition node.cc:2748
void copy_attributes(const AttributeAccessor src_attributes, AttrDomain src_domain, AttrDomain dst_domain, const AttributeFilter &attribute_filter, MutableAttributeAccessor dst_attributes)
Mesh * curve_to_mesh_sweep(const CurvesGeometry &main, const CurvesGeometry &profile, const VArray< float > &scales, bool fill_caps, const bke::AttributeFilter &attribute_filter={})
Mesh * curve_to_wire_mesh(const CurvesGeometry &curve, const bke::AttributeFilter &attribute_filter={})
void debug_randomize_mesh_order(Mesh *mesh)
Definition randomize.cc:217
bke::GeometrySet join_geometries(Span< bke::GeometrySet > geometries, const bke::AttributeFilter &attribute_filter, const std::optional< Span< bke::GeometryComponent::Type > > &component_types_to_join=std::nullopt)
static void node_declare(NodeDeclarationBuilder &b)
static void node_geo_exec(GeoNodeExecParams params)
static void grease_pencil_to_mesh(GeometrySet &geometry_set, const GeometrySet &profile_set, const Field< float > &scale_field, const bool fill_caps, const AttributeFilter &attribute_filter)
static Mesh * curve_to_mesh(const bke::CurvesGeometry &curves, const GeometrySet &profile_set, const fn::FieldContext &context, const Field< float > &scale_field, const bool fill_caps, const AttributeFilter &attribute_filter)
void geo_node_type_base(blender::bke::bNodeType *ntype, std::string idname, const std::optional< int16_t > legacy_type)
CurvesGeometry geometry
GeometryComponent & get_component_for_write(GeometryComponent::Type component_type)
const GreasePencil * get_grease_pencil() const
void keep_only_during_modify(Span< GeometryComponent::Type > component_types)
const Curves * get_curves() const
void modify_geometry_sets(ForeachSubGeometryCallback callback)
void replace_mesh(Mesh *mesh, GeometryOwnershipType ownership=GeometryOwnershipType::Owned)
void replace_grease_pencil(GreasePencil *grease_pencil, GeometryOwnershipType ownership=GeometryOwnershipType::Owned)
Defines a node type.
Definition BKE_node.hh:226
std::string ui_description
Definition BKE_node.hh:232
NodeGeometryExecFunction geometry_node_execute
Definition BKE_node.hh:347
const char * enum_name_legacy
Definition BKE_node.hh:235
NodeDeclareFunction declare
Definition BKE_node.hh:355
static GeometrySet from_instances(Instances *instances, GeometryOwnershipType ownership=GeometryOwnershipType::Owned)
static GeometrySet from_mesh(Mesh *mesh, GeometryOwnershipType ownership=GeometryOwnershipType::Owned)