Blender V5.0
node_geo_points_to_vertices.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 "BLI_array_utils.hh"
6
8
9#include "BKE_customdata.hh"
10#include "BKE_mesh.hh"
11
13
14#include "node_geometry_util.hh"
15
17
19{
20 b.add_input<decl::Geometry>("Points")
21 .supported_type(GeometryComponent::Type::PointCloud)
22 .description("Points that are converted to vertices in a mesh");
23 b.add_input<decl::Bool>("Selection").default_value(true).field_on_all().hide_value();
24 b.add_output<decl::Geometry>("Mesh").propagate_all();
25}
26
27/* One improvement would be to move the attribute arrays directly to the mesh when possible. */
29 Field<bool> &selection_field,
30 const AttributeFilter &attribute_filter)
31{
32 const PointCloud *points = geometry_set.get_pointcloud();
33 if (points == nullptr) {
34 geometry_set.keep_only({GeometryComponent::Type::Edit});
35 return;
36 }
37 if (points->totpoint == 0) {
38 geometry_set.keep_only({GeometryComponent::Type::Edit});
39 return;
40 }
41
42 const bke::PointCloudFieldContext field_context{*points};
43 fn::FieldEvaluator selection_evaluator{field_context, points->totpoint};
44 selection_evaluator.add(selection_field);
45 selection_evaluator.evaluate();
46 const IndexMask selection = selection_evaluator.get_evaluated_as_mask(0);
47
49 geometry_set.gather_attributes_for_propagation({GeometryComponent::Type::PointCloud},
50 GeometryComponent::Type::Mesh,
51 false,
52 attribute_filter,
53 attributes);
54
55 Mesh *mesh;
56 if (selection.size() == points->totpoint) {
57 /* Create a mesh without positions so the attribute can be shared. */
58 mesh = BKE_mesh_new_nomain(0, 0, 0, 0);
59 CustomData_free_layer_named(&mesh->vert_data, "position");
60 mesh->verts_num = selection.size();
61 }
62 else {
63 mesh = BKE_mesh_new_nomain(selection.size(), 0, 0, 0);
64 }
65
66 const AttributeAccessor src_attributes = points->attributes();
67 MutableAttributeAccessor dst_attributes = mesh->attributes_for_write();
68
69 for (const int i : attributes.names.index_range()) {
70 const StringRef id = attributes.names[i];
71 const bke::AttrType data_type = attributes.kinds[i].data_type;
72 const GAttributeReader src = src_attributes.lookup(id);
73 if (selection.size() == points->totpoint && src.sharing_info && src.varray.is_span()) {
75 *src.sharing_info);
76 dst_attributes.add(id, AttrDomain::Point, data_type, init);
77 }
78 else {
80 id, AttrDomain::Point, data_type);
81 array_utils::gather(src.varray, selection, dst.span);
82 dst.finish();
83 }
84 }
85
86 mesh->tag_loose_edges_none();
87 mesh->tag_overlapping_none();
88
89 geometry_set.replace_mesh(mesh);
90 geometry_set.keep_only({GeometryComponent::Type::Mesh, GeometryComponent::Type::Edit});
91}
92
94{
95 GeometrySet geometry_set = params.extract_input<GeometrySet>("Points");
96 Field<bool> selection_field = params.extract_input<Field<bool>>("Selection");
97
98 geometry::foreach_real_geometry(geometry_set, [&](GeometrySet &geometry_set) {
100 geometry_set, selection_field, params.get_attribute_filter("Mesh"));
101 });
102
103 params.set_output("Mesh", std::move(geometry_set));
104}
105
106static void node_register()
107{
108 static blender::bke::bNodeType ntype;
109
110 geo_node_type_base(&ntype, "GeometryNodePointsToVertices", GEO_NODE_POINTS_TO_VERTICES);
111 ntype.ui_name = "Points to Vertices";
112 ntype.ui_description = "Generate a mesh vertex for each point cloud point";
113 ntype.enum_name_legacy = "POINTS_TO_VERTICES";
115 ntype.declare = node_declare;
118}
120
121} // namespace blender::nodes::node_geo_points_to_vertices_cc
CustomData interface, see also DNA_customdata_types.h.
bool CustomData_free_layer_named(CustomData *data, blender::StringRef name)
Mesh * BKE_mesh_new_nomain(int verts_num, int edges_num, int faces_num, int corners_num)
#define NODE_CLASS_GEOMETRY
Definition BKE_node.hh:461
#define GEO_NODE_POINTS_TO_VERTICES
#define NOD_REGISTER_NODE(REGISTER_FUNC)
void init()
AttributeSet attributes
const void * data() const
GAttributeReader lookup(const StringRef attribute_id) const
bool add(const StringRef attribute_id, const AttrDomain domain, const AttrType data_type, const AttributeInit &initializer)
GSpanAttributeWriter lookup_or_add_for_write_only_span(StringRef attribute_id, AttrDomain domain, AttrType data_type)
int add(GField field, GVArray *varray_ptr)
Definition field.cc:751
IndexMask get_evaluated_as_mask(int field_index)
Definition field.cc:804
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
void gather(const GVArray &src, const IndexMask &indices, GMutableSpan dst, int64_t grain_size=4096)
void node_register_type(bNodeType &ntype)
Definition node.cc:2416
void foreach_real_geometry(bke::GeometrySet &geometry, FunctionRef< void(bke::GeometrySet &geometry_set)> fn)
static void geometry_set_points_to_vertices(GeometrySet &geometry_set, Field< bool > &selection_field, const AttributeFilter &attribute_filter)
static void node_declare(NodeDeclarationBuilder &b)
void geo_node_type_base(blender::bke::bNodeType *ntype, std::string idname, const std::optional< int16_t > legacy_type)
static void init(bNodeTree *, bNode *node)
CustomData vert_data
int verts_num
const ImplicitSharingInfo * sharing_info
Vector< AttributeDomainAndType, 16 > kinds
void keep_only(Span< GeometryComponent::Type > component_types)
void gather_attributes_for_propagation(Span< GeometryComponent::Type > component_types, GeometryComponent::Type dst_component_type, bool include_instances, const AttributeFilter &attribute_filter, GatheredAttributes &r_attributes) const
const PointCloud * get_pointcloud() const
void replace_mesh(Mesh *mesh, GeometryOwnershipType ownership=GeometryOwnershipType::Owned)
Defines a node type.
Definition BKE_node.hh:238
std::string ui_description
Definition BKE_node.hh:244
NodeGeometryExecFunction geometry_node_execute
Definition BKE_node.hh:354
const char * enum_name_legacy
Definition BKE_node.hh:247
NodeDeclareFunction declare
Definition BKE_node.hh:362
i
Definition text_draw.cc:230